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