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