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