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