SkCanvas.cpp revision 8432808ad8898ac7137bc7ce1d9df6005e866401
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 "SkDrawable.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        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
1780        // To prevent accidental rejecting at this stage, we have to sort it before we check.
1781        SkRect tmp(r);
1782        tmp.sort();
1783
1784        bounds = &paint.computeFastBounds(tmp, &storage);
1785        if (this->quickReject(*bounds)) {
1786            return;
1787        }
1788    }
1789
1790    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1791
1792    while (iter.next()) {
1793        iter.fDevice->drawRect(iter, r, looper.paint());
1794    }
1795
1796    LOOPER_END
1797}
1798
1799void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
1800    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
1801    SkRect storage;
1802    const SkRect* bounds = NULL;
1803    if (paint.canComputeFastBounds()) {
1804        bounds = &paint.computeFastBounds(oval, &storage);
1805        if (this->quickReject(*bounds)) {
1806            return;
1807        }
1808    }
1809
1810    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1811
1812    while (iter.next()) {
1813        iter.fDevice->drawOval(iter, oval, looper.paint());
1814    }
1815
1816    LOOPER_END
1817}
1818
1819void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
1820    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
1821    SkRect storage;
1822    const SkRect* bounds = NULL;
1823    if (paint.canComputeFastBounds()) {
1824        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1825        if (this->quickReject(*bounds)) {
1826            return;
1827        }
1828    }
1829
1830    if (rrect.isRect()) {
1831        // call the non-virtual version
1832        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1833        return;
1834    } else if (rrect.isOval()) {
1835        // call the non-virtual version
1836        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1837        return;
1838    }
1839
1840    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1841
1842    while (iter.next()) {
1843        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1844    }
1845
1846    LOOPER_END
1847}
1848
1849void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1850                            const SkPaint& paint) {
1851    SkRect storage;
1852    const SkRect* bounds = NULL;
1853    if (paint.canComputeFastBounds()) {
1854        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1855        if (this->quickReject(*bounds)) {
1856            return;
1857        }
1858    }
1859
1860    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1861
1862    while (iter.next()) {
1863        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1864    }
1865
1866    LOOPER_END
1867}
1868
1869void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
1870    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
1871    if (!path.isFinite()) {
1872        return;
1873    }
1874
1875    SkRect storage;
1876    const SkRect* bounds = NULL;
1877    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1878        const SkRect& pathBounds = path.getBounds();
1879        bounds = &paint.computeFastBounds(pathBounds, &storage);
1880        if (this->quickReject(*bounds)) {
1881            return;
1882        }
1883    }
1884
1885    const SkRect& r = path.getBounds();
1886    if (r.width() <= 0 && r.height() <= 0) {
1887        if (path.isInverseFillType()) {
1888            this->internalDrawPaint(paint);
1889        }
1890        return;
1891    }
1892
1893    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1894
1895    while (iter.next()) {
1896        iter.fDevice->drawPath(iter, path, looper.paint());
1897    }
1898
1899    LOOPER_END
1900}
1901
1902void SkCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1903    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
1904    image->draw(this, dx, dy, paint);
1905}
1906
1907void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1908                               const SkPaint* paint) {
1909    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
1910    image->drawRect(this, src, dst, paint);
1911}
1912
1913void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
1914    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
1915    SkDEBUGCODE(bitmap.validate();)
1916
1917    if (NULL == paint || paint->canComputeFastBounds()) {
1918        SkRect bounds = {
1919            x, y,
1920            x + SkIntToScalar(bitmap.width()),
1921            y + SkIntToScalar(bitmap.height())
1922        };
1923        if (paint) {
1924            (void)paint->computeFastBounds(bounds, &bounds);
1925        }
1926        if (this->quickReject(bounds)) {
1927            return;
1928        }
1929    }
1930
1931    SkMatrix matrix;
1932    matrix.setTranslate(x, y);
1933    this->internalDrawBitmap(bitmap, matrix, paint);
1934}
1935
1936// this one is non-virtual, so it can be called safely by other canvas apis
1937void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1938                                      const SkRect& dst, const SkPaint* paint,
1939                                      DrawBitmapRectFlags flags) {
1940    if (bitmap.drawsNothing() || dst.isEmpty()) {
1941        return;
1942    }
1943
1944    SkRect storage;
1945    const SkRect* bounds = &dst;
1946    if (NULL == paint || paint->canComputeFastBounds()) {
1947        if (paint) {
1948            bounds = &paint->computeFastBounds(dst, &storage);
1949        }
1950        if (this->quickReject(*bounds)) {
1951            return;
1952        }
1953    }
1954
1955    SkLazyPaint lazy;
1956    if (NULL == paint) {
1957        paint = lazy.init();
1958    }
1959
1960    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1961
1962    while (iter.next()) {
1963        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1964    }
1965
1966    LOOPER_END
1967}
1968
1969void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1970                                const SkPaint* paint, DrawBitmapRectFlags flags) {
1971    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
1972    SkDEBUGCODE(bitmap.validate();)
1973    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
1974}
1975
1976void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1977                                      const SkIRect& center, const SkRect& dst,
1978                                      const SkPaint* paint) {
1979    if (bitmap.drawsNothing()) {
1980        return;
1981    }
1982    if (NULL == paint || paint->canComputeFastBounds()) {
1983        SkRect storage;
1984        const SkRect* bounds = &dst;
1985        if (paint) {
1986            bounds = &paint->computeFastBounds(dst, &storage);
1987        }
1988        if (this->quickReject(*bounds)) {
1989            return;
1990        }
1991    }
1992
1993    const int32_t w = bitmap.width();
1994    const int32_t h = bitmap.height();
1995
1996    SkIRect c = center;
1997    // pin center to the bounds of the bitmap
1998    c.fLeft = SkMax32(0, center.fLeft);
1999    c.fTop = SkMax32(0, center.fTop);
2000    c.fRight = SkPin32(center.fRight, c.fLeft, w);
2001    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
2002
2003    const SkScalar srcX[4] = {
2004        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
2005    };
2006    const SkScalar srcY[4] = {
2007        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
2008    };
2009    SkScalar dstX[4] = {
2010        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
2011        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
2012    };
2013    SkScalar dstY[4] = {
2014        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
2015        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
2016    };
2017
2018    if (dstX[1] > dstX[2]) {
2019        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
2020        dstX[2] = dstX[1];
2021    }
2022
2023    if (dstY[1] > dstY[2]) {
2024        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2025        dstY[2] = dstY[1];
2026    }
2027
2028    for (int y = 0; y < 3; y++) {
2029        SkRect s, d;
2030
2031        s.fTop = srcY[y];
2032        s.fBottom = srcY[y+1];
2033        d.fTop = dstY[y];
2034        d.fBottom = dstY[y+1];
2035        for (int x = 0; x < 3; x++) {
2036            s.fLeft = srcX[x];
2037            s.fRight = srcX[x+1];
2038            d.fLeft = dstX[x];
2039            d.fRight = dstX[x+1];
2040            this->internalDrawBitmapRect(bitmap, &s, d, paint,
2041                                         kNone_DrawBitmapRectFlag);
2042        }
2043    }
2044}
2045
2046void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2047                                const SkPaint* paint) {
2048    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2049    SkDEBUGCODE(bitmap.validate();)
2050
2051    // Need a device entry-point, so gpu can use a mesh
2052    this->internalDrawBitmapNine(bitmap, center, dst, paint);
2053}
2054
2055class SkDeviceFilteredPaint {
2056public:
2057    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2058        uint32_t filteredFlags = device->filterTextFlags(paint);
2059        if (filteredFlags != paint.getFlags()) {
2060            SkPaint* newPaint = fLazy.set(paint);
2061            newPaint->setFlags(filteredFlags);
2062            fPaint = newPaint;
2063        } else {
2064            fPaint = &paint;
2065        }
2066    }
2067
2068    const SkPaint& paint() const { return *fPaint; }
2069
2070private:
2071    const SkPaint*  fPaint;
2072    SkLazyPaint     fLazy;
2073};
2074
2075void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2076                        const SkRect& r, SkScalar textSize) {
2077    if (paint.getStyle() == SkPaint::kFill_Style) {
2078        draw.fDevice->drawRect(draw, r, paint);
2079    } else {
2080        SkPaint p(paint);
2081        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2082        draw.fDevice->drawRect(draw, r, p);
2083    }
2084}
2085
2086void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2087                                   const char text[], size_t byteLength,
2088                                   SkScalar x, SkScalar y) {
2089    SkASSERT(byteLength == 0 || text != NULL);
2090
2091    // nothing to draw
2092    if (text == NULL || byteLength == 0 ||
2093        draw.fClip->isEmpty() ||
2094        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2095        return;
2096    }
2097
2098    SkScalar    width = 0;
2099    SkPoint     start;
2100
2101    start.set(0, 0);    // to avoid warning
2102    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2103                            SkPaint::kStrikeThruText_Flag)) {
2104        width = paint.measureText(text, byteLength);
2105
2106        SkScalar offsetX = 0;
2107        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2108            offsetX = SkScalarHalf(width);
2109        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2110            offsetX = width;
2111        }
2112        start.set(x - offsetX, y);
2113    }
2114
2115    if (0 == width) {
2116        return;
2117    }
2118
2119    uint32_t flags = paint.getFlags();
2120
2121    if (flags & (SkPaint::kUnderlineText_Flag |
2122                 SkPaint::kStrikeThruText_Flag)) {
2123        SkScalar textSize = paint.getTextSize();
2124        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2125        SkRect   r;
2126
2127        r.fLeft = start.fX;
2128        r.fRight = start.fX + width;
2129
2130        if (flags & SkPaint::kUnderlineText_Flag) {
2131            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2132                                             start.fY);
2133            r.fTop = offset;
2134            r.fBottom = offset + height;
2135            DrawRect(draw, paint, r, textSize);
2136        }
2137        if (flags & SkPaint::kStrikeThruText_Flag) {
2138            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2139                                             start.fY);
2140            r.fTop = offset;
2141            r.fBottom = offset + height;
2142            DrawRect(draw, paint, r, textSize);
2143        }
2144    }
2145}
2146
2147void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2148                          const SkPaint& paint) {
2149    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2150
2151    while (iter.next()) {
2152        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2153        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2154        DrawTextDecorations(iter, dfp.paint(),
2155                            static_cast<const char*>(text), byteLength, x, y);
2156    }
2157
2158    LOOPER_END
2159}
2160
2161void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2162                             const SkPaint& paint) {
2163    SkPoint textOffset = SkPoint::Make(0, 0);
2164
2165    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2166
2167    while (iter.next()) {
2168        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2169        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2170                                  dfp.paint());
2171    }
2172
2173    LOOPER_END
2174}
2175
2176void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2177                              SkScalar constY, const SkPaint& paint) {
2178
2179    SkPoint textOffset = SkPoint::Make(0, constY);
2180
2181    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2182
2183    while (iter.next()) {
2184        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2185        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2186                                  dfp.paint());
2187    }
2188
2189    LOOPER_END
2190}
2191
2192void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2193                                const SkMatrix* matrix, const SkPaint& paint) {
2194    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2195
2196    while (iter.next()) {
2197        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2198                                     matrix, looper.paint());
2199    }
2200
2201    LOOPER_END
2202}
2203
2204void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2205                              const SkPaint& paint) {
2206
2207    if (paint.canComputeFastBounds()) {
2208        SkRect storage;
2209
2210        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
2211            return;
2212        }
2213    }
2214
2215    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2216
2217    while (iter.next()) {
2218        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2219        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
2220    }
2221
2222    LOOPER_END
2223}
2224
2225// These will become non-virtual, so they always call the (virtual) onDraw... method
2226void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2227                        const SkPaint& paint) {
2228    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2229    this->onDrawText(text, byteLength, x, y, paint);
2230}
2231void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2232                           const SkPaint& paint) {
2233    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2234    this->onDrawPosText(text, byteLength, pos, paint);
2235}
2236void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2237                            SkScalar constY, const SkPaint& paint) {
2238    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2239    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2240}
2241void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2242                              const SkMatrix* matrix, const SkPaint& paint) {
2243    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2244    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2245}
2246void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2247                            const SkPaint& paint) {
2248    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2249    if (blob) {
2250        this->onDrawTextBlob(blob, x, y, paint);
2251    }
2252}
2253
2254void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
2255                              const SkPoint verts[], const SkPoint texs[],
2256                              const SkColor colors[], SkXfermode* xmode,
2257                              const uint16_t indices[], int indexCount,
2258                              const SkPaint& paint) {
2259    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2260    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2261
2262    while (iter.next()) {
2263        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2264                                   colors, xmode, indices, indexCount,
2265                                   looper.paint());
2266    }
2267
2268    LOOPER_END
2269}
2270
2271void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2272                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2273    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2274    if (NULL == cubics) {
2275        return;
2276    }
2277
2278    // Since a patch is always within the convex hull of the control points, we discard it when its
2279    // bounding rectangle is completely outside the current clip.
2280    SkRect bounds;
2281    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2282    if (this->quickReject(bounds)) {
2283        return;
2284    }
2285
2286    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2287}
2288
2289void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2290                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2291
2292    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2293
2294    while (iter.next()) {
2295        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2296    }
2297
2298    LOOPER_END
2299}
2300
2301void SkCanvas::drawDrawable(SkDrawable* dr) {
2302    if (dr && !this->quickReject(dr->getBounds())) {
2303        this->onDrawDrawable(dr);
2304    }
2305}
2306
2307void SkCanvas::onDrawDrawable(SkDrawable* dr) {
2308    dr->draw(this);
2309}
2310
2311//////////////////////////////////////////////////////////////////////////////
2312// These methods are NOT virtual, and therefore must call back into virtual
2313// methods, rather than actually drawing themselves.
2314//////////////////////////////////////////////////////////////////////////////
2315
2316void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2317                        SkXfermode::Mode mode) {
2318    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2319    SkPaint paint;
2320
2321    paint.setARGB(a, r, g, b);
2322    if (SkXfermode::kSrcOver_Mode != mode) {
2323        paint.setXfermodeMode(mode);
2324    }
2325    this->drawPaint(paint);
2326}
2327
2328void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2329    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2330    SkPaint paint;
2331
2332    paint.setColor(c);
2333    if (SkXfermode::kSrcOver_Mode != mode) {
2334        paint.setXfermodeMode(mode);
2335    }
2336    this->drawPaint(paint);
2337}
2338
2339void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2340    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2341    SkPoint pt;
2342
2343    pt.set(x, y);
2344    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2345}
2346
2347void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2348    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2349    SkPoint pt;
2350    SkPaint paint;
2351
2352    pt.set(x, y);
2353    paint.setColor(color);
2354    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2355}
2356
2357void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2358                        const SkPaint& paint) {
2359    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2360    SkPoint pts[2];
2361
2362    pts[0].set(x0, y0);
2363    pts[1].set(x1, y1);
2364    this->drawPoints(kLines_PointMode, 2, pts, paint);
2365}
2366
2367void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2368                              SkScalar right, SkScalar bottom,
2369                              const SkPaint& paint) {
2370    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2371    SkRect  r;
2372
2373    r.set(left, top, right, bottom);
2374    this->drawRect(r, paint);
2375}
2376
2377void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2378                          const SkPaint& paint) {
2379    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2380    if (radius < 0) {
2381        radius = 0;
2382    }
2383
2384    SkRect  r;
2385    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2386    this->drawOval(r, paint);
2387}
2388
2389void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2390                             const SkPaint& paint) {
2391    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2392    if (rx > 0 && ry > 0) {
2393        if (paint.canComputeFastBounds()) {
2394            SkRect storage;
2395            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2396                return;
2397            }
2398        }
2399        SkRRect rrect;
2400        rrect.setRectXY(r, rx, ry);
2401        this->drawRRect(rrect, paint);
2402    } else {
2403        this->drawRect(r, paint);
2404    }
2405}
2406
2407void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2408                       SkScalar sweepAngle, bool useCenter,
2409                       const SkPaint& paint) {
2410    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2411    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2412        this->drawOval(oval, paint);
2413    } else {
2414        SkPath  path;
2415        if (useCenter) {
2416            path.moveTo(oval.centerX(), oval.centerY());
2417        }
2418        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2419        if (useCenter) {
2420            path.close();
2421        }
2422        this->drawPath(path, paint);
2423    }
2424}
2425
2426void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2427                                const SkPath& path, SkScalar hOffset,
2428                                SkScalar vOffset, const SkPaint& paint) {
2429    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2430    SkMatrix    matrix;
2431
2432    matrix.setTranslate(hOffset, vOffset);
2433    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2434}
2435
2436///////////////////////////////////////////////////////////////////////////////
2437void SkCanvas::drawPicture(const SkPicture* picture) {
2438    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2439    if (picture) {
2440        this->onDrawPicture(picture, NULL, NULL);
2441    }
2442}
2443
2444void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2445    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)");
2446    if (picture) {
2447        if (matrix && matrix->isIdentity()) {
2448            matrix = NULL;
2449        }
2450        this->onDrawPicture(picture, matrix, paint);
2451    }
2452}
2453
2454void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2455                             const SkPaint* paint) {
2456    SkBaseDevice* device = this->getTopDevice();
2457    if (device) {
2458        // Canvas has to first give the device the opportunity to render
2459        // the picture itself.
2460        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2461            return; // the device has rendered the entire picture
2462        }
2463    }
2464
2465    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2466
2467    picture->playback(this);
2468}
2469
2470///////////////////////////////////////////////////////////////////////////////
2471///////////////////////////////////////////////////////////////////////////////
2472
2473SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2474    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2475
2476    SkASSERT(canvas);
2477
2478    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2479    fDone = !fImpl->next();
2480}
2481
2482SkCanvas::LayerIter::~LayerIter() {
2483    fImpl->~SkDrawIter();
2484}
2485
2486void SkCanvas::LayerIter::next() {
2487    fDone = !fImpl->next();
2488}
2489
2490SkBaseDevice* SkCanvas::LayerIter::device() const {
2491    return fImpl->getDevice();
2492}
2493
2494const SkMatrix& SkCanvas::LayerIter::matrix() const {
2495    return fImpl->getMatrix();
2496}
2497
2498const SkPaint& SkCanvas::LayerIter::paint() const {
2499    const SkPaint* paint = fImpl->getPaint();
2500    if (NULL == paint) {
2501        paint = &fDefaultPaint;
2502    }
2503    return *paint;
2504}
2505
2506const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2507int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2508int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2509
2510///////////////////////////////////////////////////////////////////////////////
2511
2512SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2513
2514///////////////////////////////////////////////////////////////////////////////
2515
2516static bool supported_for_raster_canvas(const SkImageInfo& info) {
2517    switch (info.alphaType()) {
2518        case kPremul_SkAlphaType:
2519        case kOpaque_SkAlphaType:
2520            break;
2521        default:
2522            return false;
2523    }
2524
2525    switch (info.colorType()) {
2526        case kAlpha_8_SkColorType:
2527        case kRGB_565_SkColorType:
2528        case kN32_SkColorType:
2529            break;
2530        default:
2531            return false;
2532    }
2533
2534    return true;
2535}
2536
2537SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2538    if (!supported_for_raster_canvas(info)) {
2539        return NULL;
2540    }
2541
2542    SkBitmap bitmap;
2543    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2544        return NULL;
2545    }
2546    return SkNEW_ARGS(SkCanvas, (bitmap));
2547}
2548
2549///////////////////////////////////////////////////////////////////////////////
2550
2551SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2552                                                 const SkPaint* paint, const SkRect& bounds)
2553    : fCanvas(canvas)
2554    , fSaveCount(canvas->getSaveCount())
2555{
2556    if (paint) {
2557        SkRect newBounds = bounds;
2558        if (matrix) {
2559            matrix->mapRect(&newBounds);
2560        }
2561        canvas->saveLayer(&newBounds, paint);
2562    } else if (matrix) {
2563        canvas->save();
2564    }
2565
2566    if (matrix) {
2567        canvas->concat(*matrix);
2568    }
2569}
2570
2571SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2572    fCanvas->restoreToCount(fSaveCount);
2573}
2574