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