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