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