SkCanvas.cpp revision fd4ee4dea13f083c81cc80180fa09ee0127158a1
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, SkIPoint* origin) {
1110    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
1111    if (pixels && origin) {
1112        *origin = this->getTopDevice(false)->getOrigin();
1113    }
1114    return pixels;
1115}
1116
1117void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
1118    SkBaseDevice* dev = this->getTopDevice();
1119    return dev ? dev->accessPixels(info, rowBytes) : NULL;
1120}
1121
1122SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1123    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1124    if (NULL == fAddr) {
1125        fInfo = canvas->imageInfo();
1126        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
1127            return; // failure, fAddr is NULL
1128        }
1129        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1130            return; // failure, fAddr is NULL
1131        }
1132        fAddr = fBitmap.getPixels();
1133        fRowBytes = fBitmap.rowBytes();
1134    }
1135    SkASSERT(fAddr);    // success
1136}
1137
1138bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1139    if (fAddr) {
1140        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes,
1141                                     NULL, NULL);
1142    } else {
1143        bitmap->reset();
1144        return false;
1145    }
1146}
1147
1148void SkCanvas::onPushCull(const SkRect& cullRect) {
1149    // do nothing. Subclasses may do something
1150}
1151
1152void SkCanvas::onPopCull() {
1153    // do nothing. Subclasses may do something
1154}
1155
1156/////////////////////////////////////////////////////////////////////////////
1157#ifdef SK_DEBUG
1158// Ensure that cull rects are monotonically nested in device space.
1159void SkCanvas::validateCull(const SkIRect& devCull) {
1160    if (fCullStack.isEmpty()
1161        || devCull.isEmpty()
1162        || fCullStack.top().contains(devCull)) {
1163        return;
1164    }
1165
1166    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1167              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1168              fCullStack.top().x(), fCullStack.top().y(),
1169              fCullStack.top().right(), fCullStack.top().bottom()));
1170
1171#ifdef ASSERT_NESTED_CULLING
1172    SkDEBUGFAIL("Invalid cull.");
1173#endif
1174}
1175#endif
1176
1177void SkCanvas::pushCull(const SkRect& cullRect) {
1178    ++fCullCount;
1179    this->onPushCull(cullRect);
1180
1181#ifdef SK_DEBUG
1182    // Map the cull rect into device space.
1183    SkRect mappedCull;
1184    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1185
1186    // Take clipping into account.
1187    SkIRect devClip, devCull;
1188    mappedCull.roundOut(&devCull);
1189    this->getClipDeviceBounds(&devClip);
1190    if (!devCull.intersect(devClip)) {
1191        devCull.setEmpty();
1192    }
1193
1194    this->validateCull(devCull);
1195    fCullStack.push(devCull); // balanced in popCull
1196#endif
1197}
1198
1199void SkCanvas::popCull() {
1200    SkASSERT(fCullStack.count() == fCullCount);
1201
1202    if (fCullCount > 0) {
1203        --fCullCount;
1204        this->onPopCull();
1205
1206        SkDEBUGCODE(fCullStack.pop());
1207    }
1208}
1209
1210/////////////////////////////////////////////////////////////////////////////
1211
1212void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1213                                const SkMatrix& matrix, const SkPaint* paint) {
1214    if (bitmap.drawsNothing()) {
1215        return;
1216    }
1217
1218    SkLazyPaint lazy;
1219    if (NULL == paint) {
1220        paint = lazy.init();
1221    }
1222
1223    SkDEBUGCODE(bitmap.validate();)
1224    CHECK_LOCKCOUNT_BALANCE(bitmap);
1225
1226    SkRect storage;
1227    const SkRect* bounds = NULL;
1228    if (paint && paint->canComputeFastBounds()) {
1229        bitmap.getBounds(&storage);
1230        matrix.mapRect(&storage);
1231        bounds = &paint->computeFastBounds(storage, &storage);
1232    }
1233
1234    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1235
1236    while (iter.next()) {
1237        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1238    }
1239
1240    LOOPER_END
1241}
1242
1243void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1244                                  const SkPaint* paint) {
1245    SkPaint tmp;
1246    if (NULL == paint) {
1247        tmp.setDither(true);
1248        paint = &tmp;
1249    }
1250
1251    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1252    while (iter.next()) {
1253        SkBaseDevice* dstDev = iter.fDevice;
1254        paint = &looper.paint();
1255        SkImageFilter* filter = paint->getImageFilter();
1256        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1257        if (filter && !dstDev->canHandleImageFilter(filter)) {
1258            SkDeviceImageFilterProxy proxy(dstDev);
1259            SkBitmap dst;
1260            SkIPoint offset = SkIPoint::Make(0, 0);
1261            const SkBitmap& src = srcDev->accessBitmap(false);
1262            SkMatrix matrix = *iter.fMatrix;
1263            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1264            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1265            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
1266            SkAutoUnref aur(NULL);
1267            if (!cache) {
1268                cache = SkImageFilter::Cache::Create();
1269                aur.reset(cache);
1270            }
1271            SkImageFilter::Context ctx(matrix, clipBounds, cache);
1272            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1273                SkPaint tmpUnfiltered(*paint);
1274                tmpUnfiltered.setImageFilter(NULL);
1275                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1276                                   tmpUnfiltered);
1277            }
1278        } else {
1279            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1280        }
1281    }
1282    LOOPER_END
1283}
1284
1285void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1286                          const SkPaint* paint) {
1287    if (bitmap.drawsNothing()) {
1288        return;
1289    }
1290    SkDEBUGCODE(bitmap.validate();)
1291    CHECK_LOCKCOUNT_BALANCE(bitmap);
1292
1293    SkPaint tmp;
1294    if (NULL == paint) {
1295        paint = &tmp;
1296    }
1297
1298    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1299
1300    while (iter.next()) {
1301        paint = &looper.paint();
1302        SkImageFilter* filter = paint->getImageFilter();
1303        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1304        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1305            SkDeviceImageFilterProxy proxy(iter.fDevice);
1306            SkBitmap dst;
1307            SkIPoint offset = SkIPoint::Make(0, 0);
1308            SkMatrix matrix = *iter.fMatrix;
1309            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1310            SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1311            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
1312            SkAutoUnref aur(NULL);
1313            if (!cache) {
1314                cache = SkImageFilter::Cache::Create();
1315                aur.reset(cache);
1316            }
1317            SkImageFilter::Context ctx(matrix, clipBounds, cache);
1318            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1319                SkPaint tmpUnfiltered(*paint);
1320                tmpUnfiltered.setImageFilter(NULL);
1321                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1322                                         tmpUnfiltered);
1323            }
1324        } else {
1325            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1326        }
1327    }
1328    LOOPER_END
1329}
1330
1331/////////////////////////////////////////////////////////////////////////////
1332void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1333    SkMatrix m;
1334    m.setTranslate(dx, dy);
1335    this->concat(m);
1336}
1337
1338void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1339    SkMatrix m;
1340    m.setScale(sx, sy);
1341    this->concat(m);
1342}
1343
1344void SkCanvas::rotate(SkScalar degrees) {
1345    SkMatrix m;
1346    m.setRotate(degrees);
1347    this->concat(m);
1348}
1349
1350void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1351    SkMatrix m;
1352    m.setSkew(sx, sy);
1353    this->concat(m);
1354}
1355
1356void SkCanvas::didConcat(const SkMatrix&) {
1357    // Do nothing. Subclasses may do something.
1358}
1359
1360void SkCanvas::concat(const SkMatrix& matrix) {
1361    if (matrix.isIdentity()) {
1362        return;
1363    }
1364
1365    fDeviceCMDirty = true;
1366    fCachedLocalClipBoundsDirty = true;
1367    fMCRec->fMatrix->preConcat(matrix);
1368
1369    this->didConcat(matrix);
1370}
1371
1372void SkCanvas::didSetMatrix(const SkMatrix&) {
1373    // Do nothing. Subclasses may do something.
1374}
1375
1376void SkCanvas::setMatrix(const SkMatrix& matrix) {
1377    fDeviceCMDirty = true;
1378    fCachedLocalClipBoundsDirty = true;
1379    *fMCRec->fMatrix = matrix;
1380    this->didSetMatrix(matrix);
1381}
1382
1383void SkCanvas::resetMatrix() {
1384    SkMatrix matrix;
1385
1386    matrix.reset();
1387    this->setMatrix(matrix);
1388}
1389
1390//////////////////////////////////////////////////////////////////////////////
1391
1392void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1393    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1394    this->onClipRect(rect, op, edgeStyle);
1395}
1396
1397void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1398#ifdef SK_ENABLE_CLIP_QUICKREJECT
1399    if (SkRegion::kIntersect_Op == op) {
1400        if (fMCRec->fRasterClip->isEmpty()) {
1401            return false;
1402        }
1403
1404        if (this->quickReject(rect)) {
1405            fDeviceCMDirty = true;
1406            fCachedLocalClipBoundsDirty = true;
1407
1408            fClipStack.clipEmpty();
1409            return fMCRec->fRasterClip->setEmpty();
1410        }
1411    }
1412#endif
1413
1414    AutoValidateClip avc(this);
1415
1416    fDeviceCMDirty = true;
1417    fCachedLocalClipBoundsDirty = true;
1418    if (!fAllowSoftClip) {
1419        edgeStyle = kHard_ClipEdgeStyle;
1420    }
1421
1422    if (fMCRec->fMatrix->rectStaysRect()) {
1423        // for these simpler matrices, we can stay a rect even after applying
1424        // the matrix. This means we don't have to a) make a path, and b) tell
1425        // the region code to scan-convert the path, only to discover that it
1426        // is really just a rect.
1427        SkRect      r;
1428
1429        fMCRec->fMatrix->mapRect(&r, rect);
1430        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1431        fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1432    } else {
1433        // since we're rotated or some such thing, we convert the rect to a path
1434        // and clip against that, since it can handle any matrix. However, to
1435        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1436        // we explicitly call "our" version of clipPath.
1437        SkPath  path;
1438
1439        path.addRect(rect);
1440        this->SkCanvas::onClipPath(path, op, edgeStyle);
1441    }
1442}
1443
1444static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
1445                             const SkPath& devPath, SkRegion::Op op, bool doAA) {
1446    // base is used to limit the size (and therefore memory allocation) of the
1447    // region that results from scan converting devPath.
1448    SkRegion base;
1449
1450    if (SkRegion::kIntersect_Op == op) {
1451        // since we are intersect, we can do better (tighter) with currRgn's
1452        // bounds, than just using the device. However, if currRgn is complex,
1453        // our region blitter may hork, so we do that case in two steps.
1454        if (currClip->isRect()) {
1455            // FIXME: we should also be able to do this when currClip->isBW(),
1456            // but relaxing the test above triggers GM asserts in
1457            // SkRgnBuilder::blitH(). We need to investigate what's going on.
1458            currClip->setPath(devPath, currClip->bwRgn(), doAA);
1459        } else {
1460            base.setRect(currClip->getBounds());
1461            SkRasterClip clip;
1462            clip.setPath(devPath, base, doAA);
1463            currClip->op(clip, op);
1464        }
1465    } else {
1466        const SkBaseDevice* device = canvas->getDevice();
1467        if (!device) {
1468            currClip->setEmpty();
1469            return;
1470        }
1471
1472        base.setRect(0, 0, device->width(), device->height());
1473
1474        if (SkRegion::kReplace_Op == op) {
1475            currClip->setPath(devPath, base, doAA);
1476        } else {
1477            SkRasterClip clip;
1478            clip.setPath(devPath, base, doAA);
1479            currClip->op(clip, op);
1480        }
1481    }
1482}
1483
1484void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1485    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1486    if (rrect.isRect()) {
1487        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1488    } else {
1489        this->onClipRRect(rrect, op, edgeStyle);
1490    }
1491}
1492
1493void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1494    SkRRect transformedRRect;
1495    if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
1496        AutoValidateClip avc(this);
1497
1498        fDeviceCMDirty = true;
1499        fCachedLocalClipBoundsDirty = true;
1500        if (!fAllowSoftClip) {
1501            edgeStyle = kHard_ClipEdgeStyle;
1502        }
1503
1504        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1505
1506        SkPath devPath;
1507        devPath.addRRect(transformedRRect);
1508
1509        clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1510        return;
1511    }
1512
1513    SkPath path;
1514    path.addRRect(rrect);
1515    // call the non-virtual version
1516    this->SkCanvas::onClipPath(path, op, edgeStyle);
1517}
1518
1519void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1520    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1521    SkRect r;
1522    if (!path.isInverseFillType() && path.isRect(&r)) {
1523        this->onClipRect(r, op, edgeStyle);
1524    } else {
1525        this->onClipPath(path, op, edgeStyle);
1526    }
1527}
1528
1529void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1530#ifdef SK_ENABLE_CLIP_QUICKREJECT
1531    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1532        if (fMCRec->fRasterClip->isEmpty()) {
1533            return false;
1534        }
1535
1536        if (this->quickReject(path.getBounds())) {
1537            fDeviceCMDirty = true;
1538            fCachedLocalClipBoundsDirty = true;
1539
1540            fClipStack.clipEmpty();
1541            return fMCRec->fRasterClip->setEmpty();
1542        }
1543    }
1544#endif
1545
1546    AutoValidateClip avc(this);
1547
1548    fDeviceCMDirty = true;
1549    fCachedLocalClipBoundsDirty = true;
1550    if (!fAllowSoftClip) {
1551        edgeStyle = kHard_ClipEdgeStyle;
1552    }
1553
1554    SkPath devPath;
1555    path.transform(*fMCRec->fMatrix, &devPath);
1556
1557    // Check if the transfomation, or the original path itself
1558    // made us empty. Note this can also happen if we contained NaN
1559    // values. computing the bounds detects this, and will set our
1560    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1561    if (devPath.getBounds().isEmpty()) {
1562        // resetting the path will remove any NaN or other wanky values
1563        // that might upset our scan converter.
1564        devPath.reset();
1565    }
1566
1567    // if we called path.swap() we could avoid a deep copy of this path
1568    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1569
1570    if (fAllowSimplifyClip) {
1571        devPath.reset();
1572        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1573        const SkClipStack* clipStack = getClipStack();
1574        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
1575        const SkClipStack::Element* element;
1576        while ((element = iter.next())) {
1577            SkClipStack::Element::Type type = element->getType();
1578            if (type == SkClipStack::Element::kEmpty_Type) {
1579                continue;
1580            }
1581            SkPath operand;
1582            element->asPath(&operand);
1583            SkRegion::Op elementOp = element->getOp();
1584            if (elementOp == SkRegion::kReplace_Op) {
1585                devPath = operand;
1586            } else {
1587                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1588            }
1589            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1590            // perhaps we need an API change to avoid this sort of mixed-signals about
1591            // clipping.
1592            if (element->isAA()) {
1593                edgeStyle = kSoft_ClipEdgeStyle;
1594            }
1595        }
1596        op = SkRegion::kReplace_Op;
1597    }
1598
1599    clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
1600}
1601
1602void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1603                                                   bool inverseFilled) {
1604    // This is for updating the clip conservatively using only bounds
1605    // information.
1606    // Contract:
1607    //    The current clip must contain the true clip. The true
1608    //    clip is the clip that would have normally been computed
1609    //    by calls to clipPath and clipRRect
1610    // Objective:
1611    //    Keep the current clip as small as possible without
1612    //    breaking the contract, using only clip bounding rectangles
1613    //    (for performance).
1614
1615    // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1616    // don't have to worry about getting caught in a loop. Thus anywhere
1617    // we call a virtual method, we explicitly prefix it with
1618    // SkCanvas:: to be sure to call the base-class.
1619
1620    if (inverseFilled) {
1621        switch (op) {
1622            case SkRegion::kIntersect_Op:
1623            case SkRegion::kDifference_Op:
1624                // These ops can only shrink the current clip. So leaving
1625                // the clip unchanged conservatively respects the contract.
1626                break;
1627            case SkRegion::kUnion_Op:
1628            case SkRegion::kReplace_Op:
1629            case SkRegion::kReverseDifference_Op:
1630            case SkRegion::kXOR_Op: {
1631                    // These ops can grow the current clip up to the extents of
1632                    // the input clip, which is inverse filled, so we just set
1633                    // the current clip to the device bounds.
1634                    SkRect deviceBounds;
1635                    SkIRect deviceIBounds;
1636                    this->getDevice()->getGlobalBounds(&deviceIBounds);
1637                    deviceBounds = SkRect::Make(deviceIBounds);
1638
1639                    // set the clip in device space
1640                    SkMatrix savedMatrix = this->getTotalMatrix();
1641                    this->SkCanvas::setMatrix(SkMatrix::I());
1642                    this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
1643                                               kHard_ClipEdgeStyle);
1644                    this->setMatrix(savedMatrix);
1645                    break;
1646            }
1647            default:
1648                SkASSERT(0); // unhandled op?
1649        }
1650    } else {
1651        // Not inverse filled
1652        switch (op) {
1653            case SkRegion::kIntersect_Op:
1654            case SkRegion::kUnion_Op:
1655            case SkRegion::kReplace_Op:
1656                this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
1657                break;
1658            case SkRegion::kDifference_Op:
1659                // Difference can only shrink the current clip.
1660                // Leaving clip unchanged conservatively fullfills the contract.
1661                break;
1662            case SkRegion::kReverseDifference_Op:
1663                // To reverse, we swap in the bounds with a replace op.
1664                // As with difference, leave it unchanged.
1665                this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
1666                break;
1667            case SkRegion::kXOR_Op:
1668                // Be conservative, based on (A XOR B) always included in (A union B),
1669                // which is always included in (bounds(A) union bounds(B))
1670                this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
1671                break;
1672            default:
1673                SkASSERT(0); // unhandled op?
1674        }
1675    }
1676}
1677
1678void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1679    this->onClipRegion(rgn, op);
1680}
1681
1682void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1683    AutoValidateClip avc(this);
1684
1685    fDeviceCMDirty = true;
1686    fCachedLocalClipBoundsDirty = true;
1687
1688    // todo: signal fClipStack that we have a region, and therefore (I guess)
1689    // we have to ignore it, and use the region directly?
1690    fClipStack.clipDevRect(rgn.getBounds(), op);
1691
1692    fMCRec->fRasterClip->op(rgn, op);
1693}
1694
1695#ifdef SK_DEBUG
1696void SkCanvas::validateClip() const {
1697    // construct clipRgn from the clipstack
1698    const SkBaseDevice* device = this->getDevice();
1699    if (!device) {
1700        SkASSERT(this->isClipEmpty());
1701        return;
1702    }
1703
1704    SkIRect ir;
1705    ir.set(0, 0, device->width(), device->height());
1706    SkRasterClip tmpClip(ir);
1707
1708    SkClipStack::B2TIter                iter(fClipStack);
1709    const SkClipStack::Element* element;
1710    while ((element = iter.next()) != NULL) {
1711        switch (element->getType()) {
1712            case SkClipStack::Element::kRect_Type:
1713                element->getRect().round(&ir);
1714                tmpClip.op(ir, element->getOp());
1715                break;
1716            case SkClipStack::Element::kEmpty_Type:
1717                tmpClip.setEmpty();
1718                break;
1719            default: {
1720                SkPath path;
1721                element->asPath(&path);
1722                clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
1723                break;
1724            }
1725        }
1726    }
1727}
1728#endif
1729
1730void SkCanvas::replayClips(ClipVisitor* visitor) const {
1731    SkClipStack::B2TIter                iter(fClipStack);
1732    const SkClipStack::Element*         element;
1733
1734    static const SkRect kEmpty = { 0, 0, 0, 0 };
1735    while ((element = iter.next()) != NULL) {
1736        switch (element->getType()) {
1737            case SkClipStack::Element::kPath_Type:
1738                visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
1739                break;
1740            case SkClipStack::Element::kRRect_Type:
1741                visitor->clipRRect(element->getRRect(), element->getOp(), element->isAA());
1742                break;
1743            case SkClipStack::Element::kRect_Type:
1744                visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
1745                break;
1746            case SkClipStack::Element::kEmpty_Type:
1747                visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
1748                break;
1749        }
1750    }
1751}
1752
1753///////////////////////////////////////////////////////////////////////////////
1754
1755bool SkCanvas::isClipEmpty() const {
1756    return fMCRec->fRasterClip->isEmpty();
1757}
1758
1759bool SkCanvas::isClipRect() const {
1760    return fMCRec->fRasterClip->isRect();
1761}
1762
1763bool SkCanvas::quickReject(const SkRect& rect) const {
1764
1765    if (!rect.isFinite())
1766        return true;
1767
1768    if (fMCRec->fRasterClip->isEmpty()) {
1769        return true;
1770    }
1771
1772    if (fMCRec->fMatrix->hasPerspective()) {
1773        SkRect dst;
1774        fMCRec->fMatrix->mapRect(&dst, rect);
1775        SkIRect idst;
1776        dst.roundOut(&idst);
1777        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1778    } else {
1779        const SkRect& clipR = this->getLocalClipBounds();
1780
1781        // for speed, do the most likely reject compares first
1782        // TODO: should we use | instead, or compare all 4 at once?
1783        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1784            return true;
1785        }
1786        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1787            return true;
1788        }
1789        return false;
1790    }
1791}
1792
1793bool SkCanvas::quickReject(const SkPath& path) const {
1794    return path.isEmpty() || this->quickReject(path.getBounds());
1795}
1796
1797bool SkCanvas::getClipBounds(SkRect* bounds) const {
1798    SkIRect ibounds;
1799    if (!this->getClipDeviceBounds(&ibounds)) {
1800        return false;
1801    }
1802
1803    SkMatrix inverse;
1804    // if we can't invert the CTM, we can't return local clip bounds
1805    if (!fMCRec->fMatrix->invert(&inverse)) {
1806        if (bounds) {
1807            bounds->setEmpty();
1808        }
1809        return false;
1810    }
1811
1812    if (NULL != bounds) {
1813        SkRect r;
1814        // adjust it outwards in case we are antialiasing
1815        const int inset = 1;
1816
1817        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1818               ibounds.fRight + inset, ibounds.fBottom + inset);
1819        inverse.mapRect(bounds, r);
1820    }
1821    return true;
1822}
1823
1824bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1825    const SkRasterClip& clip = *fMCRec->fRasterClip;
1826    if (clip.isEmpty()) {
1827        if (bounds) {
1828            bounds->setEmpty();
1829        }
1830        return false;
1831    }
1832
1833    if (NULL != bounds) {
1834        *bounds = clip.getBounds();
1835    }
1836    return true;
1837}
1838
1839const SkMatrix& SkCanvas::getTotalMatrix() const {
1840    return *fMCRec->fMatrix;
1841}
1842
1843#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
1844SkCanvas::ClipType SkCanvas::getClipType() const {
1845    if (fMCRec->fRasterClip->isEmpty()) {
1846        return kEmpty_ClipType;
1847    }
1848    if (fMCRec->fRasterClip->isRect()) {
1849        return kRect_ClipType;
1850    }
1851    return kComplex_ClipType;
1852}
1853#endif
1854
1855#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
1856const SkRegion& SkCanvas::getTotalClip() const {
1857    return fMCRec->fRasterClip->forceGetBW();
1858}
1859#endif
1860
1861const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1862    return fMCRec->fRasterClip->forceGetBW();
1863}
1864
1865void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
1866    path->reset();
1867
1868    const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
1869    if (rgn.isEmpty()) {
1870        return;
1871    }
1872    (void)rgn.getBoundaryPath(path);
1873}
1874
1875GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1876    SkBaseDevice* dev = this->getTopDevice();
1877    return dev ? dev->accessRenderTarget() : NULL;
1878}
1879
1880SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
1881    SkBaseDevice* device = this->getTopDevice();
1882    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
1883}
1884
1885GrContext* SkCanvas::getGrContext() {
1886#if SK_SUPPORT_GPU
1887    SkBaseDevice* device = this->getTopDevice();
1888    if (NULL != device) {
1889        GrRenderTarget* renderTarget = device->accessRenderTarget();
1890        if (NULL != renderTarget) {
1891            return renderTarget->getContext();
1892        }
1893    }
1894#endif
1895
1896    return NULL;
1897
1898}
1899
1900void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1901                          const SkPaint& paint) {
1902    if (outer.isEmpty()) {
1903        return;
1904    }
1905    if (inner.isEmpty()) {
1906        this->drawRRect(outer, paint);
1907        return;
1908    }
1909
1910    // We don't have this method (yet), but technically this is what we should
1911    // be able to assert...
1912    // SkASSERT(outer.contains(inner));
1913    //
1914    // For now at least check for containment of bounds
1915    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1916
1917    this->onDrawDRRect(outer, inner, paint);
1918}
1919
1920//////////////////////////////////////////////////////////////////////////////
1921//  These are the virtual drawing methods
1922//////////////////////////////////////////////////////////////////////////////
1923
1924void SkCanvas::clear(SkColor color) {
1925    SkDrawIter  iter(this);
1926    this->predrawNotify();
1927    while (iter.next()) {
1928        iter.fDevice->clear(color);
1929    }
1930}
1931
1932void SkCanvas::onDiscard() {
1933    if (NULL != fSurfaceBase) {
1934        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1935    }
1936}
1937
1938void SkCanvas::drawPaint(const SkPaint& paint) {
1939    this->internalDrawPaint(paint);
1940}
1941
1942void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1943    CHECK_SHADER_NOSETCONTEXT(paint);
1944
1945    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1946
1947    while (iter.next()) {
1948        iter.fDevice->drawPaint(iter, looper.paint());
1949    }
1950
1951    LOOPER_END
1952}
1953
1954void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1955                          const SkPaint& paint) {
1956    if ((long)count <= 0) {
1957        return;
1958    }
1959
1960    CHECK_SHADER_NOSETCONTEXT(paint);
1961
1962    SkRect r, storage;
1963    const SkRect* bounds = NULL;
1964    if (paint.canComputeFastBounds()) {
1965        // special-case 2 points (common for drawing a single line)
1966        if (2 == count) {
1967            r.set(pts[0], pts[1]);
1968        } else {
1969            r.set(pts, SkToInt(count));
1970        }
1971        bounds = &paint.computeFastStrokeBounds(r, &storage);
1972        if (this->quickReject(*bounds)) {
1973            return;
1974        }
1975    }
1976
1977    SkASSERT(pts != NULL);
1978
1979    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1980
1981    while (iter.next()) {
1982        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1983    }
1984
1985    LOOPER_END
1986}
1987
1988void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1989    CHECK_SHADER_NOSETCONTEXT(paint);
1990
1991    SkRect storage;
1992    const SkRect* bounds = NULL;
1993    if (paint.canComputeFastBounds()) {
1994        bounds = &paint.computeFastBounds(r, &storage);
1995        if (this->quickReject(*bounds)) {
1996            return;
1997        }
1998    }
1999
2000    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
2001
2002    while (iter.next()) {
2003        iter.fDevice->drawRect(iter, r, looper.paint());
2004    }
2005
2006    LOOPER_END
2007}
2008
2009void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
2010    CHECK_SHADER_NOSETCONTEXT(paint);
2011
2012    SkRect storage;
2013    const SkRect* bounds = NULL;
2014    if (paint.canComputeFastBounds()) {
2015        bounds = &paint.computeFastBounds(oval, &storage);
2016        if (this->quickReject(*bounds)) {
2017            return;
2018        }
2019    }
2020
2021    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2022
2023    while (iter.next()) {
2024        iter.fDevice->drawOval(iter, oval, looper.paint());
2025    }
2026
2027    LOOPER_END
2028}
2029
2030void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
2031    CHECK_SHADER_NOSETCONTEXT(paint);
2032
2033    SkRect storage;
2034    const SkRect* bounds = NULL;
2035    if (paint.canComputeFastBounds()) {
2036        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
2037        if (this->quickReject(*bounds)) {
2038            return;
2039        }
2040    }
2041
2042    if (rrect.isRect()) {
2043        // call the non-virtual version
2044        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2045        return;
2046    } else if (rrect.isOval()) {
2047        // call the non-virtual version
2048        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2049        return;
2050    }
2051
2052    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2053
2054    while (iter.next()) {
2055        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2056    }
2057
2058    LOOPER_END
2059}
2060
2061void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2062                            const SkPaint& paint) {
2063    CHECK_SHADER_NOSETCONTEXT(paint);
2064
2065    SkRect storage;
2066    const SkRect* bounds = NULL;
2067    if (paint.canComputeFastBounds()) {
2068        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
2069        if (this->quickReject(*bounds)) {
2070            return;
2071        }
2072    }
2073
2074    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2075
2076    while (iter.next()) {
2077        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2078    }
2079
2080    LOOPER_END
2081}
2082
2083void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
2084    CHECK_SHADER_NOSETCONTEXT(paint);
2085
2086    if (!path.isFinite()) {
2087        return;
2088    }
2089
2090    SkRect storage;
2091    const SkRect* bounds = NULL;
2092    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2093        const SkRect& pathBounds = path.getBounds();
2094        bounds = &paint.computeFastBounds(pathBounds, &storage);
2095        if (this->quickReject(*bounds)) {
2096            return;
2097        }
2098    }
2099
2100    const SkRect& r = path.getBounds();
2101    if (r.width() <= 0 && r.height() <= 0) {
2102        if (path.isInverseFillType()) {
2103            this->internalDrawPaint(paint);
2104        }
2105        return;
2106    }
2107
2108    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
2109
2110    while (iter.next()) {
2111        iter.fDevice->drawPath(iter, path, looper.paint());
2112    }
2113
2114    LOOPER_END
2115}
2116
2117void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
2118                          const SkPaint* paint) {
2119    SkDEBUGCODE(bitmap.validate();)
2120
2121    if (NULL == paint || paint->canComputeFastBounds()) {
2122        SkRect bounds = {
2123            x, y,
2124            x + SkIntToScalar(bitmap.width()),
2125            y + SkIntToScalar(bitmap.height())
2126        };
2127        if (paint) {
2128            (void)paint->computeFastBounds(bounds, &bounds);
2129        }
2130        if (this->quickReject(bounds)) {
2131            return;
2132        }
2133    }
2134
2135    SkMatrix matrix;
2136    matrix.setTranslate(x, y);
2137    this->internalDrawBitmap(bitmap, matrix, paint);
2138}
2139
2140// this one is non-virtual, so it can be called safely by other canvas apis
2141void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2142                                      const SkRect& dst, const SkPaint* paint,
2143                                      DrawBitmapRectFlags flags) {
2144    if (bitmap.drawsNothing() || dst.isEmpty()) {
2145        return;
2146    }
2147
2148    CHECK_LOCKCOUNT_BALANCE(bitmap);
2149
2150    SkRect storage;
2151    const SkRect* bounds = &dst;
2152    if (NULL == paint || paint->canComputeFastBounds()) {
2153        if (paint) {
2154            bounds = &paint->computeFastBounds(dst, &storage);
2155        }
2156        if (this->quickReject(*bounds)) {
2157            return;
2158        }
2159    }
2160
2161    SkLazyPaint lazy;
2162    if (NULL == paint) {
2163        paint = lazy.init();
2164    }
2165
2166    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2167
2168    while (iter.next()) {
2169        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2170    }
2171
2172    LOOPER_END
2173}
2174
2175void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
2176                                    const SkRect& dst, const SkPaint* paint,
2177                                    DrawBitmapRectFlags flags) {
2178    SkDEBUGCODE(bitmap.validate();)
2179    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
2180}
2181
2182void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
2183                                const SkPaint* paint) {
2184    SkDEBUGCODE(bitmap.validate();)
2185    this->internalDrawBitmap(bitmap, matrix, paint);
2186}
2187
2188void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
2189                                      const SkIRect& center, const SkRect& dst,
2190                                      const SkPaint* paint) {
2191    if (bitmap.drawsNothing()) {
2192        return;
2193    }
2194    if (NULL == paint || paint->canComputeFastBounds()) {
2195        SkRect storage;
2196        const SkRect* bounds = &dst;
2197        if (paint) {
2198            bounds = &paint->computeFastBounds(dst, &storage);
2199        }
2200        if (this->quickReject(*bounds)) {
2201            return;
2202        }
2203    }
2204
2205    const int32_t w = bitmap.width();
2206    const int32_t h = bitmap.height();
2207
2208    SkIRect c = center;
2209    // pin center to the bounds of the bitmap
2210    c.fLeft = SkMax32(0, center.fLeft);
2211    c.fTop = SkMax32(0, center.fTop);
2212    c.fRight = SkPin32(center.fRight, c.fLeft, w);
2213    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
2214
2215    const SkScalar srcX[4] = {
2216        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
2217    };
2218    const SkScalar srcY[4] = {
2219        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
2220    };
2221    SkScalar dstX[4] = {
2222        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
2223        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
2224    };
2225    SkScalar dstY[4] = {
2226        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
2227        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
2228    };
2229
2230    if (dstX[1] > dstX[2]) {
2231        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
2232        dstX[2] = dstX[1];
2233    }
2234
2235    if (dstY[1] > dstY[2]) {
2236        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2237        dstY[2] = dstY[1];
2238    }
2239
2240    for (int y = 0; y < 3; y++) {
2241        SkRect s, d;
2242
2243        s.fTop = srcY[y];
2244        s.fBottom = srcY[y+1];
2245        d.fTop = dstY[y];
2246        d.fBottom = dstY[y+1];
2247        for (int x = 0; x < 3; x++) {
2248            s.fLeft = srcX[x];
2249            s.fRight = srcX[x+1];
2250            d.fLeft = dstX[x];
2251            d.fRight = dstX[x+1];
2252            this->internalDrawBitmapRect(bitmap, &s, d, paint,
2253                                         kNone_DrawBitmapRectFlag);
2254        }
2255    }
2256}
2257
2258void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
2259                              const SkRect& dst, const SkPaint* paint) {
2260    SkDEBUGCODE(bitmap.validate();)
2261
2262    // Need a device entry-point, so gpu can use a mesh
2263    this->internalDrawBitmapNine(bitmap, center, dst, paint);
2264}
2265
2266class SkDeviceFilteredPaint {
2267public:
2268    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2269        SkBaseDevice::TextFlags flags;
2270        if (device->filterTextFlags(paint, &flags)) {
2271            SkPaint* newPaint = fLazy.set(paint);
2272            newPaint->setFlags(flags.fFlags);
2273            newPaint->setHinting(flags.fHinting);
2274            fPaint = newPaint;
2275        } else {
2276            fPaint = &paint;
2277        }
2278    }
2279
2280    const SkPaint& paint() const { return *fPaint; }
2281
2282private:
2283    const SkPaint*  fPaint;
2284    SkLazyPaint     fLazy;
2285};
2286
2287void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2288                        const SkRect& r, SkScalar textSize) {
2289    if (paint.getStyle() == SkPaint::kFill_Style) {
2290        draw.fDevice->drawRect(draw, r, paint);
2291    } else {
2292        SkPaint p(paint);
2293        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2294        draw.fDevice->drawRect(draw, r, p);
2295    }
2296}
2297
2298void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2299                                   const char text[], size_t byteLength,
2300                                   SkScalar x, SkScalar y) {
2301    SkASSERT(byteLength == 0 || text != NULL);
2302
2303    // nothing to draw
2304    if (text == NULL || byteLength == 0 ||
2305        draw.fClip->isEmpty() ||
2306        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2307        return;
2308    }
2309
2310    SkScalar    width = 0;
2311    SkPoint     start;
2312
2313    start.set(0, 0);    // to avoid warning
2314    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2315                            SkPaint::kStrikeThruText_Flag)) {
2316        width = paint.measureText(text, byteLength);
2317
2318        SkScalar offsetX = 0;
2319        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2320            offsetX = SkScalarHalf(width);
2321        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2322            offsetX = width;
2323        }
2324        start.set(x - offsetX, y);
2325    }
2326
2327    if (0 == width) {
2328        return;
2329    }
2330
2331    uint32_t flags = paint.getFlags();
2332
2333    if (flags & (SkPaint::kUnderlineText_Flag |
2334                 SkPaint::kStrikeThruText_Flag)) {
2335        SkScalar textSize = paint.getTextSize();
2336        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2337        SkRect   r;
2338
2339        r.fLeft = start.fX;
2340        r.fRight = start.fX + width;
2341
2342        if (flags & SkPaint::kUnderlineText_Flag) {
2343            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2344                                             start.fY);
2345            r.fTop = offset;
2346            r.fBottom = offset + height;
2347            DrawRect(draw, paint, r, textSize);
2348        }
2349        if (flags & SkPaint::kStrikeThruText_Flag) {
2350            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2351                                             start.fY);
2352            r.fTop = offset;
2353            r.fBottom = offset + height;
2354            DrawRect(draw, paint, r, textSize);
2355        }
2356    }
2357}
2358
2359void SkCanvas::drawText(const void* text, size_t byteLength,
2360                        SkScalar x, SkScalar y, const SkPaint& paint) {
2361    CHECK_SHADER_NOSETCONTEXT(paint);
2362
2363    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2364
2365    while (iter.next()) {
2366        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2367        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2368        DrawTextDecorations(iter, dfp.paint(),
2369                            static_cast<const char*>(text), byteLength, x, y);
2370    }
2371
2372    LOOPER_END
2373}
2374
2375void SkCanvas::drawPosText(const void* text, size_t byteLength,
2376                           const SkPoint pos[], const SkPaint& paint) {
2377    CHECK_SHADER_NOSETCONTEXT(paint);
2378
2379    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2380
2381    while (iter.next()) {
2382        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2383        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2384                                  dfp.paint());
2385    }
2386
2387    LOOPER_END
2388}
2389
2390void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
2391                            const SkScalar xpos[], SkScalar constY,
2392                            const SkPaint& paint) {
2393    CHECK_SHADER_NOSETCONTEXT(paint);
2394
2395    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2396
2397    while (iter.next()) {
2398        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2399        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2400                                  dfp.paint());
2401    }
2402
2403    LOOPER_END
2404}
2405
2406void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
2407                              const SkPath& path, const SkMatrix* matrix,
2408                              const SkPaint& paint) {
2409    CHECK_SHADER_NOSETCONTEXT(paint);
2410
2411    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2412
2413    while (iter.next()) {
2414        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2415                                     matrix, looper.paint());
2416    }
2417
2418    LOOPER_END
2419}
2420
2421void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
2422                            const SkPoint verts[], const SkPoint texs[],
2423                            const SkColor colors[], SkXfermode* xmode,
2424                            const uint16_t indices[], int indexCount,
2425                            const SkPaint& paint) {
2426    CHECK_SHADER_NOSETCONTEXT(paint);
2427
2428    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2429
2430    while (iter.next()) {
2431        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2432                                   colors, xmode, indices, indexCount,
2433                                   looper.paint());
2434    }
2435
2436    LOOPER_END
2437}
2438
2439//////////////////////////////////////////////////////////////////////////////
2440// These methods are NOT virtual, and therefore must call back into virtual
2441// methods, rather than actually drawing themselves.
2442//////////////////////////////////////////////////////////////////////////////
2443
2444void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2445                        SkXfermode::Mode mode) {
2446    SkPaint paint;
2447
2448    paint.setARGB(a, r, g, b);
2449    if (SkXfermode::kSrcOver_Mode != mode) {
2450        paint.setXfermodeMode(mode);
2451    }
2452    this->drawPaint(paint);
2453}
2454
2455void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2456    SkPaint paint;
2457
2458    paint.setColor(c);
2459    if (SkXfermode::kSrcOver_Mode != mode) {
2460        paint.setXfermodeMode(mode);
2461    }
2462    this->drawPaint(paint);
2463}
2464
2465void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2466    SkPoint pt;
2467
2468    pt.set(x, y);
2469    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2470}
2471
2472void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2473    SkPoint pt;
2474    SkPaint paint;
2475
2476    pt.set(x, y);
2477    paint.setColor(color);
2478    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2479}
2480
2481void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2482                        const SkPaint& paint) {
2483    SkPoint pts[2];
2484
2485    pts[0].set(x0, y0);
2486    pts[1].set(x1, y1);
2487    this->drawPoints(kLines_PointMode, 2, pts, paint);
2488}
2489
2490void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2491                              SkScalar right, SkScalar bottom,
2492                              const SkPaint& paint) {
2493    SkRect  r;
2494
2495    r.set(left, top, right, bottom);
2496    this->drawRect(r, paint);
2497}
2498
2499void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2500                          const SkPaint& paint) {
2501    if (radius < 0) {
2502        radius = 0;
2503    }
2504
2505    SkRect  r;
2506    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2507    this->drawOval(r, paint);
2508}
2509
2510void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2511                             const SkPaint& paint) {
2512    if (rx > 0 && ry > 0) {
2513        if (paint.canComputeFastBounds()) {
2514            SkRect storage;
2515            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2516                return;
2517            }
2518        }
2519        SkRRect rrect;
2520        rrect.setRectXY(r, rx, ry);
2521        this->drawRRect(rrect, paint);
2522    } else {
2523        this->drawRect(r, paint);
2524    }
2525}
2526
2527void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2528                       SkScalar sweepAngle, bool useCenter,
2529                       const SkPaint& paint) {
2530    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2531        this->drawOval(oval, paint);
2532    } else {
2533        SkPath  path;
2534        if (useCenter) {
2535            path.moveTo(oval.centerX(), oval.centerY());
2536        }
2537        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2538        if (useCenter) {
2539            path.close();
2540        }
2541        this->drawPath(path, paint);
2542    }
2543}
2544
2545void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2546                                const SkPath& path, SkScalar hOffset,
2547                                SkScalar vOffset, const SkPaint& paint) {
2548    SkMatrix    matrix;
2549
2550    matrix.setTranslate(hOffset, vOffset);
2551    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2552}
2553
2554///////////////////////////////////////////////////////////////////////////////
2555void SkCanvas::EXPERIMENTAL_optimize(SkPicture* picture) {
2556    SkBaseDevice* device = this->getDevice();
2557    if (NULL != device) {
2558        device->EXPERIMENTAL_optimize(picture);
2559    }
2560}
2561
2562void SkCanvas::EXPERIMENTAL_purge(SkPicture* picture) {
2563    SkBaseDevice* device = this->getTopDevice();
2564    if (NULL != device) {
2565        device->EXPERIMENTAL_purge(picture);
2566    }
2567}
2568
2569void SkCanvas::drawPicture(SkPicture& picture) {
2570    SkBaseDevice* device = this->getTopDevice();
2571    if (NULL != device) {
2572        // Canvas has to first give the device the opportunity to render
2573        // the picture itself.
2574        if (device->EXPERIMENTAL_drawPicture(this, &picture)) {
2575            return; // the device has rendered the entire picture
2576        }
2577    }
2578
2579    picture.draw(this);
2580}
2581
2582///////////////////////////////////////////////////////////////////////////////
2583///////////////////////////////////////////////////////////////////////////////
2584
2585SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2586    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2587
2588    SkASSERT(canvas);
2589
2590    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2591    fDone = !fImpl->next();
2592}
2593
2594SkCanvas::LayerIter::~LayerIter() {
2595    fImpl->~SkDrawIter();
2596}
2597
2598void SkCanvas::LayerIter::next() {
2599    fDone = !fImpl->next();
2600}
2601
2602SkBaseDevice* SkCanvas::LayerIter::device() const {
2603    return fImpl->getDevice();
2604}
2605
2606const SkMatrix& SkCanvas::LayerIter::matrix() const {
2607    return fImpl->getMatrix();
2608}
2609
2610const SkPaint& SkCanvas::LayerIter::paint() const {
2611    const SkPaint* paint = fImpl->getPaint();
2612    if (NULL == paint) {
2613        paint = &fDefaultPaint;
2614    }
2615    return *paint;
2616}
2617
2618const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2619int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2620int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2621
2622///////////////////////////////////////////////////////////////////////////////
2623
2624SkCanvas::ClipVisitor::~ClipVisitor() { }
2625
2626///////////////////////////////////////////////////////////////////////////////
2627
2628static bool supported_for_raster_canvas(const SkImageInfo& info) {
2629    switch (info.alphaType()) {
2630        case kPremul_SkAlphaType:
2631        case kOpaque_SkAlphaType:
2632            break;
2633        default:
2634            return false;
2635    }
2636
2637    switch (info.colorType()) {
2638        case kAlpha_8_SkColorType:
2639        case kRGB_565_SkColorType:
2640        case kN32_SkColorType:
2641            break;
2642        default:
2643            return false;
2644    }
2645
2646    return true;
2647}
2648
2649SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
2650    if (!supported_for_raster_canvas(info)) {
2651        return NULL;
2652    }
2653
2654    SkBitmap bitmap;
2655    if (!bitmap.allocPixels(info)) {
2656        return NULL;
2657    }
2658
2659    // should this functionality be moved into allocPixels()?
2660    if (!bitmap.info().isOpaque()) {
2661        bitmap.eraseColor(0);
2662    }
2663    return SkNEW_ARGS(SkCanvas, (bitmap));
2664}
2665
2666SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2667    if (!supported_for_raster_canvas(info)) {
2668        return NULL;
2669    }
2670
2671    SkBitmap bitmap;
2672    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2673        return NULL;
2674    }
2675    return SkNEW_ARGS(SkCanvas, (bitmap));
2676}
2677