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