SkCanvas.cpp revision 2d97bc139a7de5813468bd3dbfd0037351ae5606
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::internalSave() {
815    int saveCount = this->getSaveCount(); // record this before the actual save
816
817    MCRec* newTop = (MCRec*)fMCStack.push_back();
818    new (newTop) MCRec(*fMCRec);    // balanced in restore()
819    fMCRec = newTop;
820
821    fClipStack.save();
822
823    return saveCount;
824}
825
826int SkCanvas::save() {
827    this->willSave();
828    return this->internalSave();
829}
830
831static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
832#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
833    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
834#else
835    return true;
836#endif
837}
838
839bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
840                               SkIRect* intersection, const SkImageFilter* imageFilter) {
841    SkIRect clipBounds;
842    SkRegion::Op op = SkRegion::kIntersect_Op;
843    if (!this->getClipDeviceBounds(&clipBounds)) {
844        return false;
845    }
846
847    if (imageFilter) {
848        imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
849        // Filters may grow the bounds beyond the device bounds.
850        op = SkRegion::kReplace_Op;
851    }
852    SkIRect ir;
853    if (bounds) {
854        SkRect r;
855
856        this->getTotalMatrix().mapRect(&r, *bounds);
857        r.roundOut(&ir);
858        // early exit if the layer's bounds are clipped out
859        if (!ir.intersect(clipBounds)) {
860            if (bounds_affects_clip(flags)) {
861                fMCRec->fRasterClip.setEmpty();
862            }
863            return false;
864        }
865    } else {    // no user bounds, so just use the clip
866        ir = clipBounds;
867    }
868
869    if (bounds_affects_clip(flags)) {
870        fClipStack.clipDevRect(ir, op);
871        // early exit if the clip is now empty
872        if (!fMCRec->fRasterClip.op(ir, op)) {
873            return false;
874        }
875    }
876
877    if (intersection) {
878        *intersection = ir;
879    }
880    return true;
881}
882
883int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
884    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
885    return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
886}
887
888int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
889                        SaveFlags flags) {
890    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
891    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
892}
893
894int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
895                                bool justForImageFilter, SaveLayerStrategy strategy) {
896#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
897    flags |= kClipToLayer_SaveFlag;
898#endif
899
900    // do this before we create the layer. We don't call the public save() since
901    // that would invoke a possibly overridden virtual
902    int count = this->internalSave();
903
904    fDeviceCMDirty = true;
905
906    SkIRect ir;
907    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
908        return count;
909    }
910
911    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
912    // the clipRectBounds() call above?
913    if (kNoLayer_SaveLayerStrategy == strategy) {
914        return count;
915    }
916
917    // Kill the imagefilter if our device doesn't allow it
918    SkLazyPaint lazyP;
919    if (paint && paint->getImageFilter()) {
920        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
921            if (justForImageFilter) {
922                // early exit if the layer was just for the imageFilter
923                return count;
924            }
925            SkPaint* p = lazyP.set(*paint);
926            p->setImageFilter(NULL);
927            paint = p;
928        }
929    }
930
931    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
932    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
933                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
934
935    SkBaseDevice* device = this->getTopDevice();
936    if (NULL == device) {
937        SkDebugf("Unable to find device for layer.");
938        return count;
939    }
940
941    SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage;
942    if (paint && paint->getImageFilter()) {
943        usage = SkBaseDevice::kImageFilter_Usage;
944    }
945    device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage,
946                                                                       fProps.pixelGeometry()));
947    if (NULL == device) {
948        SkDebugf("Unable to create device for layer.");
949        return count;
950    }
951
952    device->setOrigin(ir.fLeft, ir.fTop);
953    DeviceCM* layer = SkNEW_ARGS(DeviceCM,
954                                 (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
955    device->unref();
956
957    layer->fNext = fMCRec->fTopLayer;
958    fMCRec->fLayer = layer;
959    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
960
961    fSaveLayerCount += 1;
962    return count;
963}
964
965int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
966    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
967}
968
969int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
970                             SaveFlags flags) {
971    if (0xFF == alpha) {
972        return this->saveLayer(bounds, NULL, flags);
973    } else {
974        SkPaint tmpPaint;
975        tmpPaint.setAlpha(alpha);
976        return this->saveLayer(bounds, &tmpPaint, flags);
977    }
978}
979
980void SkCanvas::restore() {
981    // check for underflow
982    if (fMCStack.count() > 1) {
983        this->willRestore();
984        this->internalRestore();
985        this->didRestore();
986    }
987}
988
989void SkCanvas::internalRestore() {
990    SkASSERT(fMCStack.count() != 0);
991
992    fDeviceCMDirty = true;
993    fCachedLocalClipBoundsDirty = true;
994
995    fClipStack.restore();
996
997    // reserve our layer (if any)
998    DeviceCM* layer = fMCRec->fLayer;   // may be null
999    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1000    fMCRec->fLayer = NULL;
1001
1002    // now do the normal restore()
1003    fMCRec->~MCRec();       // balanced in save()
1004    fMCStack.pop_back();
1005    fMCRec = (MCRec*)fMCStack.back();
1006
1007    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1008        since if we're being recorded, we don't want to record this (the
1009        recorder will have already recorded the restore).
1010    */
1011    if (layer) {
1012        if (layer->fNext) {
1013            const SkIPoint& origin = layer->fDevice->getOrigin();
1014            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1015                                     layer->fPaint);
1016            // reset this, since internalDrawDevice will have set it to true
1017            fDeviceCMDirty = true;
1018
1019            SkASSERT(fSaveLayerCount > 0);
1020            fSaveLayerCount -= 1;
1021        }
1022        SkDELETE(layer);
1023    }
1024}
1025
1026int SkCanvas::getSaveCount() const {
1027    return fMCStack.count();
1028}
1029
1030void SkCanvas::restoreToCount(int count) {
1031    // sanity check
1032    if (count < 1) {
1033        count = 1;
1034    }
1035
1036    int n = this->getSaveCount() - count;
1037    for (int i = 0; i < n; ++i) {
1038        this->restore();
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("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("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::clear(SkColor color) {
1710    SkDrawIter  iter(this, false/*clear can affect empty clips*/);
1711    this->predrawNotify();
1712    while (iter.next()) {
1713        iter.fDevice->clear(color);
1714    }
1715}
1716
1717void SkCanvas::onDiscard() {
1718    if (fSurfaceBase) {
1719        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1720    }
1721}
1722
1723void SkCanvas::drawPaint(const SkPaint& paint) {
1724    TRACE_EVENT0("skia", "SkCanvas::drawPaint()");
1725    this->internalDrawPaint(paint);
1726}
1727
1728void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1729    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1730
1731    while (iter.next()) {
1732        iter.fDevice->drawPaint(iter, looper.paint());
1733    }
1734
1735    LOOPER_END
1736}
1737
1738void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1739                          const SkPaint& paint) {
1740    TRACE_EVENT1("skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
1741    if ((long)count <= 0) {
1742        return;
1743    }
1744
1745    SkRect r, storage;
1746    const SkRect* bounds = NULL;
1747    if (paint.canComputeFastBounds()) {
1748        // special-case 2 points (common for drawing a single line)
1749        if (2 == count) {
1750            r.set(pts[0], pts[1]);
1751        } else {
1752            r.set(pts, SkToInt(count));
1753        }
1754        bounds = &paint.computeFastStrokeBounds(r, &storage);
1755        if (this->quickReject(*bounds)) {
1756            return;
1757        }
1758    }
1759
1760    SkASSERT(pts != NULL);
1761
1762    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1763
1764    while (iter.next()) {
1765        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1766    }
1767
1768    LOOPER_END
1769}
1770
1771void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1772    TRACE_EVENT0("skia", "SkCanvas::drawRect()");
1773    SkRect storage;
1774    const SkRect* bounds = NULL;
1775    if (paint.canComputeFastBounds()) {
1776        bounds = &paint.computeFastBounds(r, &storage);
1777        if (this->quickReject(*bounds)) {
1778            return;
1779        }
1780    }
1781
1782    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1783
1784    while (iter.next()) {
1785        iter.fDevice->drawRect(iter, r, looper.paint());
1786    }
1787
1788    LOOPER_END
1789}
1790
1791void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1792    TRACE_EVENT0("skia", "SkCanvas::drawOval()");
1793    SkRect storage;
1794    const SkRect* bounds = NULL;
1795    if (paint.canComputeFastBounds()) {
1796        bounds = &paint.computeFastBounds(oval, &storage);
1797        if (this->quickReject(*bounds)) {
1798            return;
1799        }
1800    }
1801
1802    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1803
1804    while (iter.next()) {
1805        iter.fDevice->drawOval(iter, oval, looper.paint());
1806    }
1807
1808    LOOPER_END
1809}
1810
1811void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1812    TRACE_EVENT0("skia", "SkCanvas::drawRRect()");
1813    SkRect storage;
1814    const SkRect* bounds = NULL;
1815    if (paint.canComputeFastBounds()) {
1816        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1817        if (this->quickReject(*bounds)) {
1818            return;
1819        }
1820    }
1821
1822    if (rrect.isRect()) {
1823        // call the non-virtual version
1824        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1825        return;
1826    } else if (rrect.isOval()) {
1827        // call the non-virtual version
1828        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1829        return;
1830    }
1831
1832    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1833
1834    while (iter.next()) {
1835        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1836    }
1837
1838    LOOPER_END
1839}
1840
1841void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1842                            const SkPaint& paint) {
1843    SkRect storage;
1844    const SkRect* bounds = NULL;
1845    if (paint.canComputeFastBounds()) {
1846        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1847        if (this->quickReject(*bounds)) {
1848            return;
1849        }
1850    }
1851
1852    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1853
1854    while (iter.next()) {
1855        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1856    }
1857
1858    LOOPER_END
1859}
1860
1861void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1862    TRACE_EVENT0("skia", "SkCanvas::drawPath()");
1863    if (!path.isFinite()) {
1864        return;
1865    }
1866
1867    SkRect storage;
1868    const SkRect* bounds = NULL;
1869    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1870        const SkRect& pathBounds = path.getBounds();
1871        bounds = &paint.computeFastBounds(pathBounds, &storage);
1872        if (this->quickReject(*bounds)) {
1873            return;
1874        }
1875    }
1876
1877    const SkRect& r = path.getBounds();
1878    if (r.width() <= 0 && r.height() <= 0) {
1879        if (path.isInverseFillType()) {
1880            this->internalDrawPaint(paint);
1881        }
1882        return;
1883    }
1884
1885    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1886
1887    while (iter.next()) {
1888        iter.fDevice->drawPath(iter, path, looper.paint());
1889    }
1890
1891    LOOPER_END
1892}
1893
1894void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top,
1895                       const SkPaint* paint) {
1896    TRACE_EVENT0("skia", "SkCanvas::drawImage()");
1897    image->draw(this, left, top, paint);
1898}
1899
1900void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src,
1901                           const SkRect& dst,
1902                           const SkPaint* paint) {
1903    TRACE_EVENT0("skia", "SkCanvas::drawImageRect()");
1904    image->drawRect(this, src, dst, paint);
1905}
1906
1907void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1908                          const SkPaint* paint) {
1909    TRACE_EVENT0("skia", "SkCanvas::drawBitmap()");
1910    SkDEBUGCODE(bitmap.validate();)
1911
1912    if (NULL == paint || paint->canComputeFastBounds()) {
1913        SkRect bounds = {
1914            x, y,
1915            x + SkIntToScalar(bitmap.width()),
1916            y + SkIntToScalar(bitmap.height())
1917        };
1918        if (paint) {
1919            (void)paint->computeFastBounds(bounds, &bounds);
1920        }
1921        if (this->quickReject(bounds)) {
1922            return;
1923        }
1924    }
1925
1926    SkMatrix matrix;
1927    matrix.setTranslate(x, y);
1928    this->internalDrawBitmap(bitmap, matrix, paint);
1929}
1930
1931// this one is non-virtual, so it can be called safely by other canvas apis
1932void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1933                                      const SkRect& dst, const SkPaint* paint,
1934                                      DrawBitmapRectFlags flags) {
1935    if (bitmap.drawsNothing() || dst.isEmpty()) {
1936        return;
1937    }
1938
1939    SkRect storage;
1940    const SkRect* bounds = &dst;
1941    if (NULL == paint || paint->canComputeFastBounds()) {
1942        if (paint) {
1943            bounds = &paint->computeFastBounds(dst, &storage);
1944        }
1945        if (this->quickReject(*bounds)) {
1946            return;
1947        }
1948    }
1949
1950    SkLazyPaint lazy;
1951    if (NULL == paint) {
1952        paint = lazy.init();
1953    }
1954
1955    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1956
1957    while (iter.next()) {
1958        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1959    }
1960
1961    LOOPER_END
1962}
1963
1964void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1965                                    const SkRect& dst, const SkPaint* paint,
1966                                    DrawBitmapRectFlags flags) {
1967    TRACE_EVENT0("skia", "SkCanvas::drawBitmapRectToRect()");
1968    SkDEBUGCODE(bitmap.validate();)
1969    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
1970}
1971
1972void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1973                                const SkPaint* paint) {
1974    TRACE_EVENT0("skia", "SkCanvas::drawBitmapMatrix()");
1975    SkDEBUGCODE(bitmap.validate();)
1976    this->internalDrawBitmap(bitmap, matrix, paint);
1977}
1978
1979void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1980                                      const SkIRect& center, const SkRect& dst,
1981                                      const SkPaint* paint) {
1982    if (bitmap.drawsNothing()) {
1983        return;
1984    }
1985    if (NULL == paint || paint->canComputeFastBounds()) {
1986        SkRect storage;
1987        const SkRect* bounds = &dst;
1988        if (paint) {
1989            bounds = &paint->computeFastBounds(dst, &storage);
1990        }
1991        if (this->quickReject(*bounds)) {
1992            return;
1993        }
1994    }
1995
1996    const int32_t w = bitmap.width();
1997    const int32_t h = bitmap.height();
1998
1999    SkIRect c = center;
2000    // pin center to the bounds of the bitmap
2001    c.fLeft = SkMax32(0, center.fLeft);
2002    c.fTop = SkMax32(0, center.fTop);
2003    c.fRight = SkPin32(center.fRight, c.fLeft, w);
2004    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
2005
2006    const SkScalar srcX[4] = {
2007        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
2008    };
2009    const SkScalar srcY[4] = {
2010        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
2011    };
2012    SkScalar dstX[4] = {
2013        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
2014        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
2015    };
2016    SkScalar dstY[4] = {
2017        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
2018        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
2019    };
2020
2021    if (dstX[1] > dstX[2]) {
2022        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
2023        dstX[2] = dstX[1];
2024    }
2025
2026    if (dstY[1] > dstY[2]) {
2027        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2028        dstY[2] = dstY[1];
2029    }
2030
2031    for (int y = 0; y < 3; y++) {
2032        SkRect s, d;
2033
2034        s.fTop = srcY[y];
2035        s.fBottom = srcY[y+1];
2036        d.fTop = dstY[y];
2037        d.fBottom = dstY[y+1];
2038        for (int x = 0; x < 3; x++) {
2039            s.fLeft = srcX[x];
2040            s.fRight = srcX[x+1];
2041            d.fLeft = dstX[x];
2042            d.fRight = dstX[x+1];
2043            this->internalDrawBitmapRect(bitmap, &s, d, paint,
2044                                         kNone_DrawBitmapRectFlag);
2045        }
2046    }
2047}
2048
2049void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
2050                              const SkRect& dst, const SkPaint* paint) {
2051    TRACE_EVENT0("skia", "SkCanvas::drawBitmapNine()");
2052    SkDEBUGCODE(bitmap.validate();)
2053
2054    // Need a device entry-point, so gpu can use a mesh
2055    this->internalDrawBitmapNine(bitmap, center, dst, paint);
2056}
2057
2058class SkDeviceFilteredPaint {
2059public:
2060    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2061        uint32_t filteredFlags = device->filterTextFlags(paint);
2062        if (filteredFlags != paint.getFlags()) {
2063            SkPaint* newPaint = fLazy.set(paint);
2064            newPaint->setFlags(filteredFlags);
2065            fPaint = newPaint;
2066        } else {
2067            fPaint = &paint;
2068        }
2069    }
2070
2071    const SkPaint& paint() const { return *fPaint; }
2072
2073private:
2074    const SkPaint*  fPaint;
2075    SkLazyPaint     fLazy;
2076};
2077
2078void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2079                        const SkRect& r, SkScalar textSize) {
2080    if (paint.getStyle() == SkPaint::kFill_Style) {
2081        draw.fDevice->drawRect(draw, r, paint);
2082    } else {
2083        SkPaint p(paint);
2084        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2085        draw.fDevice->drawRect(draw, r, p);
2086    }
2087}
2088
2089void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2090                                   const char text[], size_t byteLength,
2091                                   SkScalar x, SkScalar y) {
2092    SkASSERT(byteLength == 0 || text != NULL);
2093
2094    // nothing to draw
2095    if (text == NULL || byteLength == 0 ||
2096        draw.fClip->isEmpty() ||
2097        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2098        return;
2099    }
2100
2101    SkScalar    width = 0;
2102    SkPoint     start;
2103
2104    start.set(0, 0);    // to avoid warning
2105    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2106                            SkPaint::kStrikeThruText_Flag)) {
2107        width = paint.measureText(text, byteLength);
2108
2109        SkScalar offsetX = 0;
2110        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2111            offsetX = SkScalarHalf(width);
2112        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2113            offsetX = width;
2114        }
2115        start.set(x - offsetX, y);
2116    }
2117
2118    if (0 == width) {
2119        return;
2120    }
2121
2122    uint32_t flags = paint.getFlags();
2123
2124    if (flags & (SkPaint::kUnderlineText_Flag |
2125                 SkPaint::kStrikeThruText_Flag)) {
2126        SkScalar textSize = paint.getTextSize();
2127        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2128        SkRect   r;
2129
2130        r.fLeft = start.fX;
2131        r.fRight = start.fX + width;
2132
2133        if (flags & SkPaint::kUnderlineText_Flag) {
2134            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2135                                             start.fY);
2136            r.fTop = offset;
2137            r.fBottom = offset + height;
2138            DrawRect(draw, paint, r, textSize);
2139        }
2140        if (flags & SkPaint::kStrikeThruText_Flag) {
2141            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2142                                             start.fY);
2143            r.fTop = offset;
2144            r.fBottom = offset + height;
2145            DrawRect(draw, paint, r, textSize);
2146        }
2147    }
2148}
2149
2150void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2151                          const SkPaint& paint) {
2152    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2153
2154    while (iter.next()) {
2155        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2156        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2157        DrawTextDecorations(iter, dfp.paint(),
2158                            static_cast<const char*>(text), byteLength, x, y);
2159    }
2160
2161    LOOPER_END
2162}
2163
2164void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2165                             const SkPaint& paint) {
2166    SkPoint textOffset = SkPoint::Make(0, 0);
2167
2168    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2169
2170    while (iter.next()) {
2171        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2172        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2173                                  dfp.paint());
2174    }
2175
2176    LOOPER_END
2177}
2178
2179void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2180                              SkScalar constY, const SkPaint& paint) {
2181
2182    SkPoint textOffset = SkPoint::Make(0, constY);
2183
2184    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2185
2186    while (iter.next()) {
2187        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2188        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2189                                  dfp.paint());
2190    }
2191
2192    LOOPER_END
2193}
2194
2195void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2196                                const SkMatrix* matrix, const SkPaint& paint) {
2197    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2198
2199    while (iter.next()) {
2200        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2201                                     matrix, looper.paint());
2202    }
2203
2204    LOOPER_END
2205}
2206
2207void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2208                              const SkPaint& paint) {
2209
2210    if (paint.canComputeFastBounds()) {
2211        SkRect storage;
2212
2213        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
2214            return;
2215        }
2216    }
2217
2218    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2219
2220    while (iter.next()) {
2221        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2222        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
2223    }
2224
2225    LOOPER_END
2226}
2227
2228// These will become non-virtual, so they always call the (virtual) onDraw... method
2229void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2230                        const SkPaint& paint) {
2231    TRACE_EVENT0("skia", "SkCanvas::drawText()");
2232    this->onDrawText(text, byteLength, x, y, paint);
2233}
2234void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2235                           const SkPaint& paint) {
2236    TRACE_EVENT0("skia", "SkCanvas::drawPosText()");
2237    this->onDrawPosText(text, byteLength, pos, paint);
2238}
2239void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2240                            SkScalar constY, const SkPaint& paint) {
2241    TRACE_EVENT0("skia", "SkCanvas::drawPosTextH()");
2242    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2243}
2244void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2245                              const SkMatrix* matrix, const SkPaint& paint) {
2246    TRACE_EVENT0("skia", "SkCanvas::drawTextOnPath()");
2247    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2248}
2249void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2250                            const SkPaint& paint) {
2251    TRACE_EVENT0("skia", "SkCanvas::drawTextBlob()");
2252    if (blob) {
2253        this->onDrawTextBlob(blob, x, y, paint);
2254    }
2255}
2256
2257void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
2258                            const SkPoint verts[], const SkPoint texs[],
2259                            const SkColor colors[], SkXfermode* xmode,
2260                            const uint16_t indices[], int indexCount,
2261                            const SkPaint& paint) {
2262    TRACE_EVENT0("skia", "SkCanvas::drawVertices()");
2263    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2264
2265    while (iter.next()) {
2266        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2267                                   colors, xmode, indices, indexCount,
2268                                   looper.paint());
2269    }
2270
2271    LOOPER_END
2272}
2273
2274void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2275                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2276    TRACE_EVENT0("skia", "SkCanvas::drawPatch()");
2277    if (NULL == cubics) {
2278        return;
2279    }
2280
2281    // Since a patch is always within the convex hull of the control points, we discard it when its
2282    // bounding rectangle is completely outside the current clip.
2283    SkRect bounds;
2284    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2285    if (this->quickReject(bounds)) {
2286        return;
2287    }
2288
2289    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2290}
2291
2292void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2293                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2294
2295    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2296
2297    while (iter.next()) {
2298        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2299    }
2300
2301    LOOPER_END
2302}
2303
2304void SkCanvas::EXPERIMENTAL_drawDrawable(SkCanvasDrawable* dr) {
2305    if (dr && !this->quickReject(dr->getBounds())) {
2306        this->onDrawDrawable(dr);
2307    }
2308}
2309
2310void SkCanvas::onDrawDrawable(SkCanvasDrawable* dr) {
2311    dr->draw(this);
2312}
2313
2314//////////////////////////////////////////////////////////////////////////////
2315// These methods are NOT virtual, and therefore must call back into virtual
2316// methods, rather than actually drawing themselves.
2317//////////////////////////////////////////////////////////////////////////////
2318
2319void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2320                        SkXfermode::Mode mode) {
2321    TRACE_EVENT0("skia", "SkCanvas::drawARGB()");
2322    SkPaint paint;
2323
2324    paint.setARGB(a, r, g, b);
2325    if (SkXfermode::kSrcOver_Mode != mode) {
2326        paint.setXfermodeMode(mode);
2327    }
2328    this->drawPaint(paint);
2329}
2330
2331void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2332    TRACE_EVENT0("skia", "SkCanvas::drawColor()");
2333    SkPaint paint;
2334
2335    paint.setColor(c);
2336    if (SkXfermode::kSrcOver_Mode != mode) {
2337        paint.setXfermodeMode(mode);
2338    }
2339    this->drawPaint(paint);
2340}
2341
2342void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2343    TRACE_EVENT0("skia", "SkCanvas::drawPoint(SkPaint)");
2344    SkPoint pt;
2345
2346    pt.set(x, y);
2347    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2348}
2349
2350void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2351    TRACE_EVENT0("skia", "SkCanvas::drawPoint(SkColor)");
2352    SkPoint pt;
2353    SkPaint paint;
2354
2355    pt.set(x, y);
2356    paint.setColor(color);
2357    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2358}
2359
2360void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2361                        const SkPaint& paint) {
2362    TRACE_EVENT0("skia", "SkCanvas::drawLine()");
2363    SkPoint pts[2];
2364
2365    pts[0].set(x0, y0);
2366    pts[1].set(x1, y1);
2367    this->drawPoints(kLines_PointMode, 2, pts, paint);
2368}
2369
2370void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2371                              SkScalar right, SkScalar bottom,
2372                              const SkPaint& paint) {
2373    TRACE_EVENT0("skia", "SkCanvas::drawRectCoords()");
2374    SkRect  r;
2375
2376    r.set(left, top, right, bottom);
2377    this->drawRect(r, paint);
2378}
2379
2380void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2381                          const SkPaint& paint) {
2382    TRACE_EVENT0("skia", "SkCanvas::drawCircle()");
2383    if (radius < 0) {
2384        radius = 0;
2385    }
2386
2387    SkRect  r;
2388    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2389    this->drawOval(r, paint);
2390}
2391
2392void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2393                             const SkPaint& paint) {
2394    TRACE_EVENT0("skia", "SkCanvas::drawRoundRect()");
2395    if (rx > 0 && ry > 0) {
2396        if (paint.canComputeFastBounds()) {
2397            SkRect storage;
2398            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2399                return;
2400            }
2401        }
2402        SkRRect rrect;
2403        rrect.setRectXY(r, rx, ry);
2404        this->drawRRect(rrect, paint);
2405    } else {
2406        this->drawRect(r, paint);
2407    }
2408}
2409
2410void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2411                       SkScalar sweepAngle, bool useCenter,
2412                       const SkPaint& paint) {
2413    TRACE_EVENT0("skia", "SkCanvas::drawArc()");
2414    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2415        this->drawOval(oval, paint);
2416    } else {
2417        SkPath  path;
2418        if (useCenter) {
2419            path.moveTo(oval.centerX(), oval.centerY());
2420        }
2421        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2422        if (useCenter) {
2423            path.close();
2424        }
2425        this->drawPath(path, paint);
2426    }
2427}
2428
2429void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2430                                const SkPath& path, SkScalar hOffset,
2431                                SkScalar vOffset, const SkPaint& paint) {
2432    TRACE_EVENT0("skia", "SkCanvas::drawTextOnPathHV()");
2433    SkMatrix    matrix;
2434
2435    matrix.setTranslate(hOffset, vOffset);
2436    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2437}
2438
2439///////////////////////////////////////////////////////////////////////////////
2440void SkCanvas::drawPicture(const SkPicture* picture) {
2441    TRACE_EVENT0("skia", "SkCanvas::drawPicture()");
2442    if (picture) {
2443        this->onDrawPicture(picture, NULL, NULL);
2444    }
2445}
2446
2447void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2448    TRACE_EVENT0("skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)");
2449    if (picture) {
2450        if (matrix && matrix->isIdentity()) {
2451            matrix = NULL;
2452        }
2453        this->onDrawPicture(picture, matrix, paint);
2454    }
2455}
2456
2457void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2458                             const SkPaint* paint) {
2459    SkBaseDevice* device = this->getTopDevice();
2460    if (device) {
2461        // Canvas has to first give the device the opportunity to render
2462        // the picture itself.
2463        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2464            return; // the device has rendered the entire picture
2465        }
2466    }
2467
2468    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2469
2470    picture->playback(this);
2471}
2472
2473///////////////////////////////////////////////////////////////////////////////
2474///////////////////////////////////////////////////////////////////////////////
2475
2476SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2477    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2478
2479    SkASSERT(canvas);
2480
2481    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2482    fDone = !fImpl->next();
2483}
2484
2485SkCanvas::LayerIter::~LayerIter() {
2486    fImpl->~SkDrawIter();
2487}
2488
2489void SkCanvas::LayerIter::next() {
2490    fDone = !fImpl->next();
2491}
2492
2493SkBaseDevice* SkCanvas::LayerIter::device() const {
2494    return fImpl->getDevice();
2495}
2496
2497const SkMatrix& SkCanvas::LayerIter::matrix() const {
2498    return fImpl->getMatrix();
2499}
2500
2501const SkPaint& SkCanvas::LayerIter::paint() const {
2502    const SkPaint* paint = fImpl->getPaint();
2503    if (NULL == paint) {
2504        paint = &fDefaultPaint;
2505    }
2506    return *paint;
2507}
2508
2509const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2510int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2511int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2512
2513///////////////////////////////////////////////////////////////////////////////
2514
2515SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2516
2517///////////////////////////////////////////////////////////////////////////////
2518
2519static bool supported_for_raster_canvas(const SkImageInfo& info) {
2520    switch (info.alphaType()) {
2521        case kPremul_SkAlphaType:
2522        case kOpaque_SkAlphaType:
2523            break;
2524        default:
2525            return false;
2526    }
2527
2528    switch (info.colorType()) {
2529        case kAlpha_8_SkColorType:
2530        case kRGB_565_SkColorType:
2531        case kN32_SkColorType:
2532            break;
2533        default:
2534            return false;
2535    }
2536
2537    return true;
2538}
2539
2540SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
2541    if (!supported_for_raster_canvas(info)) {
2542        return NULL;
2543    }
2544
2545    SkBitmap bitmap;
2546    if (!bitmap.tryAllocPixels(info)) {
2547        return NULL;
2548    }
2549
2550    // should this functionality be moved into allocPixels()?
2551    if (!bitmap.info().isOpaque()) {
2552        bitmap.eraseColor(0);
2553    }
2554    return SkNEW_ARGS(SkCanvas, (bitmap));
2555}
2556
2557SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2558    if (!supported_for_raster_canvas(info)) {
2559        return NULL;
2560    }
2561
2562    SkBitmap bitmap;
2563    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2564        return NULL;
2565    }
2566    return SkNEW_ARGS(SkCanvas, (bitmap));
2567}
2568
2569///////////////////////////////////////////////////////////////////////////////
2570
2571SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2572                                                 const SkPaint* paint, const SkRect& bounds)
2573    : fCanvas(canvas)
2574    , fSaveCount(canvas->getSaveCount())
2575{
2576    if (paint) {
2577        SkRect newBounds = bounds;
2578        if (matrix) {
2579            matrix->mapRect(&newBounds);
2580        }
2581        canvas->saveLayer(&newBounds, paint);
2582    } else if (matrix) {
2583        canvas->save();
2584    }
2585
2586    if (matrix) {
2587        canvas->concat(*matrix);
2588    }
2589}
2590
2591SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2592    fCanvas->restoreToCount(fSaveCount);
2593}
2594