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