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