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