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