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