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