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