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