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