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