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