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