Home | History | Annotate | Download | only in core
      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
     71 class AutoCheckLockCountBalance {
     72 public:
     73     AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
     74 };
     75 #else
     76 class AutoCheckLockCountBalance {
     77 public:
     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 
     86 private:
     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 
     98 typedef SkTLazy<SkPaint> SkLazyPaint;
     99 
    100 void 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 */
    115 struct 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 
    179 private:
    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 */
    190 class SkCanvas::MCRec {
    191 public:
    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 
    245 private:
    246     SkMatrix        fMatrixStorage;
    247     SkRasterClip    fRasterClipStorage;
    248 };
    249 
    250 class SkDrawIter : public SkDraw {
    251 public:
    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 
    296 private:
    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 
    307 class AutoDrawLooper {
    308 public:
    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 
    365 private:
    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 
    381 bool 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 
    441 SkBaseDevice* 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 
    462 SkCanvas::SkCanvas()
    463     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    464 {
    465     inc_canvas();
    466 
    467     this->init(NULL);
    468 }
    469 
    470 SkCanvas::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 
    480 SkCanvas::SkCanvas(SkBaseDevice* device)
    481     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    482 {
    483     inc_canvas();
    484 
    485     this->init(device);
    486 }
    487 
    488 SkCanvas::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 
    496 SkCanvas::~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 
    508 SkDrawFilter* SkCanvas::getDrawFilter() const {
    509     return fMCRec->fFilter;
    510 }
    511 
    512 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
    513     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
    514     return filter;
    515 }
    516 
    517 SkMetaData& 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 
    528 void SkCanvas::flush() {
    529     SkBaseDevice* device = this->getDevice();
    530     if (device) {
    531         device->flush();
    532     }
    533 }
    534 
    535 SkISize SkCanvas::getTopLayerSize() const {
    536     SkBaseDevice* d = this->getTopDevice();
    537     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
    538 }
    539 
    540 SkIPoint SkCanvas::getTopLayerOrigin() const {
    541     SkBaseDevice* d = this->getTopDevice();
    542     return d ? d->getOrigin() : SkIPoint::Make(0, 0);
    543 }
    544 
    545 SkISize SkCanvas::getBaseLayerSize() const {
    546     SkBaseDevice* d = this->getDevice();
    547     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
    548 }
    549 
    550 SkBaseDevice* 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 
    557 SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
    558     if (updateMatrixClip) {
    559         const_cast<SkCanvas*>(this)->updateDeviceCMCache();
    560     }
    561     return fMCRec->fTopLayer->fDevice;
    562 }
    563 
    564 SkBaseDevice* 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 
    616 bool 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 
    641 bool 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 
    660 bool 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 
    705 bool 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 
    717 bool 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 
    760 SkCanvas* SkCanvas::canvasForDrawIter() {
    761     return this;
    762 }
    763 
    764 //////////////////////////////////////////////////////////////////////////////
    765 
    766 void 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 
    786 int 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 
    801 int SkCanvas::save() {
    802     this->willSave(kMatrixClip_SaveFlag);
    803     return this->internalSave(kMatrixClip_SaveFlag);
    804 }
    805 
    806 int SkCanvas::save(SaveFlags flags) {
    807     this->willSave(flags);
    808     // call shared impl
    809     return this->internalSave(flags);
    810 }
    811 
    812 static 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 
    820 bool 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 
    864 int 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 
    869 int 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 
    875 static SkBaseDevice* create_compatible_device(SkCanvas* canvas,
    876                                               const SkImageInfo& info) {
    877     SkBaseDevice* device = canvas->getDevice();
    878     return device ? device->createCompatibleDevice(info) : NULL;
    879 }
    880 
    881 int 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 
    945 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
    946     return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
    947 }
    948 
    949 int 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 
    960 void SkCanvas::restore() {
    961     // check for underflow
    962     if (fMCStack.count() > 1) {
    963         this->willRestore();
    964         this->internalRestore();
    965     }
    966 }
    967 
    968 void 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 
   1007 int SkCanvas::getSaveCount() const {
   1008     return fMCStack.count();
   1009 }
   1010 
   1011 void 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 
   1023 bool SkCanvas::isDrawingToLayer() const {
   1024     return fSaveLayerCount > 0;
   1025 }
   1026 
   1027 SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
   1028     return this->onNewSurface(info);
   1029 }
   1030 
   1031 SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
   1032     SkBaseDevice* dev = this->getDevice();
   1033     return dev ? dev->newSurface(info) : NULL;
   1034 }
   1035 
   1036 SkImageInfo 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 
   1045 const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
   1046     return this->onPeekPixels(info, rowBytes);
   1047 }
   1048 
   1049 const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
   1050     SkBaseDevice* dev = this->getDevice();
   1051     return dev ? dev->peekPixels(info, rowBytes) : NULL;
   1052 }
   1053 
   1054 void* 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 
   1062 void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
   1063     SkBaseDevice* dev = this->getTopDevice();
   1064     return dev ? dev->accessPixels(info, rowBytes) : NULL;
   1065 }
   1066 
   1067 SkAutoROCanvasPixels::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 
   1083 bool 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 
   1092 void SkCanvas::onPushCull(const SkRect& cullRect) {
   1093     // do nothing. Subclasses may do something
   1094 }
   1095 
   1096 void 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.
   1103 void 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 
   1121 void 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 
   1143 void 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 
   1156 void 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 
   1187 void 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 
   1229 void 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 /////////////////////////////////////////////////////////////////////////////
   1276 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
   1277     SkMatrix m;
   1278     m.setTranslate(dx, dy);
   1279     this->concat(m);
   1280 }
   1281 
   1282 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
   1283     SkMatrix m;
   1284     m.setScale(sx, sy);
   1285     this->concat(m);
   1286 }
   1287 
   1288 void SkCanvas::rotate(SkScalar degrees) {
   1289     SkMatrix m;
   1290     m.setRotate(degrees);
   1291     this->concat(m);
   1292 }
   1293 
   1294 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
   1295     SkMatrix m;
   1296     m.setSkew(sx, sy);
   1297     this->concat(m);
   1298 }
   1299 
   1300 void 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 
   1312 void SkCanvas::setMatrix(const SkMatrix& matrix) {
   1313     fDeviceCMDirty = true;
   1314     fCachedLocalClipBoundsDirty = true;
   1315     *fMCRec->fMatrix = matrix;
   1316     this->didSetMatrix(matrix);
   1317 }
   1318 
   1319 void SkCanvas::resetMatrix() {
   1320     SkMatrix matrix;
   1321 
   1322     matrix.reset();
   1323     this->setMatrix(matrix);
   1324 }
   1325 
   1326 //////////////////////////////////////////////////////////////////////////////
   1327 
   1328 void 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 
   1333 void 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 
   1380 static 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 
   1420 void 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 
   1429 void 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 
   1455 void 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 
   1465 void 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 
   1537 void 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 
   1613 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
   1614     this->onClipRegion(rgn, op);
   1615 }
   1616 
   1617 void 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
   1631 void 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 
   1665 void SkCanvas::replayClips(ClipVisitor* visitor) const {
   1666     SkClipStack::B2TIter                iter(fClipStack);
   1667     const SkClipStack::Element*         element;
   1668 
   1669     while ((element = iter.next()) != NULL) {
   1670         element->replay(visitor);
   1671     }
   1672 }
   1673 
   1674 ///////////////////////////////////////////////////////////////////////////////
   1675 
   1676 bool SkCanvas::isClipEmpty() const {
   1677     return fMCRec->fRasterClip->isEmpty();
   1678 }
   1679 
   1680 bool SkCanvas::isClipRect() const {
   1681     return fMCRec->fRasterClip->isRect();
   1682 }
   1683 
   1684 bool SkCanvas::quickReject(const SkRect& rect) const {
   1685 
   1686     if (!rect.isFinite())
   1687         return true;
   1688 
   1689     if (fMCRec->fRasterClip->isEmpty()) {
   1690         return true;
   1691     }
   1692 
   1693     if (fMCRec->fMatrix->hasPerspective()) {
   1694         SkRect dst;
   1695         fMCRec->fMatrix->mapRect(&dst, rect);
   1696         SkIRect idst;
   1697         dst.roundOut(&idst);
   1698         return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
   1699     } else {
   1700         const SkRect& clipR = this->getLocalClipBounds();
   1701 
   1702         // for speed, do the most likely reject compares first
   1703         // TODO: should we use | instead, or compare all 4 at once?
   1704         if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
   1705             return true;
   1706         }
   1707         if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
   1708             return true;
   1709         }
   1710         return false;
   1711     }
   1712 }
   1713 
   1714 bool SkCanvas::quickReject(const SkPath& path) const {
   1715     return path.isEmpty() || this->quickReject(path.getBounds());
   1716 }
   1717 
   1718 bool SkCanvas::getClipBounds(SkRect* bounds) const {
   1719     SkIRect ibounds;
   1720     if (!this->getClipDeviceBounds(&ibounds)) {
   1721         return false;
   1722     }
   1723 
   1724     SkMatrix inverse;
   1725     // if we can't invert the CTM, we can't return local clip bounds
   1726     if (!fMCRec->fMatrix->invert(&inverse)) {
   1727         if (bounds) {
   1728             bounds->setEmpty();
   1729         }
   1730         return false;
   1731     }
   1732 
   1733     if (NULL != bounds) {
   1734         SkRect r;
   1735         // adjust it outwards in case we are antialiasing
   1736         const int inset = 1;
   1737 
   1738         r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
   1739                ibounds.fRight + inset, ibounds.fBottom + inset);
   1740         inverse.mapRect(bounds, r);
   1741     }
   1742     return true;
   1743 }
   1744 
   1745 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
   1746     const SkRasterClip& clip = *fMCRec->fRasterClip;
   1747     if (clip.isEmpty()) {
   1748         if (bounds) {
   1749             bounds->setEmpty();
   1750         }
   1751         return false;
   1752     }
   1753 
   1754     if (NULL != bounds) {
   1755         *bounds = clip.getBounds();
   1756     }
   1757     return true;
   1758 }
   1759 
   1760 const SkMatrix& SkCanvas::getTotalMatrix() const {
   1761     return *fMCRec->fMatrix;
   1762 }
   1763 
   1764 #ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
   1765 SkCanvas::ClipType SkCanvas::getClipType() const {
   1766     if (fMCRec->fRasterClip->isEmpty()) {
   1767         return kEmpty_ClipType;
   1768     }
   1769     if (fMCRec->fRasterClip->isRect()) {
   1770         return kRect_ClipType;
   1771     }
   1772     return kComplex_ClipType;
   1773 }
   1774 #endif
   1775 
   1776 #ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
   1777 const SkRegion& SkCanvas::getTotalClip() const {
   1778     return fMCRec->fRasterClip->forceGetBW();
   1779 }
   1780 #endif
   1781 
   1782 const SkRegion& SkCanvas::internal_private_getTotalClip() const {
   1783     return fMCRec->fRasterClip->forceGetBW();
   1784 }
   1785 
   1786 void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
   1787     path->reset();
   1788 
   1789     const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
   1790     if (rgn.isEmpty()) {
   1791         return;
   1792     }
   1793     (void)rgn.getBoundaryPath(path);
   1794 }
   1795 
   1796 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
   1797     SkBaseDevice* dev = this->getTopDevice();
   1798     return dev ? dev->accessRenderTarget() : NULL;
   1799 }
   1800 
   1801 SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
   1802     SkBaseDevice* device = this->getTopDevice();
   1803     return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
   1804 }
   1805 
   1806 GrContext* SkCanvas::getGrContext() {
   1807 #if SK_SUPPORT_GPU
   1808     SkBaseDevice* device = this->getTopDevice();
   1809     if (NULL != device) {
   1810         GrRenderTarget* renderTarget = device->accessRenderTarget();
   1811         if (NULL != renderTarget) {
   1812             return renderTarget->getContext();
   1813         }
   1814     }
   1815 #endif
   1816 
   1817     return NULL;
   1818 
   1819 }
   1820 
   1821 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
   1822                           const SkPaint& paint) {
   1823     if (outer.isEmpty()) {
   1824         return;
   1825     }
   1826     if (inner.isEmpty()) {
   1827         this->drawRRect(outer, paint);
   1828         return;
   1829     }
   1830 
   1831     // We don't have this method (yet), but technically this is what we should
   1832     // be able to assert...
   1833     // SkASSERT(outer.contains(inner));
   1834     //
   1835     // For now at least check for containment of bounds
   1836     SkASSERT(outer.getBounds().contains(inner.getBounds()));
   1837 
   1838     this->onDrawDRRect(outer, inner, paint);
   1839 }
   1840 
   1841 //////////////////////////////////////////////////////////////////////////////
   1842 //  These are the virtual drawing methods
   1843 //////////////////////////////////////////////////////////////////////////////
   1844 
   1845 void SkCanvas::clear(SkColor color) {
   1846     SkDrawIter  iter(this);
   1847     this->predrawNotify();
   1848     while (iter.next()) {
   1849         iter.fDevice->clear(color);
   1850     }
   1851 }
   1852 
   1853 void SkCanvas::onDiscard() {
   1854     if (NULL != fSurfaceBase) {
   1855         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
   1856     }
   1857 }
   1858 
   1859 void SkCanvas::drawPaint(const SkPaint& paint) {
   1860     this->internalDrawPaint(paint);
   1861 }
   1862 
   1863 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
   1864     LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
   1865 
   1866     while (iter.next()) {
   1867         iter.fDevice->drawPaint(iter, looper.paint());
   1868     }
   1869 
   1870     LOOPER_END
   1871 }
   1872 
   1873 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
   1874                           const SkPaint& paint) {
   1875     if ((long)count <= 0) {
   1876         return;
   1877     }
   1878 
   1879     SkRect r, storage;
   1880     const SkRect* bounds = NULL;
   1881     if (paint.canComputeFastBounds()) {
   1882         // special-case 2 points (common for drawing a single line)
   1883         if (2 == count) {
   1884             r.set(pts[0], pts[1]);
   1885         } else {
   1886             r.set(pts, SkToInt(count));
   1887         }
   1888         bounds = &paint.computeFastStrokeBounds(r, &storage);
   1889         if (this->quickReject(*bounds)) {
   1890             return;
   1891         }
   1892     }
   1893 
   1894     SkASSERT(pts != NULL);
   1895 
   1896     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
   1897 
   1898     while (iter.next()) {
   1899         iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
   1900     }
   1901 
   1902     LOOPER_END
   1903 }
   1904 
   1905 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
   1906     SkRect storage;
   1907     const SkRect* bounds = NULL;
   1908     if (paint.canComputeFastBounds()) {
   1909         bounds = &paint.computeFastBounds(r, &storage);
   1910         if (this->quickReject(*bounds)) {
   1911             return;
   1912         }
   1913     }
   1914 
   1915     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
   1916 
   1917     while (iter.next()) {
   1918         iter.fDevice->drawRect(iter, r, looper.paint());
   1919     }
   1920 
   1921     LOOPER_END
   1922 }
   1923 
   1924 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
   1925     SkRect storage;
   1926     const SkRect* bounds = NULL;
   1927     if (paint.canComputeFastBounds()) {
   1928         bounds = &paint.computeFastBounds(oval, &storage);
   1929         if (this->quickReject(*bounds)) {
   1930             return;
   1931         }
   1932     }
   1933 
   1934     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
   1935 
   1936     while (iter.next()) {
   1937         iter.fDevice->drawOval(iter, oval, looper.paint());
   1938     }
   1939 
   1940     LOOPER_END
   1941 }
   1942 
   1943 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   1944     SkRect storage;
   1945     const SkRect* bounds = NULL;
   1946     if (paint.canComputeFastBounds()) {
   1947         bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
   1948         if (this->quickReject(*bounds)) {
   1949             return;
   1950         }
   1951     }
   1952 
   1953     if (rrect.isRect()) {
   1954         // call the non-virtual version
   1955         this->SkCanvas::drawRect(rrect.getBounds(), paint);
   1956         return;
   1957     } else if (rrect.isOval()) {
   1958         // call the non-virtual version
   1959         this->SkCanvas::drawOval(rrect.getBounds(), paint);
   1960         return;
   1961     }
   1962 
   1963     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
   1964 
   1965     while (iter.next()) {
   1966         iter.fDevice->drawRRect(iter, rrect, looper.paint());
   1967     }
   1968 
   1969     LOOPER_END
   1970 }
   1971 
   1972 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
   1973                             const SkPaint& paint) {
   1974     SkRect storage;
   1975     const SkRect* bounds = NULL;
   1976     if (paint.canComputeFastBounds()) {
   1977         bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
   1978         if (this->quickReject(*bounds)) {
   1979             return;
   1980         }
   1981     }
   1982 
   1983     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
   1984 
   1985     while (iter.next()) {
   1986         iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
   1987     }
   1988 
   1989     LOOPER_END
   1990 }
   1991 
   1992 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   1993     if (!path.isFinite()) {
   1994         return;
   1995     }
   1996 
   1997     SkRect storage;
   1998     const SkRect* bounds = NULL;
   1999     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
   2000         const SkRect& pathBounds = path.getBounds();
   2001         bounds = &paint.computeFastBounds(pathBounds, &storage);
   2002         if (this->quickReject(*bounds)) {
   2003             return;
   2004         }
   2005     }
   2006 
   2007     const SkRect& r = path.getBounds();
   2008     if (r.width() <= 0 && r.height() <= 0) {
   2009         if (path.isInverseFillType()) {
   2010             this->internalDrawPaint(paint);
   2011         }
   2012         return;
   2013     }
   2014 
   2015     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
   2016 
   2017     while (iter.next()) {
   2018         iter.fDevice->drawPath(iter, path, looper.paint());
   2019     }
   2020 
   2021     LOOPER_END
   2022 }
   2023 
   2024 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
   2025                           const SkPaint* paint) {
   2026     SkDEBUGCODE(bitmap.validate();)
   2027 
   2028     if (NULL == paint || paint->canComputeFastBounds()) {
   2029         SkRect bounds = {
   2030             x, y,
   2031             x + SkIntToScalar(bitmap.width()),
   2032             y + SkIntToScalar(bitmap.height())
   2033         };
   2034         if (paint) {
   2035             (void)paint->computeFastBounds(bounds, &bounds);
   2036         }
   2037         if (this->quickReject(bounds)) {
   2038             return;
   2039         }
   2040     }
   2041 
   2042     SkMatrix matrix;
   2043     matrix.setTranslate(x, y);
   2044     this->internalDrawBitmap(bitmap, matrix, paint);
   2045 }
   2046 
   2047 // this one is non-virtual, so it can be called safely by other canvas apis
   2048 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
   2049                                       const SkRect& dst, const SkPaint* paint,
   2050                                       DrawBitmapRectFlags flags) {
   2051     if (bitmap.drawsNothing() || dst.isEmpty()) {
   2052         return;
   2053     }
   2054 
   2055     CHECK_LOCKCOUNT_BALANCE(bitmap);
   2056 
   2057     SkRect storage;
   2058     const SkRect* bounds = &dst;
   2059     if (NULL == paint || paint->canComputeFastBounds()) {
   2060         if (paint) {
   2061             bounds = &paint->computeFastBounds(dst, &storage);
   2062         }
   2063         if (this->quickReject(*bounds)) {
   2064             return;
   2065         }
   2066     }
   2067 
   2068     SkLazyPaint lazy;
   2069     if (NULL == paint) {
   2070         paint = lazy.init();
   2071     }
   2072 
   2073     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
   2074 
   2075     while (iter.next()) {
   2076         iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
   2077     }
   2078 
   2079     LOOPER_END
   2080 }
   2081 
   2082 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
   2083                                     const SkRect& dst, const SkPaint* paint,
   2084                                     DrawBitmapRectFlags flags) {
   2085     SkDEBUGCODE(bitmap.validate();)
   2086     this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
   2087 }
   2088 
   2089 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
   2090                                 const SkPaint* paint) {
   2091     SkDEBUGCODE(bitmap.validate();)
   2092     this->internalDrawBitmap(bitmap, matrix, paint);
   2093 }
   2094 
   2095 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
   2096                                       const SkIRect& center, const SkRect& dst,
   2097                                       const SkPaint* paint) {
   2098     if (bitmap.drawsNothing()) {
   2099         return;
   2100     }
   2101     if (NULL == paint || paint->canComputeFastBounds()) {
   2102         SkRect storage;
   2103         const SkRect* bounds = &dst;
   2104         if (paint) {
   2105             bounds = &paint->computeFastBounds(dst, &storage);
   2106         }
   2107         if (this->quickReject(*bounds)) {
   2108             return;
   2109         }
   2110     }
   2111 
   2112     const int32_t w = bitmap.width();
   2113     const int32_t h = bitmap.height();
   2114 
   2115     SkIRect c = center;
   2116     // pin center to the bounds of the bitmap
   2117     c.fLeft = SkMax32(0, center.fLeft);
   2118     c.fTop = SkMax32(0, center.fTop);
   2119     c.fRight = SkPin32(center.fRight, c.fLeft, w);
   2120     c.fBottom = SkPin32(center.fBottom, c.fTop, h);
   2121 
   2122     const SkScalar srcX[4] = {
   2123         0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
   2124     };
   2125     const SkScalar srcY[4] = {
   2126         0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
   2127     };
   2128     SkScalar dstX[4] = {
   2129         dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
   2130         dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
   2131     };
   2132     SkScalar dstY[4] = {
   2133         dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
   2134         dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
   2135     };
   2136 
   2137     if (dstX[1] > dstX[2]) {
   2138         dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
   2139         dstX[2] = dstX[1];
   2140     }
   2141 
   2142     if (dstY[1] > dstY[2]) {
   2143         dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
   2144         dstY[2] = dstY[1];
   2145     }
   2146 
   2147     for (int y = 0; y < 3; y++) {
   2148         SkRect s, d;
   2149 
   2150         s.fTop = srcY[y];
   2151         s.fBottom = srcY[y+1];
   2152         d.fTop = dstY[y];
   2153         d.fBottom = dstY[y+1];
   2154         for (int x = 0; x < 3; x++) {
   2155             s.fLeft = srcX[x];
   2156             s.fRight = srcX[x+1];
   2157             d.fLeft = dstX[x];
   2158             d.fRight = dstX[x+1];
   2159             this->internalDrawBitmapRect(bitmap, &s, d, paint,
   2160                                          kNone_DrawBitmapRectFlag);
   2161         }
   2162     }
   2163 }
   2164 
   2165 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
   2166                               const SkRect& dst, const SkPaint* paint) {
   2167     SkDEBUGCODE(bitmap.validate();)
   2168 
   2169     // Need a device entry-point, so gpu can use a mesh
   2170     this->internalDrawBitmapNine(bitmap, center, dst, paint);
   2171 }
   2172 
   2173 class SkDeviceFilteredPaint {
   2174 public:
   2175     SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
   2176         SkBaseDevice::TextFlags flags;
   2177         if (device->filterTextFlags(paint, &flags)) {
   2178             SkPaint* newPaint = fLazy.set(paint);
   2179             newPaint->setFlags(flags.fFlags);
   2180             newPaint->setHinting(flags.fHinting);
   2181             fPaint = newPaint;
   2182         } else {
   2183             fPaint = &paint;
   2184         }
   2185     }
   2186 
   2187     const SkPaint& paint() const { return *fPaint; }
   2188 
   2189 private:
   2190     const SkPaint*  fPaint;
   2191     SkLazyPaint     fLazy;
   2192 };
   2193 
   2194 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
   2195                         const SkRect& r, SkScalar textSize) {
   2196     if (paint.getStyle() == SkPaint::kFill_Style) {
   2197         draw.fDevice->drawRect(draw, r, paint);
   2198     } else {
   2199         SkPaint p(paint);
   2200         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
   2201         draw.fDevice->drawRect(draw, r, p);
   2202     }
   2203 }
   2204 
   2205 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
   2206                                    const char text[], size_t byteLength,
   2207                                    SkScalar x, SkScalar y) {
   2208     SkASSERT(byteLength == 0 || text != NULL);
   2209 
   2210     // nothing to draw
   2211     if (text == NULL || byteLength == 0 ||
   2212         draw.fClip->isEmpty() ||
   2213         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
   2214         return;
   2215     }
   2216 
   2217     SkScalar    width = 0;
   2218     SkPoint     start;
   2219 
   2220     start.set(0, 0);    // to avoid warning
   2221     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
   2222                             SkPaint::kStrikeThruText_Flag)) {
   2223         width = paint.measureText(text, byteLength);
   2224 
   2225         SkScalar offsetX = 0;
   2226         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   2227             offsetX = SkScalarHalf(width);
   2228         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
   2229             offsetX = width;
   2230         }
   2231         start.set(x - offsetX, y);
   2232     }
   2233 
   2234     if (0 == width) {
   2235         return;
   2236     }
   2237 
   2238     uint32_t flags = paint.getFlags();
   2239 
   2240     if (flags & (SkPaint::kUnderlineText_Flag |
   2241                  SkPaint::kStrikeThruText_Flag)) {
   2242         SkScalar textSize = paint.getTextSize();
   2243         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
   2244         SkRect   r;
   2245 
   2246         r.fLeft = start.fX;
   2247         r.fRight = start.fX + width;
   2248 
   2249         if (flags & SkPaint::kUnderlineText_Flag) {
   2250             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
   2251                                              start.fY);
   2252             r.fTop = offset;
   2253             r.fBottom = offset + height;
   2254             DrawRect(draw, paint, r, textSize);
   2255         }
   2256         if (flags & SkPaint::kStrikeThruText_Flag) {
   2257             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
   2258                                              start.fY);
   2259             r.fTop = offset;
   2260             r.fBottom = offset + height;
   2261             DrawRect(draw, paint, r, textSize);
   2262         }
   2263     }
   2264 }
   2265 
   2266 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
   2267                           const SkPaint& paint) {
   2268     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2269 
   2270     while (iter.next()) {
   2271         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2272         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
   2273         DrawTextDecorations(iter, dfp.paint(),
   2274                             static_cast<const char*>(text), byteLength, x, y);
   2275     }
   2276 
   2277     LOOPER_END
   2278 }
   2279 
   2280 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
   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->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
   2287                                   dfp.paint());
   2288     }
   2289 
   2290     LOOPER_END
   2291 }
   2292 
   2293 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
   2294                               SkScalar constY, const SkPaint& paint) {
   2295     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2296 
   2297     while (iter.next()) {
   2298         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2299         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
   2300                                   dfp.paint());
   2301     }
   2302 
   2303     LOOPER_END
   2304 }
   2305 
   2306 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
   2307                                 const SkMatrix* matrix, const SkPaint& paint) {
   2308     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2309 
   2310     while (iter.next()) {
   2311         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
   2312                                      matrix, looper.paint());
   2313     }
   2314 
   2315     LOOPER_END
   2316 }
   2317 
   2318 // These will become non-virtual, so they always call the (virtual) onDraw... method
   2319 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
   2320                         const SkPaint& paint) {
   2321     this->onDrawText(text, byteLength, x, y, paint);
   2322 }
   2323 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
   2324                            const SkPaint& paint) {
   2325     this->onDrawPosText(text, byteLength, pos, paint);
   2326 }
   2327 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
   2328                             SkScalar constY, const SkPaint& paint) {
   2329     this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
   2330 }
   2331 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
   2332                               const SkMatrix* matrix, const SkPaint& paint) {
   2333     this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
   2334 }
   2335 
   2336 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
   2337                             const SkPoint verts[], const SkPoint texs[],
   2338                             const SkColor colors[], SkXfermode* xmode,
   2339                             const uint16_t indices[], int indexCount,
   2340                             const SkPaint& paint) {
   2341     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
   2342 
   2343     while (iter.next()) {
   2344         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
   2345                                    colors, xmode, indices, indexCount,
   2346                                    looper.paint());
   2347     }
   2348 
   2349     LOOPER_END
   2350 }
   2351 
   2352 //////////////////////////////////////////////////////////////////////////////
   2353 // These methods are NOT virtual, and therefore must call back into virtual
   2354 // methods, rather than actually drawing themselves.
   2355 //////////////////////////////////////////////////////////////////////////////
   2356 
   2357 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
   2358                         SkXfermode::Mode mode) {
   2359     SkPaint paint;
   2360 
   2361     paint.setARGB(a, r, g, b);
   2362     if (SkXfermode::kSrcOver_Mode != mode) {
   2363         paint.setXfermodeMode(mode);
   2364     }
   2365     this->drawPaint(paint);
   2366 }
   2367 
   2368 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
   2369     SkPaint paint;
   2370 
   2371     paint.setColor(c);
   2372     if (SkXfermode::kSrcOver_Mode != mode) {
   2373         paint.setXfermodeMode(mode);
   2374     }
   2375     this->drawPaint(paint);
   2376 }
   2377 
   2378 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
   2379     SkPoint pt;
   2380 
   2381     pt.set(x, y);
   2382     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   2383 }
   2384 
   2385 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
   2386     SkPoint pt;
   2387     SkPaint paint;
   2388 
   2389     pt.set(x, y);
   2390     paint.setColor(color);
   2391     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   2392 }
   2393 
   2394 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
   2395                         const SkPaint& paint) {
   2396     SkPoint pts[2];
   2397 
   2398     pts[0].set(x0, y0);
   2399     pts[1].set(x1, y1);
   2400     this->drawPoints(kLines_PointMode, 2, pts, paint);
   2401 }
   2402 
   2403 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
   2404                               SkScalar right, SkScalar bottom,
   2405                               const SkPaint& paint) {
   2406     SkRect  r;
   2407 
   2408     r.set(left, top, right, bottom);
   2409     this->drawRect(r, paint);
   2410 }
   2411 
   2412 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
   2413                           const SkPaint& paint) {
   2414     if (radius < 0) {
   2415         radius = 0;
   2416     }
   2417 
   2418     SkRect  r;
   2419     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
   2420     this->drawOval(r, paint);
   2421 }
   2422 
   2423 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
   2424                              const SkPaint& paint) {
   2425     if (rx > 0 && ry > 0) {
   2426         if (paint.canComputeFastBounds()) {
   2427             SkRect storage;
   2428             if (this->quickReject(paint.computeFastBounds(r, &storage))) {
   2429                 return;
   2430             }
   2431         }
   2432         SkRRect rrect;
   2433         rrect.setRectXY(r, rx, ry);
   2434         this->drawRRect(rrect, paint);
   2435     } else {
   2436         this->drawRect(r, paint);
   2437     }
   2438 }
   2439 
   2440 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
   2441                        SkScalar sweepAngle, bool useCenter,
   2442                        const SkPaint& paint) {
   2443     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
   2444         this->drawOval(oval, paint);
   2445     } else {
   2446         SkPath  path;
   2447         if (useCenter) {
   2448             path.moveTo(oval.centerX(), oval.centerY());
   2449         }
   2450         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
   2451         if (useCenter) {
   2452             path.close();
   2453         }
   2454         this->drawPath(path, paint);
   2455     }
   2456 }
   2457 
   2458 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
   2459                                 const SkPath& path, SkScalar hOffset,
   2460                                 SkScalar vOffset, const SkPaint& paint) {
   2461     SkMatrix    matrix;
   2462 
   2463     matrix.setTranslate(hOffset, vOffset);
   2464     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
   2465 }
   2466 
   2467 ///////////////////////////////////////////////////////////////////////////////
   2468 void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
   2469     SkBaseDevice* device = this->getDevice();
   2470     if (NULL != device) {
   2471         device->EXPERIMENTAL_optimize(picture);
   2472     }
   2473 }
   2474 
   2475 void SkCanvas::EXPERIMENTAL_purge(const SkPicture* picture) {
   2476     SkBaseDevice* device = this->getTopDevice();
   2477     if (NULL != device) {
   2478         device->EXPERIMENTAL_purge(picture);
   2479     }
   2480 }
   2481 
   2482 void SkCanvas::drawPicture(const SkPicture* picture) {
   2483     if (NULL != picture) {
   2484         this->onDrawPicture(picture);
   2485     }
   2486 }
   2487 
   2488 void SkCanvas::onDrawPicture(const SkPicture* picture) {
   2489     SkASSERT(NULL != picture);
   2490 
   2491     SkBaseDevice* device = this->getTopDevice();
   2492     if (NULL != device) {
   2493         // Canvas has to first give the device the opportunity to render
   2494         // the picture itself.
   2495         if (device->EXPERIMENTAL_drawPicture(this, picture)) {
   2496             return; // the device has rendered the entire picture
   2497         }
   2498     }
   2499 
   2500     picture->draw(this);
   2501 }
   2502 
   2503 ///////////////////////////////////////////////////////////////////////////////
   2504 ///////////////////////////////////////////////////////////////////////////////
   2505 
   2506 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
   2507     SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
   2508 
   2509     SkASSERT(canvas);
   2510 
   2511     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
   2512     fDone = !fImpl->next();
   2513 }
   2514 
   2515 SkCanvas::LayerIter::~LayerIter() {
   2516     fImpl->~SkDrawIter();
   2517 }
   2518 
   2519 void SkCanvas::LayerIter::next() {
   2520     fDone = !fImpl->next();
   2521 }
   2522 
   2523 SkBaseDevice* SkCanvas::LayerIter::device() const {
   2524     return fImpl->getDevice();
   2525 }
   2526 
   2527 const SkMatrix& SkCanvas::LayerIter::matrix() const {
   2528     return fImpl->getMatrix();
   2529 }
   2530 
   2531 const SkPaint& SkCanvas::LayerIter::paint() const {
   2532     const SkPaint* paint = fImpl->getPaint();
   2533     if (NULL == paint) {
   2534         paint = &fDefaultPaint;
   2535     }
   2536     return *paint;
   2537 }
   2538 
   2539 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
   2540 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
   2541 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
   2542 
   2543 ///////////////////////////////////////////////////////////////////////////////
   2544 
   2545 SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
   2546 
   2547 ///////////////////////////////////////////////////////////////////////////////
   2548 
   2549 static bool supported_for_raster_canvas(const SkImageInfo& info) {
   2550     switch (info.alphaType()) {
   2551         case kPremul_SkAlphaType:
   2552         case kOpaque_SkAlphaType:
   2553             break;
   2554         default:
   2555             return false;
   2556     }
   2557 
   2558     switch (info.colorType()) {
   2559         case kAlpha_8_SkColorType:
   2560         case kRGB_565_SkColorType:
   2561         case kN32_SkColorType:
   2562             break;
   2563         default:
   2564             return false;
   2565     }
   2566 
   2567     return true;
   2568 }
   2569 
   2570 SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
   2571     if (!supported_for_raster_canvas(info)) {
   2572         return NULL;
   2573     }
   2574 
   2575     SkBitmap bitmap;
   2576     if (!bitmap.allocPixels(info)) {
   2577         return NULL;
   2578     }
   2579 
   2580     // should this functionality be moved into allocPixels()?
   2581     if (!bitmap.info().isOpaque()) {
   2582         bitmap.eraseColor(0);
   2583     }
   2584     return SkNEW_ARGS(SkCanvas, (bitmap));
   2585 }
   2586 
   2587 SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
   2588     if (!supported_for_raster_canvas(info)) {
   2589         return NULL;
   2590     }
   2591 
   2592     SkBitmap bitmap;
   2593     if (!bitmap.installPixels(info, pixels, rowBytes)) {
   2594         return NULL;
   2595     }
   2596     return SkNEW_ARGS(SkCanvas, (bitmap));
   2597 }
   2598