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