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