Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkCanvas.cpp
1
2 /*
3  * Copyright 2008 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9
10 #include "SkCanvas.h"
11 #include "SkBitmapDevice.h"
12 #include "SkBounder.h"
13 #include "SkDeviceImageFilterProxy.h"
14 #include "SkDraw.h"
15 #include "SkDrawFilter.h"
16 #include "SkDrawLooper.h"
17 #include "SkMetaData.h"
18 #include "SkPathOps.h"
19 #include "SkPicture.h"
20 #include "SkRasterClip.h"
21 #include "SkRRect.h"
22 #include "SkSmallAllocator.h"
23 #include "SkSurface_Base.h"
24 #include "SkTemplates.h"
25 #include "SkTextFormatParams.h"
26 #include "SkTLazy.h"
27 #include "SkUtils.h"
28
29 #if SK_SUPPORT_GPU
30 #include "GrRenderTarget.h"
31 #endif
32
33 // experimental for faster tiled drawing...
34 //#define SK_ENABLE_CLIP_QUICKREJECT
35
36 //#define SK_TRACE_SAVERESTORE
37
38 #ifdef SK_TRACE_SAVERESTORE
39     static int gLayerCounter;
40     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
41     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
42
43     static int gRecCounter;
44     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
45     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
46
47     static int gCanvasCounter;
48     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
49     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
50 #else
51     #define inc_layer()
52     #define dec_layer()
53     #define inc_rec()
54     #define dec_rec()
55     #define inc_canvas()
56     #define dec_canvas()
57 #endif
58
59 #ifdef SK_DEBUG
60 #include "SkPixelRef.h"
61
62 /*
63  *  Some pixelref subclasses can support being "locked" from another thread
64  *  during the lock-scope of skia calling them. In these instances, this balance
65  *  check will fail, but may not be indicative of a problem, so we allow a build
66  *  flag to disable this check.
67  *
68  *  Potentially another fix would be to have a (debug-only) virtual or flag on
69  *  pixelref, which could tell us at runtime if this check is valid. That would
70  *  eliminate the need for this heavy-handed build check.
71  */
72 #ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
73 class AutoCheckLockCountBalance {
74 public:
75     AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
76 };
77 #else
78 class AutoCheckLockCountBalance {
79 public:
80     AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
81         fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
82     }
83     ~AutoCheckLockCountBalance() {
84         const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
85         SkASSERT(count == fLockCount);
86     }
87
88 private:
89     const SkPixelRef* fPixelRef;
90     int               fLockCount;
91 };
92 #endif
93
94 #define CHECK_LOCKCOUNT_BALANCE(bitmap)  AutoCheckLockCountBalance clcb(bitmap)
95
96 #else
97     #define CHECK_LOCKCOUNT_BALANCE(bitmap)
98 #endif
99
100 typedef SkTLazy<SkPaint> SkLazyPaint;
101
102 void SkCanvas::predrawNotify() {
103     if (fSurfaceBase) {
104         fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
105     }
106 }
107
108 ///////////////////////////////////////////////////////////////////////////////
109
110 /*  This is the record we keep for each SkBaseDevice that the user installs.
111     The clip/matrix/proc are fields that reflect the top of the save/restore
112     stack. Whenever the canvas changes, it marks a dirty flag, and then before
113     these are used (assuming we're not on a layer) we rebuild these cache
114     values: they reflect the top of the save stack, but translated and clipped
115     by the device's XY offset and bitmap-bounds.
116 */
117 struct DeviceCM {
118     DeviceCM*           fNext;
119     SkBaseDevice*       fDevice;
120     SkRasterClip        fClip;
121     const SkMatrix*     fMatrix;
122     SkPaint*            fPaint; // may be null (in the future)
123
124     DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
125             : fNext(NULL) {
126         if (NULL != device) {
127             device->ref();
128             device->onAttachToCanvas(canvas);
129         }
130         fDevice = device;
131         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
132     }
133
134     ~DeviceCM() {
135         if (NULL != fDevice) {
136             fDevice->onDetachFromCanvas();
137             fDevice->unref();
138         }
139         SkDELETE(fPaint);
140     }
141
142     void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
143                   const SkClipStack& clipStack, SkRasterClip* updateClip) {
144         int x = fDevice->getOrigin().x();
145         int y = fDevice->getOrigin().y();
146         int width = fDevice->width();
147         int height = fDevice->height();
148
149         if ((x | y) == 0) {
150             fMatrix = &totalMatrix;
151             fClip = totalClip;
152         } else {
153             fMatrixStorage = totalMatrix;
154             fMatrixStorage.postTranslate(SkIntToScalar(-x),
155                                          SkIntToScalar(-y));
156             fMatrix = &fMatrixStorage;
157
158             totalClip.translate(-x, -y, &fClip);
159         }
160
161         fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
162
163         // intersect clip, but don't translate it (yet)
164
165         if (updateClip) {
166             updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
167                            SkRegion::kDifference_Op);
168         }
169
170         fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
171
172 #ifdef SK_DEBUG
173         if (!fClip.isEmpty()) {
174             SkIRect deviceR;
175             deviceR.set(0, 0, width, height);
176             SkASSERT(deviceR.contains(fClip.getBounds()));
177         }
178 #endif
179     }
180
181 private:
182     SkMatrix    fMatrixStorage;
183 };
184
185 /*  This is the record we keep for each save/restore level in the stack.
186     Since a level optionally copies the matrix and/or stack, we have pointers
187     for these fields. If the value is copied for this level, the copy is
188     stored in the ...Storage field, and the pointer points to that. If the
189     value is not copied for this level, we ignore ...Storage, and just point
190     at the corresponding value in the previous level in the stack.
191 */
192 class SkCanvas::MCRec {
193 public:
194     int             fFlags;
195     SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
196     SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
197     SkDrawFilter*   fFilter;        // the current filter (or null)
198
199     DeviceCM*   fLayer;
200     /*  If there are any layers in the stack, this points to the top-most
201         one that is at or below this level in the stack (so we know what
202         bitmap/device to draw into from this level. This value is NOT
203         reference counted, since the real owner is either our fLayer field,
204         or a previous one in a lower level.)
205     */
206     DeviceCM*   fTopLayer;
207
208     MCRec(const MCRec* prev, int flags) : fFlags(flags) {
209         if (NULL != prev) {
210             if (flags & SkCanvas::kMatrix_SaveFlag) {
211                 fMatrixStorage = *prev->fMatrix;
212                 fMatrix = &fMatrixStorage;
213             } else {
214                 fMatrix = prev->fMatrix;
215             }
216
217             if (flags & SkCanvas::kClip_SaveFlag) {
218                 fRasterClipStorage = *prev->fRasterClip;
219                 fRasterClip = &fRasterClipStorage;
220             } else {
221                 fRasterClip = prev->fRasterClip;
222             }
223
224             fFilter = prev->fFilter;
225             SkSafeRef(fFilter);
226
227             fTopLayer = prev->fTopLayer;
228         } else {   // no prev
229             fMatrixStorage.reset();
230
231             fMatrix     = &fMatrixStorage;
232             fRasterClip = &fRasterClipStorage;
233             fFilter     = NULL;
234             fTopLayer   = NULL;
235         }
236         fLayer = NULL;
237
238         // don't bother initializing fNext
239         inc_rec();
240     }
241     ~MCRec() {
242         SkSafeUnref(fFilter);
243         SkDELETE(fLayer);
244         dec_rec();
245     }
246
247 private:
248     SkMatrix        fMatrixStorage;
249     SkRasterClip    fRasterClipStorage;
250 };
251
252 class SkDrawIter : public SkDraw {
253 public:
254     SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
255         canvas = canvas->canvasForDrawIter();
256         fCanvas = canvas;
257         canvas->updateDeviceCMCache();
258
259         fClipStack = &canvas->fClipStack;
260         fBounder = canvas->getBounder();
261         fCurrLayer = canvas->fMCRec->fTopLayer;
262         fSkipEmptyClips = skipEmptyClips;
263     }
264
265     bool next() {
266         // skip over recs with empty clips
267         if (fSkipEmptyClips) {
268             while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
269                 fCurrLayer = fCurrLayer->fNext;
270             }
271         }
272
273         const DeviceCM* rec = fCurrLayer;
274         if (rec && rec->fDevice) {
275
276             fMatrix = rec->fMatrix;
277             fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
278             fRC     = &rec->fClip;
279             fDevice = rec->fDevice;
280             fBitmap = &fDevice->accessBitmap(true);
281             fPaint  = rec->fPaint;
282             SkDEBUGCODE(this->validate();)
283
284             fCurrLayer = rec->fNext;
285             if (fBounder) {
286                 fBounder->setClip(fClip);
287             }
288             // fCurrLayer may be NULL now
289
290             return true;
291         }
292         return false;
293     }
294
295     SkBaseDevice* getDevice() const { return fDevice; }
296     int getX() const { return fDevice->getOrigin().x(); }
297     int getY() const { return fDevice->getOrigin().y(); }
298     const SkMatrix& getMatrix() const { return *fMatrix; }
299     const SkRegion& getClip() const { return *fClip; }
300     const SkPaint* getPaint() const { return fPaint; }
301
302 private:
303     SkCanvas*       fCanvas;
304     const DeviceCM* fCurrLayer;
305     const SkPaint*  fPaint;     // May be null.
306     SkBool8         fSkipEmptyClips;
307
308     typedef SkDraw INHERITED;
309 };
310
311 /////////////////////////////////////////////////////////////////////////////
312
313 class AutoDrawLooper {
314 public:
315     AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
316                    bool skipLayerForImageFilter = false,
317                    const SkRect* bounds = NULL) : fOrigPaint(paint) {
318         fCanvas = canvas;
319         fFilter = canvas->getDrawFilter();
320         fPaint = NULL;
321         fSaveCount = canvas->getSaveCount();
322         fDoClearImageFilter = false;
323         fDone = false;
324
325         if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
326             SkPaint tmp;
327             tmp.setImageFilter(fOrigPaint.getImageFilter());
328             (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
329                                             true, SkCanvas::kFullLayer_SaveLayerStrategy);
330             // we'll clear the imageFilter for the actual draws in next(), so
331             // it will only be applied during the restore().
332             fDoClearImageFilter = true;
333         }
334
335         if (SkDrawLooper* looper = paint.getLooper()) {
336             void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
337                     looper->contextSize());
338             fLooperContext = looper->createContext(canvas, buffer);
339             fIsSimple = false;
340         } else {
341             fLooperContext = NULL;
342             // can we be marked as simple?
343             fIsSimple = !fFilter && !fDoClearImageFilter;
344         }
345     }
346
347     ~AutoDrawLooper() {
348         if (fDoClearImageFilter) {
349             fCanvas->internalRestore();
350         }
351         SkASSERT(fCanvas->getSaveCount() == fSaveCount);
352     }
353
354     const SkPaint& paint() const {
355         SkASSERT(fPaint);
356         return *fPaint;
357     }
358
359     bool next(SkDrawFilter::Type drawType) {
360         if (fDone) {
361             return false;
362         } else if (fIsSimple) {
363             fDone = true;
364             fPaint = &fOrigPaint;
365             return !fPaint->nothingToDraw();
366         } else {
367             return this->doNext(drawType);
368         }
369     }
370
371 private:
372     SkLazyPaint     fLazyPaint;
373     SkCanvas*       fCanvas;
374     const SkPaint&  fOrigPaint;
375     SkDrawFilter*   fFilter;
376     const SkPaint*  fPaint;
377     int             fSaveCount;
378     bool            fDoClearImageFilter;
379     bool            fDone;
380     bool            fIsSimple;
381     SkDrawLooper::Context* fLooperContext;
382     SkSmallAllocator<1, 32> fLooperContextAllocator;
383
384     bool doNext(SkDrawFilter::Type drawType);
385 };
386
387 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
388     fPaint = NULL;
389     SkASSERT(!fIsSimple);
390     SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
391
392     SkPaint* paint = fLazyPaint.set(fOrigPaint);
393
394     if (fDoClearImageFilter) {
395         paint->setImageFilter(NULL);
396     }
397
398     if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
399         fDone = true;
400         return false;
401     }
402     if (fFilter) {
403         if (!fFilter->filter(paint, drawType)) {
404             fDone = true;
405             return false;
406         }
407         if (NULL == fLooperContext) {
408             // no looper means we only draw once
409             fDone = true;
410         }
411     }
412     fPaint = paint;
413
414     // if we only came in here for the imagefilter, mark us as done
415     if (!fLooperContext && !fFilter) {
416         fDone = true;
417     }
418
419     // call this after any possible paint modifiers
420     if (fPaint->nothingToDraw()) {
421         fPaint = NULL;
422         return false;
423     }
424     return true;
425 }
426
427 /*  Stack helper for managing a SkBounder. In the destructor, if we were
428     given a bounder, we call its commit() method, signifying that we are
429     done accumulating bounds for that draw.
430 */
431 class SkAutoBounderCommit {
432 public:
433     SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
434     ~SkAutoBounderCommit() {
435         if (NULL != fBounder) {
436             fBounder->commit();
437         }
438     }
439 private:
440     SkBounder*  fBounder;
441 };
442 #define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit)
443
444 #include "SkColorPriv.h"
445
446 ////////// macros to place around the internal draw calls //////////////////
447
448 #define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
449     this->predrawNotify();                                          \
450     AutoDrawLooper  looper(this, paint, true);                      \
451     while (looper.next(type)) {                                     \
452         SkAutoBounderCommit ac(fBounder);                           \
453         SkDrawIter          iter(this);
454
455 #define LOOPER_BEGIN(paint, type, bounds)                           \
456     this->predrawNotify();                                          \
457     AutoDrawLooper  looper(this, paint, false, bounds);             \
458     while (looper.next(type)) {                                     \
459         SkAutoBounderCommit ac(fBounder);                           \
460         SkDrawIter          iter(this);
461
462 #define LOOPER_END    }
463
464 ////////////////////////////////////////////////////////////////////////////
465
466 SkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
467     fBounder = NULL;
468     fCachedLocalClipBounds.setEmpty();
469     fCachedLocalClipBoundsDirty = true;
470     fAllowSoftClip = true;
471     fAllowSimplifyClip = false;
472     fDeviceCMDirty = false;
473     fSaveLayerCount = 0;
474     fCullCount = 0;
475     fMetaData = NULL;
476
477     fMCRec = (MCRec*)fMCStack.push_back();
478     new (fMCRec) MCRec(NULL, 0);
479
480     fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
481     fMCRec->fTopLayer = fMCRec->fLayer;
482
483     fSurfaceBase = NULL;
484
485     return this->setRootDevice(device);
486 }
487
488 SkCanvas::SkCanvas()
489     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
490 {
491     inc_canvas();
492
493     this->init(NULL);
494 }
495
496 SkCanvas::SkCanvas(int width, int height)
497     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
498 {
499     inc_canvas();
500
501     SkBitmap bitmap;
502     bitmap.setConfig(SkImageInfo::MakeUnknown(width, height));
503     this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
504 }
505
506 SkCanvas::SkCanvas(SkBaseDevice* device)
507     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
508 {
509     inc_canvas();
510
511     this->init(device);
512 }
513
514 SkCanvas::SkCanvas(const SkBitmap& bitmap)
515     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
516 {
517     inc_canvas();
518
519     this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
520 }
521
522 SkCanvas::~SkCanvas() {
523     // free up the contents of our deque
524     this->restoreToCount(1);    // restore everything but the last
525     SkASSERT(0 == fSaveLayerCount);
526
527     this->internalRestore();    // restore the last, since we're going away
528
529     SkSafeUnref(fBounder);
530     SkDELETE(fMetaData);
531
532     dec_canvas();
533 }
534
535 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
536     SkRefCnt_SafeAssign(fBounder, bounder);
537     return bounder;
538 }
539
540 SkDrawFilter* SkCanvas::getDrawFilter() const {
541     return fMCRec->fFilter;
542 }
543
544 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
545     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
546     return filter;
547 }
548
549 SkMetaData& SkCanvas::getMetaData() {
550     // metadata users are rare, so we lazily allocate it. If that changes we
551     // can decide to just make it a field in the device (rather than a ptr)
552     if (NULL == fMetaData) {
553         fMetaData = new SkMetaData;
554     }
555     return *fMetaData;
556 }
557
558 ///////////////////////////////////////////////////////////////////////////////
559
560 void SkCanvas::flush() {
561     SkBaseDevice* device = this->getDevice();
562     if (device) {
563         device->flush();
564     }
565 }
566
567 SkISize SkCanvas::getTopLayerSize() const {
568     SkBaseDevice* d = this->getTopDevice();
569     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
570 }
571
572 SkIPoint SkCanvas::getTopLayerOrigin() const {
573     SkBaseDevice* d = this->getTopDevice();
574     return d ? d->getOrigin() : SkIPoint::Make(0, 0);
575 }
576
577 SkISize SkCanvas::getBaseLayerSize() const {
578     SkBaseDevice* d = this->getDevice();
579     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
580 }
581
582 SkBaseDevice* SkCanvas::getDevice() const {
583     // return root device
584     MCRec* rec = (MCRec*) fMCStack.front();
585     SkASSERT(rec && rec->fLayer);
586     return rec->fLayer->fDevice;
587 }
588
589 SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
590     if (updateMatrixClip) {
591         const_cast<SkCanvas*>(this)->updateDeviceCMCache();
592     }
593     return fMCRec->fTopLayer->fDevice;
594 }
595
596 SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
597     // return root device
598     SkDeque::F2BIter iter(fMCStack);
599     MCRec*           rec = (MCRec*)iter.next();
600     SkASSERT(rec && rec->fLayer);
601     SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
602
603     if (rootDevice == device) {
604         return device;
605     }
606
607     if (device) {
608         device->onAttachToCanvas(this);
609     }
610     if (rootDevice) {
611         rootDevice->onDetachFromCanvas();
612     }
613
614     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
615     rootDevice = device;
616
617     fDeviceCMDirty = true;
618
619     /*  Now we update our initial region to have the bounds of the new device,
620         and then intersect all of the clips in our stack with these bounds,
621         to ensure that we can't draw outside of the device's bounds (and trash
622                                                                      memory).
623
624     NOTE: this is only a partial-fix, since if the new device is larger than
625         the previous one, we don't know how to "enlarge" the clips in our stack,
626         so drawing may be artificially restricted. Without keeping a history of
627         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
628         reconstruct the correct clips, so this approximation will have to do.
629         The caller really needs to restore() back to the base if they want to
630         accurately take advantage of the new device bounds.
631     */
632
633     SkIRect bounds;
634     if (device) {
635         bounds.set(0, 0, device->width(), device->height());
636     } else {
637         bounds.setEmpty();
638     }
639     // now jam our 1st clip to be bounds, and intersect the rest with that
640     rec->fRasterClip->setRect(bounds);
641     while ((rec = (MCRec*)iter.next()) != NULL) {
642         (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
643     }
644
645     return device;
646 }
647
648 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
649     if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
650         return false;
651     }
652
653     bool weAllocated = false;
654     if (NULL == bitmap->pixelRef()) {
655         if (!bitmap->allocPixels()) {
656             return false;
657         }
658         weAllocated = true;
659     }
660
661     SkBitmap bm(*bitmap);
662     bm.lockPixels();
663     if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
664         return true;
665     }
666
667     if (weAllocated) {
668         bitmap->setPixelRef(NULL);
669     }
670     return false;
671 }
672
673 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
674     SkIRect r = srcRect;
675     const SkISize size = this->getBaseLayerSize();
676     if (!r.intersect(0, 0, size.width(), size.height())) {
677         bitmap->reset();
678         return false;
679     }
680
681     if (!bitmap->allocN32Pixels(r.width(), r.height())) {
682         // bitmap will already be reset.
683         return false;
684     }
685     if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
686         bitmap->reset();
687         return false;
688     }
689     return true;
690 }
691
692 bool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
693     switch (origInfo.colorType()) {
694         case kUnknown_SkColorType:
695         case kIndex_8_SkColorType:
696             return false;
697         default:
698             break;
699     }
700     if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
701         return false;
702     }
703     if (0 == origInfo.width() || 0 == origInfo.height()) {
704         return false;
705     }
706
707     SkBaseDevice* device = this->getDevice();
708     if (!device) {
709         return false;
710     }
711
712     const SkISize size = this->getBaseLayerSize();
713     SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
714     if (!srcR.intersect(0, 0, size.width(), size.height())) {
715         return false;
716     }
717
718     SkImageInfo info = origInfo;
719     // the intersect may have shrunk info's logical size
720     info.fWidth = srcR.width();
721     info.fHeight = srcR.height();
722
723     // if x or y are negative, then we have to adjust pixels
724     if (x > 0) {
725         x = 0;
726     }
727     if (y > 0) {
728         y = 0;
729     }
730     // here x,y are either 0 or negative
731     dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
732
733     // The device can assert that the requested area is always contained in its bounds
734     return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
735 }
736
737 bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
738     if (bitmap.getTexture()) {
739         return false;
740     }
741     SkBitmap bm(bitmap);
742     bm.lockPixels();
743     if (bm.getPixels()) {
744         return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
745     }
746     return false;
747 }
748
749 bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
750                            int x, int y) {
751     switch (origInfo.colorType()) {
752         case kUnknown_SkColorType:
753         case kIndex_8_SkColorType:
754             return false;
755         default:
756             break;
757     }
758     if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
759         return false;
760     }
761
762     const SkISize size = this->getBaseLayerSize();
763     SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
764     if (!target.intersect(0, 0, size.width(), size.height())) {
765         return false;
766     }
767
768     SkBaseDevice* device = this->getDevice();
769     if (!device) {
770         return false;
771     }
772
773     SkImageInfo info = origInfo;
774     // the intersect may have shrunk info's logical size
775     info.fWidth = target.width();
776     info.fHeight = target.height();
777
778     // if x or y are negative, then we have to adjust pixels
779     if (x > 0) {
780         x = 0;
781     }
782     if (y > 0) {
783         y = 0;
784     }
785     // here x,y are either 0 or negative
786     pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
787
788     // The device can assert that the requested area is always contained in its bounds
789     return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
790 }
791
792 SkCanvas* SkCanvas::canvasForDrawIter() {
793     return this;
794 }
795
796 //////////////////////////////////////////////////////////////////////////////
797
798 void SkCanvas::updateDeviceCMCache() {
799     if (fDeviceCMDirty) {
800         const SkMatrix& totalMatrix = this->getTotalMatrix();
801         const SkRasterClip& totalClip = *fMCRec->fRasterClip;
802         DeviceCM*       layer = fMCRec->fTopLayer;
803
804         if (NULL == layer->fNext) {   // only one layer
805             layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
806         } else {
807             SkRasterClip clip(totalClip);
808             do {
809                 layer->updateMC(totalMatrix, clip, fClipStack, &clip);
810             } while ((layer = layer->fNext) != NULL);
811         }
812         fDeviceCMDirty = false;
813     }
814 }
815
816 ///////////////////////////////////////////////////////////////////////////////
817
818 int SkCanvas::internalSave(SaveFlags flags) {
819     int saveCount = this->getSaveCount(); // record this before the actual save
820
821     MCRec* newTop = (MCRec*)fMCStack.push_back();
822     new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
823
824     fMCRec = newTop;
825
826     if (SkCanvas::kClip_SaveFlag & flags) {
827         fClipStack.save();
828     }
829
830     return saveCount;
831 }
832
833 void SkCanvas::willSave(SaveFlags) {
834     // Do nothing. Subclasses may do something.
835 }
836
837 int SkCanvas::save() {
838     this->willSave(kMatrixClip_SaveFlag);
839     return this->internalSave(kMatrixClip_SaveFlag);
840 }
841
842 int SkCanvas::save(SaveFlags flags) {
843     this->willSave(flags);
844     // call shared impl
845     return this->internalSave(flags);
846 }
847
848 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
849 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
850     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
851 #else
852     return true;
853 #endif
854 }
855
856 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
857                                SkIRect* intersection, const SkImageFilter* imageFilter) {
858     SkIRect clipBounds;
859     SkRegion::Op op = SkRegion::kIntersect_Op;
860     if (!this->getClipDeviceBounds(&clipBounds)) {
861         return false;
862     }
863
864     if (imageFilter) {
865         imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds);
866         // Filters may grow the bounds beyond the device bounds.
867         op = SkRegion::kReplace_Op;
868     }
869     SkIRect ir;
870     if (NULL != bounds) {
871         SkRect r;
872
873         this->getTotalMatrix().mapRect(&r, *bounds);
874         r.roundOut(&ir);
875         // early exit if the layer's bounds are clipped out
876         if (!ir.intersect(clipBounds)) {
877             if (bounds_affects_clip(flags)) {
878                 fMCRec->fRasterClip->setEmpty();
879             }
880             return false;
881         }
882     } else {    // no user bounds, so just use the clip
883         ir = clipBounds;
884     }
885
886     if (bounds_affects_clip(flags)) {
887         fClipStack.clipDevRect(ir, op);
888         // early exit if the clip is now empty
889         if (!fMCRec->fRasterClip->op(ir, op)) {
890             return false;
891         }
892     }
893
894     if (intersection) {
895         *intersection = ir;
896     }
897     return true;
898 }
899
900 SkCanvas::SaveLayerStrategy SkCanvas::willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
901
902     // Do nothing. Subclasses may do something.
903     return kFullLayer_SaveLayerStrategy;
904 }
905
906 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
907     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
908     return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
909 }
910
911 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
912                         SaveFlags flags) {
913     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
914     return this->internalSaveLayer(bounds, paint, flags, false, strategy);
915 }
916
917 static SkBaseDevice* create_compatible_device(SkCanvas* canvas,
918                                               const SkImageInfo& info) {
919     SkBaseDevice* device = canvas->getDevice();
920     return device ? device->createCompatibleDevice(info) : NULL;
921 }
922
923 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
924                                 bool justForImageFilter, SaveLayerStrategy strategy) {
925 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
926     flags = (SaveFlags)(flags | kClipToLayer_SaveFlag);
927 #endif
928
929     // do this before we create the layer. We don't call the public save() since
930     // that would invoke a possibly overridden virtual
931     int count = this->internalSave(flags);
932
933     fDeviceCMDirty = true;
934
935     SkIRect ir;
936     if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
937         return count;
938     }
939
940     // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
941     // the clipRectBounds() call above?
942     if (kNoLayer_SaveLayerStrategy == strategy) {
943         return count;
944     }
945
946     // Kill the imagefilter if our device doesn't allow it
947     SkLazyPaint lazyP;
948     if (paint && paint->getImageFilter()) {
949         if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
950             if (justForImageFilter) {
951                 // early exit if the layer was just for the imageFilter
952                 return count;
953             }
954             SkPaint* p = lazyP.set(*paint);
955             p->setImageFilter(NULL);
956             paint = p;
957         }
958     }
959
960     bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
961     SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
962                         isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
963
964     SkBaseDevice* device;
965     if (paint && paint->getImageFilter()) {
966         device = create_compatible_device(this, info);
967     } else {
968         device = this->createLayerDevice(info);
969     }
970     if (NULL == device) {
971         SkDebugf("Unable to create device for layer.");
972         return count;
973     }
974
975     device->setOrigin(ir.fLeft, ir.fTop);
976     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
977     device->unref();
978
979     layer->fNext = fMCRec->fTopLayer;
980     fMCRec->fLayer = layer;
981     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
982
983     fSaveLayerCount += 1;
984     return count;
985 }
986
987 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
988     return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
989 }
990
991 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
992                              SaveFlags flags) {
993     if (0xFF == alpha) {
994         return this->saveLayer(bounds, NULL, flags);
995     } else {
996         SkPaint tmpPaint;
997         tmpPaint.setAlpha(alpha);
998         return this->saveLayer(bounds, &tmpPaint, flags);
999     }
1000 }
1001
1002 void SkCanvas::willRestore() {
1003     // Do nothing. Subclasses may do something.
1004 }
1005
1006 void SkCanvas::restore() {
1007     // check for underflow
1008     if (fMCStack.count() > 1) {
1009         this->willRestore();
1010         this->internalRestore();
1011     }
1012 }
1013
1014 void SkCanvas::internalRestore() {
1015     SkASSERT(fMCStack.count() != 0);
1016
1017     fDeviceCMDirty = true;
1018     fCachedLocalClipBoundsDirty = true;
1019
1020     if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) {
1021         fClipStack.restore();
1022     }
1023
1024     // reserve our layer (if any)
1025     DeviceCM* layer = fMCRec->fLayer;   // may be null
1026     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1027     fMCRec->fLayer = NULL;
1028
1029     // now do the normal restore()
1030     fMCRec->~MCRec();       // balanced in save()
1031     fMCStack.pop_back();
1032     fMCRec = (MCRec*)fMCStack.back();
1033
1034     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1035         since if we're being recorded, we don't want to record this (the
1036         recorder will have already recorded the restore).
1037     */
1038     if (NULL != layer) {
1039         if (layer->fNext) {
1040             const SkIPoint& origin = layer->fDevice->getOrigin();
1041             this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1042                                      layer->fPaint);
1043             // reset this, since internalDrawDevice will have set it to true
1044             fDeviceCMDirty = true;
1045
1046             SkASSERT(fSaveLayerCount > 0);
1047             fSaveLayerCount -= 1;
1048         }
1049         SkDELETE(layer);
1050     }
1051 }
1052
1053 int SkCanvas::getSaveCount() const {
1054     return fMCStack.count();
1055 }
1056
1057 void SkCanvas::restoreToCount(int count) {
1058     // sanity check
1059     if (count < 1) {
1060         count = 1;
1061     }
1062
1063     int n = this->getSaveCount() - count;
1064     for (int i = 0; i < n; ++i) {
1065         this->restore();
1066     }
1067 }
1068
1069 bool SkCanvas::isDrawingToLayer() const {
1070     return fSaveLayerCount > 0;
1071 }
1072
1073 SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
1074     return this->onNewSurface(info);
1075 }
1076
1077 SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
1078     SkBaseDevice* dev = this->getDevice();
1079     return dev ? dev->newSurface(info) : NULL;
1080 }
1081
1082 SkImageInfo SkCanvas::imageInfo() const {
1083     SkBaseDevice* dev = this->getDevice();
1084     if (dev) {
1085         return dev->imageInfo();
1086     } else {
1087         return SkImageInfo::MakeUnknown(0, 0);
1088     }
1089 }
1090
1091 const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1092     return this->onPeekPixels(info, rowBytes);
1093 }
1094
1095 const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1096     SkBaseDevice* dev = this->getDevice();
1097     return dev ? dev->peekPixels(info, rowBytes) : NULL;
1098 }
1099
1100 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1101     void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
1102     if (pixels && origin) {
1103         *origin = this->getTopDevice(false)->getOrigin();
1104     }
1105     return pixels;
1106 }
1107
1108 void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
1109     SkBaseDevice* dev = this->getTopDevice();
1110     return dev ? dev->accessPixels(info, rowBytes) : NULL;
1111 }
1112
1113 SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1114     fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1115     if (NULL == fAddr) {
1116         fInfo = canvas->imageInfo();
1117         if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
1118             return; // failure, fAddr is NULL
1119         }
1120         if (!canvas->readPixels(&fBitmap, 0, 0)) {
1121             return; // failure, fAddr is NULL
1122         }
1123         fAddr = fBitmap.getPixels();
1124         fRowBytes = fBitmap.rowBytes();
1125     }
1126     SkASSERT(fAddr);    // success
1127 }
1128
1129 bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1130     if (fAddr) {
1131         return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes,
1132                                      NULL, NULL);
1133     } else {
1134         bitmap->reset();
1135         return false;
1136     }
1137 }
1138
1139 void SkCanvas::onPushCull(const SkRect& cullRect) {
1140     // do nothing. Subclasses may do something
1141 }
1142
1143 void SkCanvas::onPopCull() {
1144     // do nothing. Subclasses may do something
1145 }
1146
1147 /////////////////////////////////////////////////////////////////////////////
1148 #ifdef SK_DEBUG
1149 // Ensure that cull rects are monotonically nested in device space.
1150 void SkCanvas::validateCull(const SkIRect& devCull) {
1151     if (fCullStack.isEmpty()
1152         || devCull.isEmpty()
1153         || fCullStack.top().contains(devCull)) {
1154         return;
1155     }
1156
1157     SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1158               devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1159               fCullStack.top().x(), fCullStack.top().y(),
1160               fCullStack.top().right(), fCullStack.top().bottom()));
1161
1162 #ifdef ASSERT_NESTED_CULLING
1163     SkDEBUGFAIL("Invalid cull.");
1164 #endif
1165 }
1166 #endif
1167
1168 void SkCanvas::pushCull(const SkRect& cullRect) {
1169     ++fCullCount;
1170     this->onPushCull(cullRect);
1171
1172 #ifdef SK_DEBUG
1173     // Map the cull rect into device space.
1174     SkRect mappedCull;
1175     this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1176
1177     // Take clipping into account.
1178     SkIRect devClip, devCull;
1179     mappedCull.roundOut(&devCull);
1180     this->getClipDeviceBounds(&devClip);
1181     if (!devCull.intersect(devClip)) {
1182         devCull.setEmpty();
1183     }
1184
1185     this->validateCull(devCull);
1186     fCullStack.push(devCull); // balanced in popCull
1187 #endif
1188 }
1189
1190 void SkCanvas::popCull() {
1191     SkASSERT(fCullStack.count() == fCullCount);
1192
1193     if (fCullCount > 0) {
1194         --fCullCount;
1195         this->onPopCull();
1196
1197         SkDEBUGCODE(fCullStack.pop());
1198     }
1199 }
1200
1201 /////////////////////////////////////////////////////////////////////////////
1202
1203 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1204                                 const SkMatrix& matrix, const SkPaint* paint) {
1205     if (bitmap.drawsNothing()) {
1206         return;
1207     }
1208
1209     SkLazyPaint lazy;
1210     if (NULL == paint) {
1211         paint = lazy.init();
1212     }
1213
1214     SkDEBUGCODE(bitmap.validate();)
1215     CHECK_LOCKCOUNT_BALANCE(bitmap);
1216
1217     SkRect storage;
1218     const SkRect* bounds = NULL;
1219     if (paint && paint->canComputeFastBounds()) {
1220         bitmap.getBounds(&storage);
1221         matrix.mapRect(&storage);
1222         bounds = &paint->computeFastBounds(storage, &storage);
1223     }
1224
1225     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1226
1227     while (iter.next()) {
1228         iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1229     }
1230
1231     LOOPER_END
1232 }
1233
1234 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1235                                   const SkPaint* paint) {
1236     SkPaint tmp;
1237     if (NULL == paint) {
1238         tmp.setDither(true);
1239         paint = &tmp;
1240     }
1241
1242     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1243     while (iter.next()) {
1244         SkBaseDevice* dstDev = iter.fDevice;
1245         paint = &looper.paint();
1246         SkImageFilter* filter = paint->getImageFilter();
1247         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1248         if (filter && !dstDev->canHandleImageFilter(filter)) {
1249             SkDeviceImageFilterProxy proxy(dstDev);
1250             SkBitmap dst;
1251             SkIPoint offset = SkIPoint::Make(0, 0);
1252             const SkBitmap& src = srcDev->accessBitmap(false);
1253             SkMatrix matrix = *iter.fMatrix;
1254             matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1255             SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1256             SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
1257             SkAutoUnref aur(NULL);
1258             if (!cache) {
1259                 cache = SkImageFilter::Cache::Create();
1260                 aur.reset(cache);
1261             }
1262             SkImageFilter::Context ctx(matrix, clipBounds, cache);
1263             if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1264                 SkPaint tmpUnfiltered(*paint);
1265                 tmpUnfiltered.setImageFilter(NULL);
1266                 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1267                                    tmpUnfiltered);
1268             }
1269         } else {
1270             dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1271         }
1272     }
1273     LOOPER_END
1274 }
1275
1276 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1277                           const SkPaint* paint) {
1278     if (bitmap.drawsNothing()) {
1279         return;
1280     }
1281     SkDEBUGCODE(bitmap.validate();)
1282     CHECK_LOCKCOUNT_BALANCE(bitmap);
1283
1284     SkPaint tmp;
1285     if (NULL == paint) {
1286         paint = &tmp;
1287     }
1288
1289     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1290
1291     while (iter.next()) {
1292         paint = &looper.paint();
1293         SkImageFilter* filter = paint->getImageFilter();
1294         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1295         if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1296             SkDeviceImageFilterProxy proxy(iter.fDevice);
1297             SkBitmap dst;
1298             SkIPoint offset = SkIPoint::Make(0, 0);
1299             SkMatrix matrix = *iter.fMatrix;
1300             matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1301             SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1302             SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
1303             SkAutoUnref aur(NULL);
1304             if (!cache) {
1305                 cache = SkImageFilter::Cache::Create();
1306                 aur.reset(cache);
1307             }
1308             SkImageFilter::Context ctx(matrix, clipBounds, cache);
1309             if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1310                 SkPaint tmpUnfiltered(*paint);
1311                 tmpUnfiltered.setImageFilter(NULL);
1312                 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1313                                          tmpUnfiltered);
1314             }
1315         } else {
1316             iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1317         }
1318     }
1319     LOOPER_END
1320 }
1321
1322 /////////////////////////////////////////////////////////////////////////////
1323 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1324     SkMatrix m;
1325     m.setTranslate(dx, dy);
1326     this->concat(m);
1327 }
1328
1329 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1330     SkMatrix m;
1331     m.setScale(sx, sy);
1332     this->concat(m);
1333 }
1334
1335 void SkCanvas::rotate(SkScalar degrees) {
1336     SkMatrix m;
1337     m.setRotate(degrees);
1338     this->concat(m);
1339 }
1340
1341 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1342     SkMatrix m;
1343     m.setSkew(sx, sy);
1344     this->concat(m);
1345 }
1346
1347 void SkCanvas::didConcat(const SkMatrix&) {
1348     // Do nothing. Subclasses may do something.
1349 }
1350
1351 void SkCanvas::concat(const SkMatrix& matrix) {
1352     if (matrix.isIdentity()) {
1353         return;
1354     }
1355
1356     fDeviceCMDirty = true;
1357     fCachedLocalClipBoundsDirty = true;
1358     fMCRec->fMatrix->preConcat(matrix);
1359
1360     this->didConcat(matrix);
1361 }
1362
1363 void SkCanvas::didSetMatrix(const SkMatrix&) {
1364     // Do nothing. Subclasses may do something.
1365 }
1366
1367 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1368     fDeviceCMDirty = true;
1369     fCachedLocalClipBoundsDirty = true;
1370     *fMCRec->fMatrix = matrix;
1371     this->didSetMatrix(matrix);
1372 }
1373
1374 void SkCanvas::resetMatrix() {
1375     SkMatrix matrix;
1376
1377     matrix.reset();
1378     this->setMatrix(matrix);
1379 }
1380
1381 //////////////////////////////////////////////////////////////////////////////
1382
1383 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1384     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1385     this->onClipRect(rect, op, edgeStyle);
1386 }
1387
1388 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1389 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1390     if (SkRegion::kIntersect_Op == op) {
1391         if (fMCRec->fRasterClip->isEmpty()) {
1392             return false;
1393         }
1394
1395         if (this->quickReject(rect)) {
1396             fDeviceCMDirty = true;
1397             fCachedLocalClipBoundsDirty = true;
1398
1399             fClipStack.clipEmpty();
1400             return fMCRec->fRasterClip->setEmpty();
1401         }
1402     }
1403 #endif
1404
1405     AutoValidateClip avc(this);
1406
1407     fDeviceCMDirty = true;
1408     fCachedLocalClipBoundsDirty = true;
1409     if (!fAllowSoftClip) {
1410         edgeStyle = kHard_ClipEdgeStyle;
1411     }
1412
1413     if (fMCRec->fMatrix->rectStaysRect()) {
1414         // for these simpler matrices, we can stay a rect even after applying
1415         // the matrix. This means we don't have to a) make a path, and b) tell
1416         // the region code to scan-convert the path, only to discover that it
1417         // is really just a rect.
1418         SkRect      r;
1419
1420         fMCRec->fMatrix->mapRect(&r, rect);
1421         fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1422         fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1423     } else {
1424         // since we're rotated or some such thing, we convert the rect to a path
1425         // and clip against that, since it can handle any matrix. However, to
1426         // avoid recursion in the case where we are subclassed (e.g. Pictures)
1427         // we explicitly call "our" version of clipPath.
1428         SkPath  path;
1429
1430         path.addRect(rect);
1431         this->SkCanvas::onClipPath(path, op, edgeStyle);
1432     }
1433 }
1434
1435 static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
1436                              const SkPath& devPath, SkRegion::Op op, bool doAA) {
1437     // base is used to limit the size (and therefore memory allocation) of the
1438     // region that results from scan converting devPath.
1439     SkRegion base;
1440
1441     if (SkRegion::kIntersect_Op == op) {
1442         // since we are intersect, we can do better (tighter) with currRgn's
1443         // bounds, than just using the device. However, if currRgn is complex,
1444         // our region blitter may hork, so we do that case in two steps.
1445         if (currClip->isRect()) {
1446             // FIXME: we should also be able to do this when currClip->isBW(),
1447             // but relaxing the test above triggers GM asserts in
1448             // SkRgnBuilder::blitH(). We need to investigate what's going on.
1449             currClip->setPath(devPath, currClip->bwRgn(), doAA);
1450         } else {
1451             base.setRect(currClip->getBounds());
1452             SkRasterClip clip;
1453             clip.setPath(devPath, base, doAA);
1454             currClip->op(clip, op);
1455         }
1456     } else {
1457         const SkBaseDevice* device = canvas->getDevice();
1458         if (!device) {
1459             currClip->setEmpty();
1460             return;
1461         }
1462
1463         base.setRect(0, 0, device->width(), device->height());
1464
1465         if (SkRegion::kReplace_Op == op) {
1466             currClip->setPath(devPath, base, doAA);
1467         } else {
1468             SkRasterClip clip;
1469             clip.setPath(devPath, base, doAA);
1470             currClip->op(clip, op);
1471         }
1472     }
1473 }
1474
1475 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1476     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1477     if (rrect.isRect()) {
1478         this->onClipRect(rrect.getBounds(), op, edgeStyle);
1479     } else {
1480         this->onClipRRect(rrect, op, edgeStyle);
1481     }
1482 }
1483
1484 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1485     SkRRect transformedRRect;
1486     if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
1487         AutoValidateClip avc(this);
1488
1489         fDeviceCMDirty = true;
1490         fCachedLocalClipBoundsDirty = true;
1491         if (!fAllowSoftClip) {
1492             edgeStyle = kHard_ClipEdgeStyle;
1493         }
1494
1495         fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1496
1497         SkPath devPath;
1498         devPath.addRRect(transformedRRect);
1499
1500         clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1501         return;
1502     }
1503
1504     SkPath path;
1505     path.addRRect(rrect);
1506     // call the non-virtual version
1507     this->SkCanvas::onClipPath(path, op, edgeStyle);
1508 }
1509
1510 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1511     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1512     SkRect r;
1513     if (!path.isInverseFillType() && path.isRect(&r)) {
1514         this->onClipRect(r, op, edgeStyle);
1515     } else {
1516         this->onClipPath(path, op, edgeStyle);
1517     }
1518 }
1519
1520 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1521 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1522     if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1523         if (fMCRec->fRasterClip->isEmpty()) {
1524             return false;
1525         }
1526
1527         if (this->quickReject(path.getBounds())) {
1528             fDeviceCMDirty = true;
1529             fCachedLocalClipBoundsDirty = true;
1530
1531             fClipStack.clipEmpty();
1532             return fMCRec->fRasterClip->setEmpty();
1533         }
1534     }
1535 #endif
1536
1537     AutoValidateClip avc(this);
1538
1539     fDeviceCMDirty = true;
1540     fCachedLocalClipBoundsDirty = true;
1541     if (!fAllowSoftClip) {
1542         edgeStyle = kHard_ClipEdgeStyle;
1543     }
1544
1545     SkPath devPath;
1546     path.transform(*fMCRec->fMatrix, &devPath);
1547
1548     // Check if the transfomation, or the original path itself
1549     // made us empty. Note this can also happen if we contained NaN
1550     // values. computing the bounds detects this, and will set our
1551     // bounds to empty if that is the case. (see SkRect::set(pts, count))
1552     if (devPath.getBounds().isEmpty()) {
1553         // resetting the path will remove any NaN or other wanky values
1554         // that might upset our scan converter.
1555         devPath.reset();
1556     }
1557
1558     // if we called path.swap() we could avoid a deep copy of this path
1559     fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1560
1561     if (fAllowSimplifyClip) {
1562         devPath.reset();
1563         devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1564         const SkClipStack* clipStack = getClipStack();
1565         SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
1566         const SkClipStack::Element* element;
1567         while ((element = iter.next())) {
1568             SkClipStack::Element::Type type = element->getType();
1569             if (type == SkClipStack::Element::kEmpty_Type) {
1570                 continue;
1571             }
1572             SkPath operand;
1573             element->asPath(&operand);
1574             SkRegion::Op elementOp = element->getOp();
1575             if (elementOp == SkRegion::kReplace_Op) {
1576                 devPath = operand;
1577             } else {
1578                 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1579             }
1580             // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1581             // perhaps we need an API change to avoid this sort of mixed-signals about
1582             // clipping.
1583             if (element->isAA()) {
1584                 edgeStyle = kSoft_ClipEdgeStyle;
1585             }
1586         }
1587         op = SkRegion::kReplace_Op;
1588     }
1589
1590     clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
1591 }
1592
1593 void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1594                                                    bool inverseFilled) {
1595     // This is for updating the clip conservatively using only bounds
1596     // information.
1597     // Contract:
1598     //    The current clip must contain the true clip. The true
1599     //    clip is the clip that would have normally been computed
1600     //    by calls to clipPath and clipRRect
1601     // Objective:
1602     //    Keep the current clip as small as possible without
1603     //    breaking the contract, using only clip bounding rectangles
1604     //    (for performance).
1605
1606     // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1607     // don't have to worry about getting caught in a loop. Thus anywhere
1608     // we call a virtual method, we explicitly prefix it with
1609     // SkCanvas:: to be sure to call the base-class.
1610
1611     if (inverseFilled) {
1612         switch (op) {
1613             case SkRegion::kIntersect_Op:
1614             case SkRegion::kDifference_Op:
1615                 // These ops can only shrink the current clip. So leaving
1616                 // the clip unchanged conservatively respects the contract.
1617                 break;
1618             case SkRegion::kUnion_Op:
1619             case SkRegion::kReplace_Op:
1620             case SkRegion::kReverseDifference_Op:
1621             case SkRegion::kXOR_Op: {
1622                     // These ops can grow the current clip up to the extents of
1623                     // the input clip, which is inverse filled, so we just set
1624                     // the current clip to the device bounds.
1625                     SkRect deviceBounds;
1626                     SkIRect deviceIBounds;
1627                     this->getDevice()->getGlobalBounds(&deviceIBounds);
1628                     deviceBounds = SkRect::Make(deviceIBounds);
1629
1630                     // set the clip in device space
1631                     SkMatrix savedMatrix = this->getTotalMatrix();
1632                     this->SkCanvas::setMatrix(SkMatrix::I());
1633                     this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
1634                                                kHard_ClipEdgeStyle);
1635                     this->setMatrix(savedMatrix);
1636                     break;
1637             }
1638             default:
1639                 SkASSERT(0); // unhandled op?
1640         }
1641     } else {
1642         // Not inverse filled
1643         switch (op) {
1644             case SkRegion::kIntersect_Op:
1645             case SkRegion::kUnion_Op:
1646             case SkRegion::kReplace_Op:
1647                 this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
1648                 break;
1649             case SkRegion::kDifference_Op:
1650                 // Difference can only shrink the current clip.
1651                 // Leaving clip unchanged conservatively fullfills the contract.
1652                 break;
1653             case SkRegion::kReverseDifference_Op:
1654                 // To reverse, we swap in the bounds with a replace op.
1655                 // As with difference, leave it unchanged.
1656                 this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
1657                 break;
1658             case SkRegion::kXOR_Op:
1659                 // Be conservative, based on (A XOR B) always included in (A union B),
1660                 // which is always included in (bounds(A) union bounds(B))
1661                 this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
1662                 break;
1663             default:
1664                 SkASSERT(0); // unhandled op?
1665         }
1666     }
1667 }
1668
1669 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1670     this->onClipRegion(rgn, op);
1671 }
1672
1673 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1674     AutoValidateClip avc(this);
1675
1676     fDeviceCMDirty = true;
1677     fCachedLocalClipBoundsDirty = true;
1678
1679     // todo: signal fClipStack that we have a region, and therefore (I guess)
1680     // we have to ignore it, and use the region directly?
1681     fClipStack.clipDevRect(rgn.getBounds(), op);
1682
1683     fMCRec->fRasterClip->op(rgn, op);
1684 }
1685
1686 #ifdef SK_DEBUG
1687 void SkCanvas::validateClip() const {
1688     // construct clipRgn from the clipstack
1689     const SkBaseDevice* device = this->getDevice();
1690     if (!device) {
1691         SkASSERT(this->isClipEmpty());
1692         return;
1693     }
1694
1695     SkIRect ir;
1696     ir.set(0, 0, device->width(), device->height());
1697     SkRasterClip tmpClip(ir);
1698
1699     SkClipStack::B2TIter                iter(fClipStack);
1700     const SkClipStack::Element* element;
1701     while ((element = iter.next()) != NULL) {
1702         switch (element->getType()) {
1703             case SkClipStack::Element::kRect_Type:
1704                 element->getRect().round(&ir);
1705                 tmpClip.op(ir, element->getOp());
1706                 break;
1707             case SkClipStack::Element::kEmpty_Type:
1708                 tmpClip.setEmpty();
1709                 break;
1710             default: {
1711                 SkPath path;
1712                 element->asPath(&path);
1713                 clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
1714                 break;
1715             }
1716         }
1717     }
1718 }
1719 #endif
1720
1721 void SkCanvas::replayClips(ClipVisitor* visitor) const {
1722     SkClipStack::B2TIter                iter(fClipStack);
1723     const SkClipStack::Element*         element;
1724
1725     static const SkRect kEmpty = { 0, 0, 0, 0 };
1726     while ((element = iter.next()) != NULL) {
1727         switch (element->getType()) {
1728             case SkClipStack::Element::kPath_Type:
1729                 visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
1730                 break;
1731             case SkClipStack::Element::kRRect_Type:
1732                 visitor->clipRRect(element->getRRect(), element->getOp(), element->isAA());
1733                 break;
1734             case SkClipStack::Element::kRect_Type:
1735                 visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
1736                 break;
1737             case SkClipStack::Element::kEmpty_Type:
1738                 visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
1739                 break;
1740         }
1741     }
1742 }
1743
1744 ///////////////////////////////////////////////////////////////////////////////
1745
1746 bool SkCanvas::isClipEmpty() const {
1747     return fMCRec->fRasterClip->isEmpty();
1748 }
1749
1750 bool SkCanvas::isClipRect() const {
1751     return fMCRec->fRasterClip->isRect();
1752 }
1753
1754 bool SkCanvas::quickReject(const SkRect& rect) const {
1755
1756     if (!rect.isFinite())
1757         return true;
1758
1759     if (fMCRec->fRasterClip->isEmpty()) {
1760         return true;
1761     }
1762
1763     if (fMCRec->fMatrix->hasPerspective()) {
1764         SkRect dst;
1765         fMCRec->fMatrix->mapRect(&dst, rect);
1766         SkIRect idst;
1767         dst.roundOut(&idst);
1768         return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1769     } else {
1770         const SkRect& clipR = this->getLocalClipBounds();
1771
1772         // for speed, do the most likely reject compares first
1773         // TODO: should we use | instead, or compare all 4 at once?
1774         if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1775             return true;
1776         }
1777         if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1778             return true;
1779         }
1780         return false;
1781     }
1782 }
1783
1784 bool SkCanvas::quickReject(const SkPath& path) const {
1785     return path.isEmpty() || this->quickReject(path.getBounds());
1786 }
1787
1788 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1789     SkIRect ibounds;
1790     if (!this->getClipDeviceBounds(&ibounds)) {
1791         return false;
1792     }
1793
1794     SkMatrix inverse;
1795     // if we can't invert the CTM, we can't return local clip bounds
1796     if (!fMCRec->fMatrix->invert(&inverse)) {
1797         if (bounds) {
1798             bounds->setEmpty();
1799         }
1800         return false;
1801     }
1802
1803     if (NULL != bounds) {
1804         SkRect r;
1805         // adjust it outwards in case we are antialiasing
1806         const int inset = 1;
1807
1808         r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1809                ibounds.fRight + inset, ibounds.fBottom + inset);
1810         inverse.mapRect(bounds, r);
1811     }
1812     return true;
1813 }
1814
1815 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1816     const SkRasterClip& clip = *fMCRec->fRasterClip;
1817     if (clip.isEmpty()) {
1818         if (bounds) {
1819             bounds->setEmpty();
1820         }
1821         return false;
1822     }
1823
1824     if (NULL != bounds) {
1825         *bounds = clip.getBounds();
1826     }
1827     return true;
1828 }
1829
1830 const SkMatrix& SkCanvas::getTotalMatrix() const {
1831     return *fMCRec->fMatrix;
1832 }
1833
1834 #ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
1835 SkCanvas::ClipType SkCanvas::getClipType() const {
1836     if (fMCRec->fRasterClip->isEmpty()) {
1837         return kEmpty_ClipType;
1838     }
1839     if (fMCRec->fRasterClip->isRect()) {
1840         return kRect_ClipType;
1841     }
1842     return kComplex_ClipType;
1843 }
1844 #endif
1845
1846 #ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
1847 const SkRegion& SkCanvas::getTotalClip() const {
1848     return fMCRec->fRasterClip->forceGetBW();
1849 }
1850 #endif
1851
1852 const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1853     return fMCRec->fRasterClip->forceGetBW();
1854 }
1855
1856 void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
1857     path->reset();
1858
1859     const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
1860     if (rgn.isEmpty()) {
1861         return;
1862     }
1863     (void)rgn.getBoundaryPath(path);
1864 }
1865
1866 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1867     SkBaseDevice* dev = this->getTopDevice();
1868     return dev ? dev->accessRenderTarget() : NULL;
1869 }
1870
1871 SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
1872     SkBaseDevice* device = this->getTopDevice();
1873     return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
1874 }
1875
1876 GrContext* SkCanvas::getGrContext() {
1877 #if SK_SUPPORT_GPU
1878     SkBaseDevice* device = this->getTopDevice();
1879     if (NULL != device) {
1880         GrRenderTarget* renderTarget = device->accessRenderTarget();
1881         if (NULL != renderTarget) {
1882             return renderTarget->getContext();
1883         }
1884     }
1885 #endif
1886
1887     return NULL;
1888
1889 }
1890
1891 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1892                           const SkPaint& paint) {
1893     if (outer.isEmpty()) {
1894         return;
1895     }
1896     if (inner.isEmpty()) {
1897         this->drawRRect(outer, paint);
1898         return;
1899     }
1900
1901     // We don't have this method (yet), but technically this is what we should
1902     // be able to assert...
1903     // SkASSERT(outer.contains(inner));
1904     //
1905     // For now at least check for containment of bounds
1906     SkASSERT(outer.getBounds().contains(inner.getBounds()));
1907
1908     this->onDrawDRRect(outer, inner, paint);
1909 }
1910
1911 //////////////////////////////////////////////////////////////////////////////
1912 //  These are the virtual drawing methods
1913 //////////////////////////////////////////////////////////////////////////////
1914
1915 void SkCanvas::clear(SkColor color) {
1916     SkDrawIter  iter(this);
1917     this->predrawNotify();
1918     while (iter.next()) {
1919         iter.fDevice->clear(color);
1920     }
1921 }
1922
1923 void SkCanvas::onDiscard() {
1924     if (NULL != fSurfaceBase) {
1925         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1926     }
1927 }
1928
1929 void SkCanvas::drawPaint(const SkPaint& paint) {
1930     this->internalDrawPaint(paint);
1931 }
1932
1933 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1934     LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1935
1936     while (iter.next()) {
1937         iter.fDevice->drawPaint(iter, looper.paint());
1938     }
1939
1940     LOOPER_END
1941 }
1942
1943 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1944                           const SkPaint& paint) {
1945     if ((long)count <= 0) {
1946         return;
1947     }
1948
1949     SkRect r, storage;
1950     const SkRect* bounds = NULL;
1951     if (paint.canComputeFastBounds()) {
1952         // special-case 2 points (common for drawing a single line)
1953         if (2 == count) {
1954             r.set(pts[0], pts[1]);
1955         } else {
1956             r.set(pts, SkToInt(count));
1957         }
1958         bounds = &paint.computeFastStrokeBounds(r, &storage);
1959         if (this->quickReject(*bounds)) {
1960             return;
1961         }
1962     }
1963
1964     SkASSERT(pts != NULL);
1965
1966     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1967
1968     while (iter.next()) {
1969         iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1970     }
1971
1972     LOOPER_END
1973 }
1974
1975 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1976     SkRect storage;
1977     const SkRect* bounds = NULL;
1978     if (paint.canComputeFastBounds()) {
1979         bounds = &paint.computeFastBounds(r, &storage);
1980         if (this->quickReject(*bounds)) {
1981             return;
1982         }
1983     }
1984
1985     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1986
1987     while (iter.next()) {
1988         iter.fDevice->drawRect(iter, r, looper.paint());
1989     }
1990
1991     LOOPER_END
1992 }
1993
1994 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1995     SkRect storage;
1996     const SkRect* bounds = NULL;
1997     if (paint.canComputeFastBounds()) {
1998         bounds = &paint.computeFastBounds(oval, &storage);
1999         if (this->quickReject(*bounds)) {
2000             return;
2001         }
2002     }
2003
2004     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2005
2006     while (iter.next()) {
2007         iter.fDevice->drawOval(iter, oval, looper.paint());
2008     }
2009
2010     LOOPER_END
2011 }
2012
2013 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
2014     SkRect storage;
2015     const SkRect* bounds = NULL;
2016     if (paint.canComputeFastBounds()) {
2017         bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
2018         if (this->quickReject(*bounds)) {
2019             return;
2020         }
2021     }
2022
2023     if (rrect.isRect()) {
2024         // call the non-virtual version
2025         this->SkCanvas::drawRect(rrect.getBounds(), paint);
2026         return;
2027     } else if (rrect.isOval()) {
2028         // call the non-virtual version
2029         this->SkCanvas::drawOval(rrect.getBounds(), paint);
2030         return;
2031     }
2032
2033     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2034
2035     while (iter.next()) {
2036         iter.fDevice->drawRRect(iter, rrect, looper.paint());
2037     }
2038
2039     LOOPER_END
2040 }
2041
2042 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2043                             const SkPaint& paint) {
2044     SkRect storage;
2045     const SkRect* bounds = NULL;
2046     if (paint.canComputeFastBounds()) {
2047         bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
2048         if (this->quickReject(*bounds)) {
2049             return;
2050         }
2051     }
2052
2053     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2054
2055     while (iter.next()) {
2056         iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2057     }
2058
2059     LOOPER_END
2060 }
2061
2062 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
2063     if (!path.isFinite()) {
2064         return;
2065     }
2066
2067     SkRect storage;
2068     const SkRect* bounds = NULL;
2069     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2070         const SkRect& pathBounds = path.getBounds();
2071         bounds = &paint.computeFastBounds(pathBounds, &storage);
2072         if (this->quickReject(*bounds)) {
2073             return;
2074         }
2075     }
2076
2077     const SkRect& r = path.getBounds();
2078     if (r.width() <= 0 && r.height() <= 0) {
2079         if (path.isInverseFillType()) {
2080             this->internalDrawPaint(paint);
2081         }
2082         return;
2083     }
2084
2085     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
2086
2087     while (iter.next()) {
2088         iter.fDevice->drawPath(iter, path, looper.paint());
2089     }
2090
2091     LOOPER_END
2092 }
2093
2094 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
2095                           const SkPaint* paint) {
2096     SkDEBUGCODE(bitmap.validate();)
2097
2098     if (NULL == paint || paint->canComputeFastBounds()) {
2099         SkRect bounds = {
2100             x, y,
2101             x + SkIntToScalar(bitmap.width()),
2102             y + SkIntToScalar(bitmap.height())
2103         };
2104         if (paint) {
2105             (void)paint->computeFastBounds(bounds, &bounds);
2106         }
2107         if (this->quickReject(bounds)) {
2108             return;
2109         }
2110     }
2111
2112     SkMatrix matrix;
2113     matrix.setTranslate(x, y);
2114     this->internalDrawBitmap(bitmap, matrix, paint);
2115 }
2116
2117 // this one is non-virtual, so it can be called safely by other canvas apis
2118 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2119                                       const SkRect& dst, const SkPaint* paint,
2120                                       DrawBitmapRectFlags flags) {
2121     if (bitmap.drawsNothing() || dst.isEmpty()) {
2122         return;
2123     }
2124
2125     CHECK_LOCKCOUNT_BALANCE(bitmap);
2126
2127     SkRect storage;
2128     const SkRect* bounds = &dst;
2129     if (NULL == paint || paint->canComputeFastBounds()) {
2130         if (paint) {
2131             bounds = &paint->computeFastBounds(dst, &storage);
2132         }
2133         if (this->quickReject(*bounds)) {
2134             return;
2135         }
2136     }
2137
2138     SkLazyPaint lazy;
2139     if (NULL == paint) {
2140         paint = lazy.init();
2141     }
2142
2143     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2144
2145     while (iter.next()) {
2146         iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2147     }
2148
2149     LOOPER_END
2150 }
2151
2152 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
2153                                     const SkRect& dst, const SkPaint* paint,
2154                                     DrawBitmapRectFlags flags) {
2155     SkDEBUGCODE(bitmap.validate();)
2156     this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
2157 }
2158
2159 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
2160                                 const SkPaint* paint) {
2161     SkDEBUGCODE(bitmap.validate();)
2162     this->internalDrawBitmap(bitmap, matrix, paint);
2163 }
2164
2165 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
2166                                       const SkIRect& center, const SkRect& dst,
2167                                       const SkPaint* paint) {
2168     if (bitmap.drawsNothing()) {
2169         return;
2170     }
2171     if (NULL == paint || paint->canComputeFastBounds()) {
2172         SkRect storage;
2173         const SkRect* bounds = &dst;
2174         if (paint) {
2175             bounds = &paint->computeFastBounds(dst, &storage);
2176         }
2177         if (this->quickReject(*bounds)) {
2178             return;
2179         }
2180     }
2181
2182     const int32_t w = bitmap.width();
2183     const int32_t h = bitmap.height();
2184
2185     SkIRect c = center;
2186     // pin center to the bounds of the bitmap
2187     c.fLeft = SkMax32(0, center.fLeft);
2188     c.fTop = SkMax32(0, center.fTop);
2189     c.fRight = SkPin32(center.fRight, c.fLeft, w);
2190     c.fBottom = SkPin32(center.fBottom, c.fTop, h);
2191
2192     const SkScalar srcX[4] = {
2193         0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
2194     };
2195     const SkScalar srcY[4] = {
2196         0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
2197     };
2198     SkScalar dstX[4] = {
2199         dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
2200         dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
2201     };
2202     SkScalar dstY[4] = {
2203         dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
2204         dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
2205     };
2206
2207     if (dstX[1] > dstX[2]) {
2208         dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
2209         dstX[2] = dstX[1];
2210     }
2211
2212     if (dstY[1] > dstY[2]) {
2213         dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2214         dstY[2] = dstY[1];
2215     }
2216
2217     for (int y = 0; y < 3; y++) {
2218         SkRect s, d;
2219
2220         s.fTop = srcY[y];
2221         s.fBottom = srcY[y+1];
2222         d.fTop = dstY[y];
2223         d.fBottom = dstY[y+1];
2224         for (int x = 0; x < 3; x++) {
2225             s.fLeft = srcX[x];
2226             s.fRight = srcX[x+1];
2227             d.fLeft = dstX[x];
2228             d.fRight = dstX[x+1];
2229             this->internalDrawBitmapRect(bitmap, &s, d, paint,
2230                                          kNone_DrawBitmapRectFlag);
2231         }
2232     }
2233 }
2234
2235 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
2236                               const SkRect& dst, const SkPaint* paint) {
2237     SkDEBUGCODE(bitmap.validate();)
2238
2239     // Need a device entry-point, so gpu can use a mesh
2240     this->internalDrawBitmapNine(bitmap, center, dst, paint);
2241 }
2242
2243 class SkDeviceFilteredPaint {
2244 public:
2245     SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2246         SkBaseDevice::TextFlags flags;
2247         if (device->filterTextFlags(paint, &flags)) {
2248             SkPaint* newPaint = fLazy.set(paint);
2249             newPaint->setFlags(flags.fFlags);
2250             newPaint->setHinting(flags.fHinting);
2251             fPaint = newPaint;
2252         } else {
2253             fPaint = &paint;
2254         }
2255     }
2256
2257     const SkPaint& paint() const { return *fPaint; }
2258
2259 private:
2260     const SkPaint*  fPaint;
2261     SkLazyPaint     fLazy;
2262 };
2263
2264 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2265                         const SkRect& r, SkScalar textSize) {
2266     if (paint.getStyle() == SkPaint::kFill_Style) {
2267         draw.fDevice->drawRect(draw, r, paint);
2268     } else {
2269         SkPaint p(paint);
2270         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2271         draw.fDevice->drawRect(draw, r, p);
2272     }
2273 }
2274
2275 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2276                                    const char text[], size_t byteLength,
2277                                    SkScalar x, SkScalar y) {
2278     SkASSERT(byteLength == 0 || text != NULL);
2279
2280     // nothing to draw
2281     if (text == NULL || byteLength == 0 ||
2282         draw.fClip->isEmpty() ||
2283         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2284         return;
2285     }
2286
2287     SkScalar    width = 0;
2288     SkPoint     start;
2289
2290     start.set(0, 0);    // to avoid warning
2291     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2292                             SkPaint::kStrikeThruText_Flag)) {
2293         width = paint.measureText(text, byteLength);
2294
2295         SkScalar offsetX = 0;
2296         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2297             offsetX = SkScalarHalf(width);
2298         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2299             offsetX = width;
2300         }
2301         start.set(x - offsetX, y);
2302     }
2303
2304     if (0 == width) {
2305         return;
2306     }
2307
2308     uint32_t flags = paint.getFlags();
2309
2310     if (flags & (SkPaint::kUnderlineText_Flag |
2311                  SkPaint::kStrikeThruText_Flag)) {
2312         SkScalar textSize = paint.getTextSize();
2313         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2314         SkRect   r;
2315
2316         r.fLeft = start.fX;
2317         r.fRight = start.fX + width;
2318
2319         if (flags & SkPaint::kUnderlineText_Flag) {
2320             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2321                                              start.fY);
2322             r.fTop = offset;
2323             r.fBottom = offset + height;
2324             DrawRect(draw, paint, r, textSize);
2325         }
2326         if (flags & SkPaint::kStrikeThruText_Flag) {
2327             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2328                                              start.fY);
2329             r.fTop = offset;
2330             r.fBottom = offset + height;
2331             DrawRect(draw, paint, r, textSize);
2332         }
2333     }
2334 }
2335
2336 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2337                           const SkPaint& paint) {
2338     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2339
2340     while (iter.next()) {
2341         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2342         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2343         DrawTextDecorations(iter, dfp.paint(),
2344                             static_cast<const char*>(text), byteLength, x, y);
2345     }
2346
2347     LOOPER_END
2348 }
2349
2350 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2351                              const SkPaint& paint) {
2352     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2353
2354     while (iter.next()) {
2355         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2356         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2357                                   dfp.paint());
2358     }
2359
2360     LOOPER_END
2361 }
2362
2363 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2364                               SkScalar constY, const SkPaint& paint) {
2365     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2366
2367     while (iter.next()) {
2368         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2369         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2370                                   dfp.paint());
2371     }
2372
2373     LOOPER_END
2374 }
2375
2376 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2377                                 const SkMatrix* matrix, const SkPaint& paint) {
2378     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2379
2380     while (iter.next()) {
2381         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2382                                      matrix, looper.paint());
2383     }
2384
2385     LOOPER_END
2386 }
2387
2388 // These will become non-virtual, so they always call the (virtual) onDraw... method
2389 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2390                         const SkPaint& paint) {
2391     this->onDrawText(text, byteLength, x, y, paint);
2392 }
2393 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2394                            const SkPaint& paint) {
2395     this->onDrawPosText(text, byteLength, pos, paint);
2396 }
2397 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2398                             SkScalar constY, const SkPaint& paint) {
2399     this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2400 }
2401 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2402                               const SkMatrix* matrix, const SkPaint& paint) {
2403     this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2404 }
2405
2406 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
2407                             const SkPoint verts[], const SkPoint texs[],
2408                             const SkColor colors[], SkXfermode* xmode,
2409                             const uint16_t indices[], int indexCount,
2410                             const SkPaint& paint) {
2411     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2412
2413     while (iter.next()) {
2414         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2415                                    colors, xmode, indices, indexCount,
2416                                    looper.paint());
2417     }
2418
2419     LOOPER_END
2420 }
2421
2422 //////////////////////////////////////////////////////////////////////////////
2423 // These methods are NOT virtual, and therefore must call back into virtual
2424 // methods, rather than actually drawing themselves.
2425 //////////////////////////////////////////////////////////////////////////////
2426
2427 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2428                         SkXfermode::Mode mode) {
2429     SkPaint paint;
2430
2431     paint.setARGB(a, r, g, b);
2432     if (SkXfermode::kSrcOver_Mode != mode) {
2433         paint.setXfermodeMode(mode);
2434     }
2435     this->drawPaint(paint);
2436 }
2437
2438 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2439     SkPaint paint;
2440
2441     paint.setColor(c);
2442     if (SkXfermode::kSrcOver_Mode != mode) {
2443         paint.setXfermodeMode(mode);
2444     }
2445     this->drawPaint(paint);
2446 }
2447
2448 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2449     SkPoint pt;
2450
2451     pt.set(x, y);
2452     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2453 }
2454
2455 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2456     SkPoint pt;
2457     SkPaint paint;
2458
2459     pt.set(x, y);
2460     paint.setColor(color);
2461     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2462 }
2463
2464 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2465                         const SkPaint& paint) {
2466     SkPoint pts[2];
2467
2468     pts[0].set(x0, y0);
2469     pts[1].set(x1, y1);
2470     this->drawPoints(kLines_PointMode, 2, pts, paint);
2471 }
2472
2473 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2474                               SkScalar right, SkScalar bottom,
2475                               const SkPaint& paint) {
2476     SkRect  r;
2477
2478     r.set(left, top, right, bottom);
2479     this->drawRect(r, paint);
2480 }
2481
2482 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2483                           const SkPaint& paint) {
2484     if (radius < 0) {
2485         radius = 0;
2486     }
2487
2488     SkRect  r;
2489     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2490     this->drawOval(r, paint);
2491 }
2492
2493 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2494                              const SkPaint& paint) {
2495     if (rx > 0 && ry > 0) {
2496         if (paint.canComputeFastBounds()) {
2497             SkRect storage;
2498             if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2499                 return;
2500             }
2501         }
2502         SkRRect rrect;
2503         rrect.setRectXY(r, rx, ry);
2504         this->drawRRect(rrect, paint);
2505     } else {
2506         this->drawRect(r, paint);
2507     }
2508 }
2509
2510 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2511                        SkScalar sweepAngle, bool useCenter,
2512                        const SkPaint& paint) {
2513     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2514         this->drawOval(oval, paint);
2515     } else {
2516         SkPath  path;
2517         if (useCenter) {
2518             path.moveTo(oval.centerX(), oval.centerY());
2519         }
2520         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2521         if (useCenter) {
2522             path.close();
2523         }
2524         this->drawPath(path, paint);
2525     }
2526 }
2527
2528 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2529                                 const SkPath& path, SkScalar hOffset,
2530                                 SkScalar vOffset, const SkPaint& paint) {
2531     SkMatrix    matrix;
2532
2533     matrix.setTranslate(hOffset, vOffset);
2534     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2535 }
2536
2537 ///////////////////////////////////////////////////////////////////////////////
2538 void SkCanvas::EXPERIMENTAL_optimize(SkPicture* picture) {
2539     SkBaseDevice* device = this->getDevice();
2540     if (NULL != device) {
2541         device->EXPERIMENTAL_optimize(picture);
2542     }
2543 }
2544
2545 void SkCanvas::EXPERIMENTAL_purge(SkPicture* picture) {
2546     SkBaseDevice* device = this->getTopDevice();
2547     if (NULL != device) {
2548         device->EXPERIMENTAL_purge(picture);
2549     }
2550 }
2551
2552 void SkCanvas::drawPicture(SkPicture& picture) {
2553     SkBaseDevice* device = this->getTopDevice();
2554     if (NULL != device) {
2555         // Canvas has to first give the device the opportunity to render
2556         // the picture itself.
2557         if (device->EXPERIMENTAL_drawPicture(this, &picture)) {
2558             return; // the device has rendered the entire picture
2559         }
2560     }
2561
2562     picture.draw(this);
2563 }
2564
2565 ///////////////////////////////////////////////////////////////////////////////
2566 ///////////////////////////////////////////////////////////////////////////////
2567
2568 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2569     SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2570
2571     SkASSERT(canvas);
2572
2573     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2574     fDone = !fImpl->next();
2575 }
2576
2577 SkCanvas::LayerIter::~LayerIter() {
2578     fImpl->~SkDrawIter();
2579 }
2580
2581 void SkCanvas::LayerIter::next() {
2582     fDone = !fImpl->next();
2583 }
2584
2585 SkBaseDevice* SkCanvas::LayerIter::device() const {
2586     return fImpl->getDevice();
2587 }
2588
2589 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2590     return fImpl->getMatrix();
2591 }
2592
2593 const SkPaint& SkCanvas::LayerIter::paint() const {
2594     const SkPaint* paint = fImpl->getPaint();
2595     if (NULL == paint) {
2596         paint = &fDefaultPaint;
2597     }
2598     return *paint;
2599 }
2600
2601 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2602 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2603 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2604
2605 ///////////////////////////////////////////////////////////////////////////////
2606
2607 SkCanvas::ClipVisitor::~ClipVisitor() { }
2608
2609 ///////////////////////////////////////////////////////////////////////////////
2610
2611 static bool supported_for_raster_canvas(const SkImageInfo& info) {
2612     switch (info.alphaType()) {
2613         case kPremul_SkAlphaType:
2614         case kOpaque_SkAlphaType:
2615             break;
2616         default:
2617             return false;
2618     }
2619
2620     switch (info.colorType()) {
2621         case kAlpha_8_SkColorType:
2622         case kRGB_565_SkColorType:
2623         case kN32_SkColorType:
2624             break;
2625         default:
2626             return false;
2627     }
2628
2629     return true;
2630 }
2631
2632 SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
2633     if (!supported_for_raster_canvas(info)) {
2634         return NULL;
2635     }
2636
2637     SkBitmap bitmap;
2638     if (!bitmap.allocPixels(info)) {
2639         return NULL;
2640     }
2641
2642     // should this functionality be moved into allocPixels()?
2643     if (!bitmap.info().isOpaque()) {
2644         bitmap.eraseColor(0);
2645     }
2646     return SkNEW_ARGS(SkCanvas, (bitmap));
2647 }
2648
2649 SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2650     if (!supported_for_raster_canvas(info)) {
2651         return NULL;
2652     }
2653
2654     SkBitmap bitmap;
2655     if (!bitmap.installPixels(info, pixels, rowBytes)) {
2656         return NULL;
2657     }
2658     return SkNEW_ARGS(SkCanvas, (bitmap));
2659 }