SkCanvas.cpp revision d0d37cace08f12abf8d316e6949e947551d418e6
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    device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, geo), paint);
940    if (NULL == device) {
941        SkErrorInternals::SetError( kInternalError_SkError,
942                                    "Unable to create device for layer.");
943        return;
944    }
945
946    device->setOrigin(ir.fLeft, ir.fTop);
947    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip));
948    device->unref();
949
950    layer->fNext = fMCRec->fTopLayer;
951    fMCRec->fLayer = layer;
952    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
953}
954
955int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
956    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
957}
958
959int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
960                             SaveFlags flags) {
961    if (0xFF == alpha) {
962        return this->saveLayer(bounds, NULL, flags);
963    } else {
964        SkPaint tmpPaint;
965        tmpPaint.setAlpha(alpha);
966        return this->saveLayer(bounds, &tmpPaint, flags);
967    }
968}
969
970void SkCanvas::internalRestore() {
971    SkASSERT(fMCStack.count() != 0);
972
973    fDeviceCMDirty = true;
974    fCachedLocalClipBoundsDirty = true;
975
976    fClipStack->restore();
977
978    // reserve our layer (if any)
979    DeviceCM* layer = fMCRec->fLayer;   // may be null
980    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
981    fMCRec->fLayer = NULL;
982
983    // now do the normal restore()
984    fMCRec->~MCRec();       // balanced in save()
985    fMCStack.pop_back();
986    fMCRec = (MCRec*)fMCStack.back();
987
988    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
989        since if we're being recorded, we don't want to record this (the
990        recorder will have already recorded the restore).
991    */
992    if (layer) {
993        if (layer->fNext) {
994            const SkIPoint& origin = layer->fDevice->getOrigin();
995            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
996                                     layer->fPaint);
997            // reset this, since internalDrawDevice will have set it to true
998            fDeviceCMDirty = true;
999        }
1000        SkDELETE(layer);
1001    }
1002}
1003
1004SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1005    if (NULL == props) {
1006        props = &fProps;
1007    }
1008    return this->onNewSurface(info, *props);
1009}
1010
1011SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1012    SkBaseDevice* dev = this->getDevice();
1013    return dev ? dev->newSurface(info, props) : NULL;
1014}
1015
1016SkImageInfo SkCanvas::imageInfo() const {
1017    SkBaseDevice* dev = this->getDevice();
1018    if (dev) {
1019        return dev->imageInfo();
1020    } else {
1021        return SkImageInfo::MakeUnknown(0, 0);
1022    }
1023}
1024
1025const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1026    return this->onPeekPixels(info, rowBytes);
1027}
1028
1029const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1030    SkBaseDevice* dev = this->getDevice();
1031    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1032}
1033
1034void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1035    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
1036    if (pixels && origin) {
1037        *origin = this->getTopDevice(false)->getOrigin();
1038    }
1039    return pixels;
1040}
1041
1042void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
1043    SkBaseDevice* dev = this->getTopDevice();
1044    return dev ? dev->accessPixels(info, rowBytes) : NULL;
1045}
1046
1047SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1048    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1049    if (NULL == fAddr) {
1050        fInfo = canvas->imageInfo();
1051        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1052            return; // failure, fAddr is NULL
1053        }
1054        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1055            return; // failure, fAddr is NULL
1056        }
1057        fAddr = fBitmap.getPixels();
1058        fRowBytes = fBitmap.rowBytes();
1059    }
1060    SkASSERT(fAddr);    // success
1061}
1062
1063bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1064    if (fAddr) {
1065        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1066    } else {
1067        bitmap->reset();
1068        return false;
1069    }
1070}
1071
1072/////////////////////////////////////////////////////////////////////////////
1073void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1074                                const SkMatrix& matrix, const SkPaint* paint) {
1075    if (bitmap.drawsNothing()) {
1076        return;
1077    }
1078
1079    SkLazyPaint lazy;
1080    if (NULL == paint) {
1081        paint = lazy.init();
1082    }
1083
1084    SkDEBUGCODE(bitmap.validate();)
1085
1086    SkRect storage;
1087    const SkRect* bounds = NULL;
1088    if (paint && paint->canComputeFastBounds()) {
1089        bitmap.getBounds(&storage);
1090        matrix.mapRect(&storage);
1091        bounds = &paint->computeFastBounds(storage, &storage);
1092    }
1093
1094    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1095
1096    while (iter.next()) {
1097        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1098    }
1099
1100    LOOPER_END
1101}
1102
1103void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1104                                  const SkPaint* paint) {
1105    SkPaint tmp;
1106    if (NULL == paint) {
1107        paint = &tmp;
1108    }
1109
1110    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1111    while (iter.next()) {
1112        SkBaseDevice* dstDev = iter.fDevice;
1113        paint = &looper.paint();
1114        SkImageFilter* filter = paint->getImageFilter();
1115        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1116        if (filter && !dstDev->canHandleImageFilter(filter)) {
1117            SkDeviceImageFilterProxy proxy(dstDev, fProps);
1118            SkBitmap dst;
1119            SkIPoint offset = SkIPoint::Make(0, 0);
1120            const SkBitmap& src = srcDev->accessBitmap(false);
1121            SkMatrix matrix = *iter.fMatrix;
1122            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1123            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1124            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1125            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1126            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1127                SkPaint tmpUnfiltered(*paint);
1128                tmpUnfiltered.setImageFilter(NULL);
1129                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1130                                   tmpUnfiltered);
1131            }
1132        } else {
1133            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1134        }
1135    }
1136    LOOPER_END
1137}
1138
1139void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
1140    if (gTreatSpriteAsBitmap) {
1141        this->save();
1142        this->resetMatrix();
1143        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
1144        this->restore();
1145        return;
1146    }
1147
1148    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
1149    if (bitmap.drawsNothing()) {
1150        return;
1151    }
1152    SkDEBUGCODE(bitmap.validate();)
1153
1154    SkPaint tmp;
1155    if (NULL == paint) {
1156        paint = &tmp;
1157    }
1158
1159    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1160
1161    while (iter.next()) {
1162        paint = &looper.paint();
1163        SkImageFilter* filter = paint->getImageFilter();
1164        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1165        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1166            SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
1167            SkBitmap dst;
1168            SkIPoint offset = SkIPoint::Make(0, 0);
1169            SkMatrix matrix = *iter.fMatrix;
1170            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1171            const SkIRect clipBounds = bitmap.bounds();
1172            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
1173            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1174            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1175                SkPaint tmpUnfiltered(*paint);
1176                tmpUnfiltered.setImageFilter(NULL);
1177                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1178                                         tmpUnfiltered);
1179            }
1180        } else {
1181            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1182        }
1183    }
1184    LOOPER_END
1185}
1186
1187/////////////////////////////////////////////////////////////////////////////
1188void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1189    SkMatrix m;
1190    m.setTranslate(dx, dy);
1191    this->concat(m);
1192}
1193
1194void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1195    SkMatrix m;
1196    m.setScale(sx, sy);
1197    this->concat(m);
1198}
1199
1200void SkCanvas::rotate(SkScalar degrees) {
1201    SkMatrix m;
1202    m.setRotate(degrees);
1203    this->concat(m);
1204}
1205
1206void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1207    SkMatrix m;
1208    m.setSkew(sx, sy);
1209    this->concat(m);
1210}
1211
1212void SkCanvas::concat(const SkMatrix& matrix) {
1213    if (matrix.isIdentity()) {
1214        return;
1215    }
1216
1217    this->checkForDeferredSave();
1218    fDeviceCMDirty = true;
1219    fCachedLocalClipBoundsDirty = true;
1220    fMCRec->fMatrix.preConcat(matrix);
1221
1222    this->didConcat(matrix);
1223}
1224
1225void SkCanvas::setMatrix(const SkMatrix& matrix) {
1226    this->checkForDeferredSave();
1227    fDeviceCMDirty = true;
1228    fCachedLocalClipBoundsDirty = true;
1229    fMCRec->fMatrix = matrix;
1230    this->didSetMatrix(matrix);
1231}
1232
1233void SkCanvas::resetMatrix() {
1234    SkMatrix matrix;
1235
1236    matrix.reset();
1237    this->setMatrix(matrix);
1238}
1239
1240//////////////////////////////////////////////////////////////////////////////
1241
1242void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1243    this->checkForDeferredSave();
1244    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1245    this->onClipRect(rect, op, edgeStyle);
1246}
1247
1248void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1249#ifdef SK_ENABLE_CLIP_QUICKREJECT
1250    if (SkRegion::kIntersect_Op == op) {
1251        if (fMCRec->fRasterClip.isEmpty()) {
1252            return false;
1253        }
1254
1255        if (this->quickReject(rect)) {
1256            fDeviceCMDirty = true;
1257            fCachedLocalClipBoundsDirty = true;
1258
1259            fClipStack.clipEmpty();
1260            return fMCRec->fRasterClip.setEmpty();
1261        }
1262    }
1263#endif
1264
1265    AutoValidateClip avc(this);
1266
1267    fDeviceCMDirty = true;
1268    fCachedLocalClipBoundsDirty = true;
1269    if (!fAllowSoftClip) {
1270        edgeStyle = kHard_ClipEdgeStyle;
1271    }
1272
1273    if (fMCRec->fMatrix.rectStaysRect()) {
1274        // for these simpler matrices, we can stay a rect even after applying
1275        // the matrix. This means we don't have to a) make a path, and b) tell
1276        // the region code to scan-convert the path, only to discover that it
1277        // is really just a rect.
1278        SkRect      r;
1279
1280        fMCRec->fMatrix.mapRect(&r, rect);
1281        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1282        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
1283    } else {
1284        // since we're rotated or some such thing, we convert the rect to a path
1285        // and clip against that, since it can handle any matrix. However, to
1286        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1287        // we explicitly call "our" version of clipPath.
1288        SkPath  path;
1289
1290        path.addRect(rect);
1291        this->SkCanvas::onClipPath(path, op, edgeStyle);
1292    }
1293}
1294
1295static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
1296                            SkRegion::Op op, bool doAA) {
1297    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1298}
1299
1300void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1301    this->checkForDeferredSave();
1302    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1303    if (rrect.isRect()) {
1304        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1305    } else {
1306        this->onClipRRect(rrect, op, edgeStyle);
1307    }
1308}
1309
1310void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1311    SkRRect transformedRRect;
1312    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1313        AutoValidateClip avc(this);
1314
1315        fDeviceCMDirty = true;
1316        fCachedLocalClipBoundsDirty = true;
1317        if (!fAllowSoftClip) {
1318            edgeStyle = kHard_ClipEdgeStyle;
1319        }
1320
1321        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1322
1323        SkPath devPath;
1324        devPath.addRRect(transformedRRect);
1325
1326        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1327        return;
1328    }
1329
1330    SkPath path;
1331    path.addRRect(rrect);
1332    // call the non-virtual version
1333    this->SkCanvas::onClipPath(path, op, edgeStyle);
1334}
1335
1336void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1337    this->checkForDeferredSave();
1338    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1339    SkRect r;
1340    if (!path.isInverseFillType() && path.isRect(&r)) {
1341        this->onClipRect(r, op, edgeStyle);
1342    } else {
1343        this->onClipPath(path, op, edgeStyle);
1344    }
1345}
1346
1347void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1348#ifdef SK_ENABLE_CLIP_QUICKREJECT
1349    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1350        if (fMCRec->fRasterClip.isEmpty()) {
1351            return false;
1352        }
1353
1354        if (this->quickReject(path.getBounds())) {
1355            fDeviceCMDirty = true;
1356            fCachedLocalClipBoundsDirty = true;
1357
1358            fClipStack.clipEmpty();
1359            return fMCRec->fRasterClip.setEmpty();
1360        }
1361    }
1362#endif
1363
1364    AutoValidateClip avc(this);
1365
1366    fDeviceCMDirty = true;
1367    fCachedLocalClipBoundsDirty = true;
1368    if (!fAllowSoftClip) {
1369        edgeStyle = kHard_ClipEdgeStyle;
1370    }
1371
1372    SkPath devPath;
1373    path.transform(fMCRec->fMatrix, &devPath);
1374
1375    // Check if the transfomation, or the original path itself
1376    // made us empty. Note this can also happen if we contained NaN
1377    // values. computing the bounds detects this, and will set our
1378    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1379    if (devPath.getBounds().isEmpty()) {
1380        // resetting the path will remove any NaN or other wanky values
1381        // that might upset our scan converter.
1382        devPath.reset();
1383    }
1384
1385    // if we called path.swap() we could avoid a deep copy of this path
1386    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1387
1388    if (fAllowSimplifyClip) {
1389        bool clipIsAA = getClipStack()->asPath(&devPath);
1390        if (clipIsAA) {
1391            edgeStyle = kSoft_ClipEdgeStyle;
1392        }
1393
1394        op = SkRegion::kReplace_Op;
1395    }
1396
1397    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1398}
1399
1400void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1401    this->checkForDeferredSave();
1402    this->onClipRegion(rgn, op);
1403}
1404
1405void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1406    AutoValidateClip avc(this);
1407
1408    fDeviceCMDirty = true;
1409    fCachedLocalClipBoundsDirty = true;
1410
1411    // todo: signal fClipStack that we have a region, and therefore (I guess)
1412    // we have to ignore it, and use the region directly?
1413    fClipStack->clipDevRect(rgn.getBounds(), op);
1414
1415    fMCRec->fRasterClip.op(rgn, op);
1416}
1417
1418#ifdef SK_DEBUG
1419void SkCanvas::validateClip() const {
1420    // construct clipRgn from the clipstack
1421    const SkBaseDevice* device = this->getDevice();
1422    if (!device) {
1423        SkASSERT(this->isClipEmpty());
1424        return;
1425    }
1426
1427    SkIRect ir;
1428    ir.set(0, 0, device->width(), device->height());
1429    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1430
1431    SkClipStack::B2TIter                iter(*fClipStack);
1432    const SkClipStack::Element* element;
1433    while ((element = iter.next()) != NULL) {
1434        switch (element->getType()) {
1435            case SkClipStack::Element::kRect_Type:
1436                element->getRect().round(&ir);
1437                tmpClip.op(ir, element->getOp());
1438                break;
1439            case SkClipStack::Element::kEmpty_Type:
1440                tmpClip.setEmpty();
1441                break;
1442            default: {
1443                SkPath path;
1444                element->asPath(&path);
1445                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
1446                break;
1447            }
1448        }
1449    }
1450}
1451#endif
1452
1453void SkCanvas::replayClips(ClipVisitor* visitor) const {
1454    SkClipStack::B2TIter                iter(*fClipStack);
1455    const SkClipStack::Element*         element;
1456
1457    while ((element = iter.next()) != NULL) {
1458        element->replay(visitor);
1459    }
1460}
1461
1462///////////////////////////////////////////////////////////////////////////////
1463
1464bool SkCanvas::isClipEmpty() const {
1465    return fMCRec->fRasterClip.isEmpty();
1466}
1467
1468bool SkCanvas::isClipRect() const {
1469    return fMCRec->fRasterClip.isRect();
1470}
1471
1472bool SkCanvas::quickReject(const SkRect& rect) const {
1473    if (!rect.isFinite())
1474        return true;
1475
1476    if (fMCRec->fRasterClip.isEmpty()) {
1477        return true;
1478    }
1479
1480    if (fMCRec->fMatrix.hasPerspective()) {
1481        SkRect dst;
1482        fMCRec->fMatrix.mapRect(&dst, rect);
1483        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1484    } else {
1485        const SkRect& clipR = this->getLocalClipBounds();
1486
1487        // for speed, do the most likely reject compares first
1488        // TODO: should we use | instead, or compare all 4 at once?
1489        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1490            return true;
1491        }
1492        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1493            return true;
1494        }
1495        return false;
1496    }
1497}
1498
1499bool SkCanvas::quickReject(const SkPath& path) const {
1500    return path.isEmpty() || this->quickReject(path.getBounds());
1501}
1502
1503bool SkCanvas::getClipBounds(SkRect* bounds) const {
1504    SkIRect ibounds;
1505    if (!this->getClipDeviceBounds(&ibounds)) {
1506        return false;
1507    }
1508
1509    SkMatrix inverse;
1510    // if we can't invert the CTM, we can't return local clip bounds
1511    if (!fMCRec->fMatrix.invert(&inverse)) {
1512        if (bounds) {
1513            bounds->setEmpty();
1514        }
1515        return false;
1516    }
1517
1518    if (bounds) {
1519        SkRect r;
1520        // adjust it outwards in case we are antialiasing
1521        const int inset = 1;
1522
1523        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1524               ibounds.fRight + inset, ibounds.fBottom + inset);
1525        inverse.mapRect(bounds, r);
1526    }
1527    return true;
1528}
1529
1530bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1531    const SkRasterClip& clip = fMCRec->fRasterClip;
1532    if (clip.isEmpty()) {
1533        if (bounds) {
1534            bounds->setEmpty();
1535        }
1536        return false;
1537    }
1538
1539    if (bounds) {
1540        *bounds = clip.getBounds();
1541    }
1542    return true;
1543}
1544
1545const SkMatrix& SkCanvas::getTotalMatrix() const {
1546    return fMCRec->fMatrix;
1547}
1548
1549const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1550    return fMCRec->fRasterClip.forceGetBW();
1551}
1552
1553GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1554    SkBaseDevice* dev = this->getTopDevice();
1555    return dev ? dev->accessRenderTarget() : NULL;
1556}
1557
1558GrContext* SkCanvas::getGrContext() {
1559#if SK_SUPPORT_GPU
1560    SkBaseDevice* device = this->getTopDevice();
1561    if (device) {
1562        GrRenderTarget* renderTarget = device->accessRenderTarget();
1563        if (renderTarget) {
1564            return renderTarget->getContext();
1565        }
1566    }
1567#endif
1568
1569    return NULL;
1570
1571}
1572
1573void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1574                          const SkPaint& paint) {
1575    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1576    if (outer.isEmpty()) {
1577        return;
1578    }
1579    if (inner.isEmpty()) {
1580        this->drawRRect(outer, paint);
1581        return;
1582    }
1583
1584    // We don't have this method (yet), but technically this is what we should
1585    // be able to assert...
1586    // SkASSERT(outer.contains(inner));
1587    //
1588    // For now at least check for containment of bounds
1589    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1590
1591    this->onDrawDRRect(outer, inner, paint);
1592}
1593
1594// These need to stop being virtual -- clients need to override the onDraw... versions
1595
1596void SkCanvas::drawPaint(const SkPaint& paint) {
1597    this->onDrawPaint(paint);
1598}
1599
1600void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1601    this->onDrawRect(r, paint);
1602}
1603
1604void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1605    this->onDrawOval(r, paint);
1606}
1607
1608void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1609    this->onDrawRRect(rrect, paint);
1610}
1611
1612void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1613    this->onDrawPoints(mode, count, pts, paint);
1614}
1615
1616void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
1617                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
1618                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
1619    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
1620                         indices, indexCount, paint);
1621}
1622
1623void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1624    this->onDrawPath(path, paint);
1625}
1626
1627void SkCanvas::drawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1628    this->onDrawImage(image, dx, dy, paint);
1629}
1630
1631void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1632                             const SkPaint* paint) {
1633    this->onDrawImageRect(image, src, dst, paint);
1634}
1635
1636void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1637    this->onDrawBitmap(bitmap, dx, dy, paint);
1638}
1639
1640void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1641                                    const SkPaint* paint, DrawBitmapRectFlags flags) {
1642    this->onDrawBitmapRect(bitmap, src, dst, paint, flags);
1643}
1644
1645void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1646                              const SkPaint* paint) {
1647    this->onDrawBitmapNine(bitmap, center, dst, paint);
1648}
1649
1650void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
1651    this->onDrawSprite(bitmap, left, top, paint);
1652}
1653
1654//////////////////////////////////////////////////////////////////////////////
1655//  These are the virtual drawing methods
1656//////////////////////////////////////////////////////////////////////////////
1657
1658void SkCanvas::onDiscard() {
1659    if (fSurfaceBase) {
1660        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1661    }
1662}
1663
1664void SkCanvas::onDrawPaint(const SkPaint& paint) {
1665    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1666    this->internalDrawPaint(paint);
1667}
1668
1669void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1670    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1671
1672    while (iter.next()) {
1673        iter.fDevice->drawPaint(iter, looper.paint());
1674    }
1675
1676    LOOPER_END
1677}
1678
1679void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
1680                            const SkPaint& paint) {
1681    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
1682    if ((long)count <= 0) {
1683        return;
1684    }
1685
1686    SkRect r, storage;
1687    const SkRect* bounds = NULL;
1688    if (paint.canComputeFastBounds()) {
1689        // special-case 2 points (common for drawing a single line)
1690        if (2 == count) {
1691            r.set(pts[0], pts[1]);
1692        } else {
1693            r.set(pts, SkToInt(count));
1694        }
1695        bounds = &paint.computeFastStrokeBounds(r, &storage);
1696        if (this->quickReject(*bounds)) {
1697            return;
1698        }
1699    }
1700
1701    SkASSERT(pts != NULL);
1702
1703    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1704
1705    while (iter.next()) {
1706        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1707    }
1708
1709    LOOPER_END
1710}
1711
1712void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
1713    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
1714    SkRect storage;
1715    const SkRect* bounds = NULL;
1716    if (paint.canComputeFastBounds()) {
1717        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
1718        // To prevent accidental rejecting at this stage, we have to sort it before we check.
1719        SkRect tmp(r);
1720        tmp.sort();
1721
1722        bounds = &paint.computeFastBounds(tmp, &storage);
1723        if (this->quickReject(*bounds)) {
1724            return;
1725        }
1726    }
1727
1728    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1729
1730    while (iter.next()) {
1731        iter.fDevice->drawRect(iter, r, looper.paint());
1732    }
1733
1734    LOOPER_END
1735}
1736
1737void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
1738    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
1739    SkRect storage;
1740    const SkRect* bounds = NULL;
1741    if (paint.canComputeFastBounds()) {
1742        bounds = &paint.computeFastBounds(oval, &storage);
1743        if (this->quickReject(*bounds)) {
1744            return;
1745        }
1746    }
1747
1748    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1749
1750    while (iter.next()) {
1751        iter.fDevice->drawOval(iter, oval, looper.paint());
1752    }
1753
1754    LOOPER_END
1755}
1756
1757void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
1758    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
1759    SkRect storage;
1760    const SkRect* bounds = NULL;
1761    if (paint.canComputeFastBounds()) {
1762        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1763        if (this->quickReject(*bounds)) {
1764            return;
1765        }
1766    }
1767
1768    if (rrect.isRect()) {
1769        // call the non-virtual version
1770        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1771        return;
1772    } else if (rrect.isOval()) {
1773        // call the non-virtual version
1774        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1775        return;
1776    }
1777
1778    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1779
1780    while (iter.next()) {
1781        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1782    }
1783
1784    LOOPER_END
1785}
1786
1787void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1788                            const SkPaint& paint) {
1789    SkRect storage;
1790    const SkRect* bounds = NULL;
1791    if (paint.canComputeFastBounds()) {
1792        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1793        if (this->quickReject(*bounds)) {
1794            return;
1795        }
1796    }
1797
1798    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1799
1800    while (iter.next()) {
1801        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1802    }
1803
1804    LOOPER_END
1805}
1806
1807void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
1808    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
1809    if (!path.isFinite()) {
1810        return;
1811    }
1812
1813    SkRect storage;
1814    const SkRect* bounds = NULL;
1815    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1816        const SkRect& pathBounds = path.getBounds();
1817        bounds = &paint.computeFastBounds(pathBounds, &storage);
1818        if (this->quickReject(*bounds)) {
1819            return;
1820        }
1821    }
1822
1823    const SkRect& r = path.getBounds();
1824    if (r.width() <= 0 && r.height() <= 0) {
1825        if (path.isInverseFillType()) {
1826            this->internalDrawPaint(paint);
1827        }
1828        return;
1829    }
1830
1831    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1832
1833    while (iter.next()) {
1834        iter.fDevice->drawPath(iter, path, looper.paint());
1835    }
1836
1837    LOOPER_END
1838}
1839
1840void SkCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1841    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
1842    image->draw(this, dx, dy, paint);
1843}
1844
1845void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1846                               const SkPaint* paint) {
1847    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
1848    image->drawRect(this, src, dst, paint);
1849}
1850
1851void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
1852    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
1853    SkDEBUGCODE(bitmap.validate();)
1854
1855    if (NULL == paint || paint->canComputeFastBounds()) {
1856        SkRect bounds = {
1857            x, y,
1858            x + SkIntToScalar(bitmap.width()),
1859            y + SkIntToScalar(bitmap.height())
1860        };
1861        if (paint) {
1862            (void)paint->computeFastBounds(bounds, &bounds);
1863        }
1864        if (this->quickReject(bounds)) {
1865            return;
1866        }
1867    }
1868
1869    SkMatrix matrix;
1870    matrix.setTranslate(x, y);
1871    this->internalDrawBitmap(bitmap, matrix, paint);
1872}
1873
1874// this one is non-virtual, so it can be called safely by other canvas apis
1875void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1876                                      const SkRect& dst, const SkPaint* paint,
1877                                      DrawBitmapRectFlags flags) {
1878    if (bitmap.drawsNothing() || dst.isEmpty()) {
1879        return;
1880    }
1881
1882    SkRect storage;
1883    const SkRect* bounds = &dst;
1884    if (NULL == paint || paint->canComputeFastBounds()) {
1885        if (paint) {
1886            bounds = &paint->computeFastBounds(dst, &storage);
1887        }
1888        if (this->quickReject(*bounds)) {
1889            return;
1890        }
1891    }
1892
1893    SkLazyPaint lazy;
1894    if (NULL == paint) {
1895        paint = lazy.init();
1896    }
1897
1898    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1899
1900    while (iter.next()) {
1901        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1902    }
1903
1904    LOOPER_END
1905}
1906
1907void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1908                                const SkPaint* paint, DrawBitmapRectFlags flags) {
1909    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
1910    SkDEBUGCODE(bitmap.validate();)
1911    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
1912}
1913
1914void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1915                                      const SkIRect& center, const SkRect& dst,
1916                                      const SkPaint* paint) {
1917    if (bitmap.drawsNothing()) {
1918        return;
1919    }
1920    if (NULL == paint || paint->canComputeFastBounds()) {
1921        SkRect storage;
1922        const SkRect* bounds = &dst;
1923        if (paint) {
1924            bounds = &paint->computeFastBounds(dst, &storage);
1925        }
1926        if (this->quickReject(*bounds)) {
1927            return;
1928        }
1929    }
1930
1931    const int32_t w = bitmap.width();
1932    const int32_t h = bitmap.height();
1933
1934    SkIRect c = center;
1935    // pin center to the bounds of the bitmap
1936    c.fLeft = SkMax32(0, center.fLeft);
1937    c.fTop = SkMax32(0, center.fTop);
1938    c.fRight = SkPin32(center.fRight, c.fLeft, w);
1939    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1940
1941    const SkScalar srcX[4] = {
1942        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
1943    };
1944    const SkScalar srcY[4] = {
1945        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
1946    };
1947    SkScalar dstX[4] = {
1948        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1949        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1950    };
1951    SkScalar dstY[4] = {
1952        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1953        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1954    };
1955
1956    if (dstX[1] > dstX[2]) {
1957        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1958        dstX[2] = dstX[1];
1959    }
1960
1961    if (dstY[1] > dstY[2]) {
1962        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1963        dstY[2] = dstY[1];
1964    }
1965
1966    for (int y = 0; y < 3; y++) {
1967        SkRect s, d;
1968
1969        s.fTop = srcY[y];
1970        s.fBottom = srcY[y+1];
1971        d.fTop = dstY[y];
1972        d.fBottom = dstY[y+1];
1973        for (int x = 0; x < 3; x++) {
1974            s.fLeft = srcX[x];
1975            s.fRight = srcX[x+1];
1976            d.fLeft = dstX[x];
1977            d.fRight = dstX[x+1];
1978            this->internalDrawBitmapRect(bitmap, &s, d, paint,
1979                                         kNone_DrawBitmapRectFlag);
1980        }
1981    }
1982}
1983
1984void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1985                                const SkPaint* paint) {
1986    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
1987    SkDEBUGCODE(bitmap.validate();)
1988
1989    // Need a device entry-point, so gpu can use a mesh
1990    this->internalDrawBitmapNine(bitmap, center, dst, paint);
1991}
1992
1993class SkDeviceFilteredPaint {
1994public:
1995    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
1996        uint32_t filteredFlags = device->filterTextFlags(paint);
1997        if (filteredFlags != paint.getFlags()) {
1998            SkPaint* newPaint = fLazy.set(paint);
1999            newPaint->setFlags(filteredFlags);
2000            fPaint = newPaint;
2001        } else {
2002            fPaint = &paint;
2003        }
2004    }
2005
2006    const SkPaint& paint() const { return *fPaint; }
2007
2008private:
2009    const SkPaint*  fPaint;
2010    SkLazyPaint     fLazy;
2011};
2012
2013void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2014                        const SkRect& r, SkScalar textSize) {
2015    if (paint.getStyle() == SkPaint::kFill_Style) {
2016        draw.fDevice->drawRect(draw, r, paint);
2017    } else {
2018        SkPaint p(paint);
2019        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2020        draw.fDevice->drawRect(draw, r, p);
2021    }
2022}
2023
2024void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2025                                   const char text[], size_t byteLength,
2026                                   SkScalar x, SkScalar y) {
2027    SkASSERT(byteLength == 0 || text != NULL);
2028
2029    // nothing to draw
2030    if (text == NULL || byteLength == 0 ||
2031        draw.fClip->isEmpty() ||
2032        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2033        return;
2034    }
2035
2036    SkScalar    width = 0;
2037    SkPoint     start;
2038
2039    start.set(0, 0);    // to avoid warning
2040    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2041                            SkPaint::kStrikeThruText_Flag)) {
2042        width = paint.measureText(text, byteLength);
2043
2044        SkScalar offsetX = 0;
2045        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2046            offsetX = SkScalarHalf(width);
2047        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2048            offsetX = width;
2049        }
2050        start.set(x - offsetX, y);
2051    }
2052
2053    if (0 == width) {
2054        return;
2055    }
2056
2057    uint32_t flags = paint.getFlags();
2058
2059    if (flags & (SkPaint::kUnderlineText_Flag |
2060                 SkPaint::kStrikeThruText_Flag)) {
2061        SkScalar textSize = paint.getTextSize();
2062        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2063        SkRect   r;
2064
2065        r.fLeft = start.fX;
2066        r.fRight = start.fX + width;
2067
2068        if (flags & SkPaint::kUnderlineText_Flag) {
2069            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2070                                             start.fY);
2071            r.fTop = offset;
2072            r.fBottom = offset + height;
2073            DrawRect(draw, paint, r, textSize);
2074        }
2075        if (flags & SkPaint::kStrikeThruText_Flag) {
2076            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2077                                             start.fY);
2078            r.fTop = offset;
2079            r.fBottom = offset + height;
2080            DrawRect(draw, paint, r, textSize);
2081        }
2082    }
2083}
2084
2085void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2086                          const SkPaint& paint) {
2087    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2088
2089    while (iter.next()) {
2090        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2091        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2092        DrawTextDecorations(iter, dfp.paint(),
2093                            static_cast<const char*>(text), byteLength, x, y);
2094    }
2095
2096    LOOPER_END
2097}
2098
2099void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2100                             const SkPaint& paint) {
2101    SkPoint textOffset = SkPoint::Make(0, 0);
2102
2103    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2104
2105    while (iter.next()) {
2106        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2107        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2108                                  dfp.paint());
2109    }
2110
2111    LOOPER_END
2112}
2113
2114void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2115                              SkScalar constY, const SkPaint& paint) {
2116
2117    SkPoint textOffset = SkPoint::Make(0, constY);
2118
2119    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2120
2121    while (iter.next()) {
2122        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2123        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2124                                  dfp.paint());
2125    }
2126
2127    LOOPER_END
2128}
2129
2130void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2131                                const SkMatrix* matrix, const SkPaint& paint) {
2132    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2133
2134    while (iter.next()) {
2135        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2136                                     matrix, looper.paint());
2137    }
2138
2139    LOOPER_END
2140}
2141
2142void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2143                              const SkPaint& paint) {
2144
2145    SkRect storage;
2146    const SkRect* bounds = NULL;
2147    if (paint.canComputeFastBounds()) {
2148        storage = blob->bounds().makeOffset(x, y);
2149        bounds = &paint.computeFastBounds(storage, &storage);
2150
2151        if (this->quickReject(*bounds)) {
2152            return;
2153        }
2154    }
2155
2156    // We cannot filter in the looper as we normally do, because the paint is
2157    // incomplete at this point (text-related attributes are embedded within blob run paints).
2158    SkDrawFilter* drawFilter = fMCRec->fFilter;
2159    fMCRec->fFilter = NULL;
2160
2161    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2162
2163    while (iter.next()) {
2164        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2165        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
2166    }
2167
2168    LOOPER_END
2169
2170    fMCRec->fFilter = drawFilter;
2171}
2172
2173// These will become non-virtual, so they always call the (virtual) onDraw... method
2174void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2175                        const SkPaint& paint) {
2176    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2177    this->onDrawText(text, byteLength, x, y, paint);
2178}
2179void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2180                           const SkPaint& paint) {
2181    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2182    this->onDrawPosText(text, byteLength, pos, paint);
2183}
2184void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2185                            SkScalar constY, const SkPaint& paint) {
2186    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2187    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2188}
2189void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2190                              const SkMatrix* matrix, const SkPaint& paint) {
2191    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2192    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2193}
2194void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2195                            const SkPaint& paint) {
2196    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2197    if (blob) {
2198        this->onDrawTextBlob(blob, x, y, paint);
2199    }
2200}
2201
2202void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
2203                              const SkPoint verts[], const SkPoint texs[],
2204                              const SkColor colors[], SkXfermode* xmode,
2205                              const uint16_t indices[], int indexCount,
2206                              const SkPaint& paint) {
2207    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2208    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2209
2210    while (iter.next()) {
2211        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2212                                   colors, xmode, indices, indexCount,
2213                                   looper.paint());
2214    }
2215
2216    LOOPER_END
2217}
2218
2219void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2220                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2221    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2222    if (NULL == cubics) {
2223        return;
2224    }
2225
2226    // Since a patch is always within the convex hull of the control points, we discard it when its
2227    // bounding rectangle is completely outside the current clip.
2228    SkRect bounds;
2229    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2230    if (this->quickReject(bounds)) {
2231        return;
2232    }
2233
2234    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2235}
2236
2237void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2238                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2239
2240    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2241
2242    while (iter.next()) {
2243        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2244    }
2245
2246    LOOPER_END
2247}
2248
2249void SkCanvas::drawDrawable(SkDrawable* dr) {
2250    if (dr && !this->quickReject(dr->getBounds())) {
2251        this->onDrawDrawable(dr);
2252    }
2253}
2254
2255void SkCanvas::onDrawDrawable(SkDrawable* dr) {
2256    dr->draw(this);
2257}
2258
2259//////////////////////////////////////////////////////////////////////////////
2260// These methods are NOT virtual, and therefore must call back into virtual
2261// methods, rather than actually drawing themselves.
2262//////////////////////////////////////////////////////////////////////////////
2263
2264void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2265                        SkXfermode::Mode mode) {
2266    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2267    SkPaint paint;
2268
2269    paint.setARGB(a, r, g, b);
2270    if (SkXfermode::kSrcOver_Mode != mode) {
2271        paint.setXfermodeMode(mode);
2272    }
2273    this->drawPaint(paint);
2274}
2275
2276void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2277    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2278    SkPaint paint;
2279
2280    paint.setColor(c);
2281    if (SkXfermode::kSrcOver_Mode != mode) {
2282        paint.setXfermodeMode(mode);
2283    }
2284    this->drawPaint(paint);
2285}
2286
2287void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2288    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2289    SkPoint pt;
2290
2291    pt.set(x, y);
2292    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2293}
2294
2295void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2296    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2297    SkPoint pt;
2298    SkPaint paint;
2299
2300    pt.set(x, y);
2301    paint.setColor(color);
2302    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2303}
2304
2305void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2306                        const SkPaint& paint) {
2307    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2308    SkPoint pts[2];
2309
2310    pts[0].set(x0, y0);
2311    pts[1].set(x1, y1);
2312    this->drawPoints(kLines_PointMode, 2, pts, paint);
2313}
2314
2315void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2316                              SkScalar right, SkScalar bottom,
2317                              const SkPaint& paint) {
2318    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2319    SkRect  r;
2320
2321    r.set(left, top, right, bottom);
2322    this->drawRect(r, paint);
2323}
2324
2325void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2326                          const SkPaint& paint) {
2327    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2328    if (radius < 0) {
2329        radius = 0;
2330    }
2331
2332    SkRect  r;
2333    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2334    this->drawOval(r, paint);
2335}
2336
2337void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2338                             const SkPaint& paint) {
2339    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2340    if (rx > 0 && ry > 0) {
2341        if (paint.canComputeFastBounds()) {
2342            SkRect storage;
2343            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2344                return;
2345            }
2346        }
2347        SkRRect rrect;
2348        rrect.setRectXY(r, rx, ry);
2349        this->drawRRect(rrect, paint);
2350    } else {
2351        this->drawRect(r, paint);
2352    }
2353}
2354
2355void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2356                       SkScalar sweepAngle, bool useCenter,
2357                       const SkPaint& paint) {
2358    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2359    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2360        this->drawOval(oval, paint);
2361    } else {
2362        SkPath  path;
2363        if (useCenter) {
2364            path.moveTo(oval.centerX(), oval.centerY());
2365        }
2366        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2367        if (useCenter) {
2368            path.close();
2369        }
2370        this->drawPath(path, paint);
2371    }
2372}
2373
2374void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2375                                const SkPath& path, SkScalar hOffset,
2376                                SkScalar vOffset, const SkPaint& paint) {
2377    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2378    SkMatrix    matrix;
2379
2380    matrix.setTranslate(hOffset, vOffset);
2381    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2382}
2383
2384///////////////////////////////////////////////////////////////////////////////
2385void SkCanvas::drawPicture(const SkPicture* picture) {
2386    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2387    if (picture) {
2388        this->onDrawPicture(picture, NULL, NULL);
2389    }
2390}
2391
2392void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2393    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)");
2394    if (picture) {
2395        if (matrix && matrix->isIdentity()) {
2396            matrix = NULL;
2397        }
2398        this->onDrawPicture(picture, matrix, paint);
2399    }
2400}
2401
2402void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2403                             const SkPaint* paint) {
2404    SkBaseDevice* device = this->getTopDevice();
2405    if (device) {
2406        // Canvas has to first give the device the opportunity to render
2407        // the picture itself.
2408        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2409            return; // the device has rendered the entire picture
2410        }
2411    }
2412
2413    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2414
2415    picture->playback(this);
2416}
2417
2418///////////////////////////////////////////////////////////////////////////////
2419///////////////////////////////////////////////////////////////////////////////
2420
2421SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2422    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2423
2424    SkASSERT(canvas);
2425
2426    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2427    fDone = !fImpl->next();
2428}
2429
2430SkCanvas::LayerIter::~LayerIter() {
2431    fImpl->~SkDrawIter();
2432}
2433
2434void SkCanvas::LayerIter::next() {
2435    fDone = !fImpl->next();
2436}
2437
2438SkBaseDevice* SkCanvas::LayerIter::device() const {
2439    return fImpl->getDevice();
2440}
2441
2442const SkMatrix& SkCanvas::LayerIter::matrix() const {
2443    return fImpl->getMatrix();
2444}
2445
2446const SkPaint& SkCanvas::LayerIter::paint() const {
2447    const SkPaint* paint = fImpl->getPaint();
2448    if (NULL == paint) {
2449        paint = &fDefaultPaint;
2450    }
2451    return *paint;
2452}
2453
2454const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2455int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2456int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2457
2458///////////////////////////////////////////////////////////////////////////////
2459
2460SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2461
2462///////////////////////////////////////////////////////////////////////////////
2463
2464static bool supported_for_raster_canvas(const SkImageInfo& info) {
2465    switch (info.alphaType()) {
2466        case kPremul_SkAlphaType:
2467        case kOpaque_SkAlphaType:
2468            break;
2469        default:
2470            return false;
2471    }
2472
2473    switch (info.colorType()) {
2474        case kAlpha_8_SkColorType:
2475        case kRGB_565_SkColorType:
2476        case kN32_SkColorType:
2477            break;
2478        default:
2479            return false;
2480    }
2481
2482    return true;
2483}
2484
2485SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2486    if (!supported_for_raster_canvas(info)) {
2487        return NULL;
2488    }
2489
2490    SkBitmap bitmap;
2491    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2492        return NULL;
2493    }
2494    return SkNEW_ARGS(SkCanvas, (bitmap));
2495}
2496
2497///////////////////////////////////////////////////////////////////////////////
2498
2499SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2500                                                 const SkPaint* paint, const SkRect& bounds)
2501    : fCanvas(canvas)
2502    , fSaveCount(canvas->getSaveCount())
2503{
2504    if (paint) {
2505        SkRect newBounds = bounds;
2506        if (matrix) {
2507            matrix->mapRect(&newBounds);
2508        }
2509        canvas->saveLayer(&newBounds, paint);
2510    } else if (matrix) {
2511        canvas->save();
2512    }
2513
2514    if (matrix) {
2515        canvas->concat(*matrix);
2516    }
2517}
2518
2519SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2520    fCanvas->restoreToCount(fSaveCount);
2521}
2522