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