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