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