Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2008 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkCanvas.h"
      9 #include "SkCanvasPriv.h"
     10 #include "SkBitmapDevice.h"
     11 #include "SkDeviceImageFilterProxy.h"
     12 #include "SkDraw.h"
     13 #include "SkDrawFilter.h"
     14 #include "SkDrawLooper.h"
     15 #include "SkImage.h"
     16 #include "SkMetaData.h"
     17 #include "SkPathOps.h"
     18 #include "SkPatchUtils.h"
     19 #include "SkPicture.h"
     20 #include "SkRasterClip.h"
     21 #include "SkRRect.h"
     22 #include "SkSmallAllocator.h"
     23 #include "SkSurface_Base.h"
     24 #include "SkTemplates.h"
     25 #include "SkTextBlob.h"
     26 #include "SkTextFormatParams.h"
     27 #include "SkTLazy.h"
     28 #include "SkUtils.h"
     29 
     30 #if SK_SUPPORT_GPU
     31 #include "GrRenderTarget.h"
     32 #endif
     33 
     34 // experimental for faster tiled drawing...
     35 //#define SK_ENABLE_CLIP_QUICKREJECT
     36 
     37 //#define SK_TRACE_SAVERESTORE
     38 
     39 #ifdef SK_TRACE_SAVERESTORE
     40     static int gLayerCounter;
     41     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
     42     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
     43 
     44     static int gRecCounter;
     45     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
     46     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
     47 
     48     static int gCanvasCounter;
     49     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
     50     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
     51 #else
     52     #define inc_layer()
     53     #define dec_layer()
     54     #define inc_rec()
     55     #define dec_rec()
     56     #define inc_canvas()
     57     #define dec_canvas()
     58 #endif
     59 
     60 typedef SkTLazy<SkPaint> SkLazyPaint;
     61 
     62 void SkCanvas::predrawNotify() {
     63     if (fSurfaceBase) {
     64         fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
     65     }
     66 }
     67 
     68 ///////////////////////////////////////////////////////////////////////////////
     69 
     70 static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
     71     const uint32_t propFlags = props.flags();
     72     if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
     73         flags &= ~SkPaint::kDither_Flag;
     74     }
     75     if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
     76         flags &= ~SkPaint::kAntiAlias_Flag;
     77     }
     78     return flags;
     79 }
     80 
     81 ///////////////////////////////////////////////////////////////////////////////
     82 
     83 /*  This is the record we keep for each SkBaseDevice that the user installs.
     84     The clip/matrix/proc are fields that reflect the top of the save/restore
     85     stack. Whenever the canvas changes, it marks a dirty flag, and then before
     86     these are used (assuming we're not on a layer) we rebuild these cache
     87     values: they reflect the top of the save stack, but translated and clipped
     88     by the device's XY offset and bitmap-bounds.
     89 */
     90 struct DeviceCM {
     91     DeviceCM*           fNext;
     92     SkBaseDevice*       fDevice;
     93     SkRasterClip        fClip;
     94     const SkMatrix*     fMatrix;
     95     SkPaint*            fPaint; // may be null (in the future)
     96 
     97     DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas,
     98              bool conservativeRasterClip)
     99         : fNext(NULL)
    100         , fClip(conservativeRasterClip)
    101     {
    102         if (NULL != device) {
    103             device->ref();
    104             device->onAttachToCanvas(canvas);
    105         }
    106         fDevice = device;
    107         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
    108     }
    109 
    110     ~DeviceCM() {
    111         if (fDevice) {
    112             fDevice->onDetachFromCanvas();
    113             fDevice->unref();
    114         }
    115         SkDELETE(fPaint);
    116     }
    117 
    118     void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
    119                   const SkClipStack& clipStack, SkRasterClip* updateClip) {
    120         int x = fDevice->getOrigin().x();
    121         int y = fDevice->getOrigin().y();
    122         int width = fDevice->width();
    123         int height = fDevice->height();
    124 
    125         if ((x | y) == 0) {
    126             fMatrix = &totalMatrix;
    127             fClip = totalClip;
    128         } else {
    129             fMatrixStorage = totalMatrix;
    130             fMatrixStorage.postTranslate(SkIntToScalar(-x),
    131                                          SkIntToScalar(-y));
    132             fMatrix = &fMatrixStorage;
    133 
    134             totalClip.translate(-x, -y, &fClip);
    135         }
    136 
    137         fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
    138 
    139         // intersect clip, but don't translate it (yet)
    140 
    141         if (updateClip) {
    142             updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
    143                            SkRegion::kDifference_Op);
    144         }
    145 
    146         fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
    147 
    148 #ifdef SK_DEBUG
    149         if (!fClip.isEmpty()) {
    150             SkIRect deviceR;
    151             deviceR.set(0, 0, width, height);
    152             SkASSERT(deviceR.contains(fClip.getBounds()));
    153         }
    154 #endif
    155     }
    156 
    157 private:
    158     SkMatrix    fMatrixStorage;
    159 };
    160 
    161 /*  This is the record we keep for each save/restore level in the stack.
    162     Since a level optionally copies the matrix and/or stack, we have pointers
    163     for these fields. If the value is copied for this level, the copy is
    164     stored in the ...Storage field, and the pointer points to that. If the
    165     value is not copied for this level, we ignore ...Storage, and just point
    166     at the corresponding value in the previous level in the stack.
    167 */
    168 class SkCanvas::MCRec {
    169 public:
    170     SkRasterClip    fRasterClip;
    171     SkMatrix        fMatrix;
    172     SkDrawFilter*   fFilter;    // the current filter (or null)
    173     DeviceCM*       fLayer;
    174     /*  If there are any layers in the stack, this points to the top-most
    175         one that is at or below this level in the stack (so we know what
    176         bitmap/device to draw into from this level. This value is NOT
    177         reference counted, since the real owner is either our fLayer field,
    178         or a previous one in a lower level.)
    179     */
    180     DeviceCM*   fTopLayer;
    181 
    182     MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
    183         fMatrix.reset();
    184         fFilter     = NULL;
    185         fLayer      = NULL;
    186         fTopLayer   = NULL;
    187 
    188         // don't bother initializing fNext
    189         inc_rec();
    190     }
    191     MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) {
    192         fMatrix = prev.fMatrix;
    193         fFilter = SkSafeRef(prev.fFilter);
    194         fLayer = NULL;
    195         fTopLayer = prev.fTopLayer;
    196 
    197         // don't bother initializing fNext
    198         inc_rec();
    199     }
    200     ~MCRec() {
    201         SkSafeUnref(fFilter);
    202         SkDELETE(fLayer);
    203         dec_rec();
    204     }
    205 };
    206 
    207 class SkDrawIter : public SkDraw {
    208 public:
    209     SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
    210         canvas = canvas->canvasForDrawIter();
    211         fCanvas = canvas;
    212         canvas->updateDeviceCMCache();
    213 
    214         fClipStack = &canvas->fClipStack;
    215         fCurrLayer = canvas->fMCRec->fTopLayer;
    216         fSkipEmptyClips = skipEmptyClips;
    217     }
    218 
    219     bool next() {
    220         // skip over recs with empty clips
    221         if (fSkipEmptyClips) {
    222             while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
    223                 fCurrLayer = fCurrLayer->fNext;
    224             }
    225         }
    226 
    227         const DeviceCM* rec = fCurrLayer;
    228         if (rec && rec->fDevice) {
    229 
    230             fMatrix = rec->fMatrix;
    231             fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
    232             fRC     = &rec->fClip;
    233             fDevice = rec->fDevice;
    234             fBitmap = &fDevice->accessBitmap(true);
    235             fPaint  = rec->fPaint;
    236             SkDEBUGCODE(this->validate();)
    237 
    238             fCurrLayer = rec->fNext;
    239             // fCurrLayer may be NULL now
    240 
    241             return true;
    242         }
    243         return false;
    244     }
    245 
    246     SkBaseDevice* getDevice() const { return fDevice; }
    247     int getX() const { return fDevice->getOrigin().x(); }
    248     int getY() const { return fDevice->getOrigin().y(); }
    249     const SkMatrix& getMatrix() const { return *fMatrix; }
    250     const SkRegion& getClip() const { return *fClip; }
    251     const SkPaint* getPaint() const { return fPaint; }
    252 
    253 private:
    254     SkCanvas*       fCanvas;
    255     const DeviceCM* fCurrLayer;
    256     const SkPaint*  fPaint;     // May be null.
    257     SkBool8         fSkipEmptyClips;
    258 
    259     typedef SkDraw INHERITED;
    260 };
    261 
    262 /////////////////////////////////////////////////////////////////////////////
    263 
    264 class AutoDrawLooper {
    265 public:
    266     AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
    267                    bool skipLayerForImageFilter = false,
    268                    const SkRect* bounds = NULL) : fOrigPaint(paint) {
    269         fCanvas = canvas;
    270         fFilter = canvas->getDrawFilter();
    271         fPaint = &fOrigPaint;
    272         fSaveCount = canvas->getSaveCount();
    273         fDoClearImageFilter = false;
    274         fDone = false;
    275 
    276         if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
    277             SkPaint tmp;
    278             tmp.setImageFilter(fOrigPaint.getImageFilter());
    279             (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
    280                                             true, SkCanvas::kFullLayer_SaveLayerStrategy);
    281             // we'll clear the imageFilter for the actual draws in next(), so
    282             // it will only be applied during the restore().
    283             fDoClearImageFilter = true;
    284         }
    285 
    286         if (SkDrawLooper* looper = paint.getLooper()) {
    287             void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
    288                     looper->contextSize());
    289             fLooperContext = looper->createContext(canvas, buffer);
    290             fIsSimple = false;
    291         } else {
    292             fLooperContext = NULL;
    293             // can we be marked as simple?
    294             fIsSimple = !fFilter && !fDoClearImageFilter;
    295         }
    296 
    297         uint32_t oldFlags = paint.getFlags();
    298         fNewPaintFlags = filter_paint_flags(props, oldFlags);
    299         if (fIsSimple && (fNewPaintFlags != oldFlags)) {
    300             SkPaint* paint = fLazyPaint.set(fOrigPaint);
    301             paint->setFlags(fNewPaintFlags);
    302             fPaint = paint;
    303             // if we're not simple, doNext() will take care of calling setFlags()
    304         }
    305     }
    306 
    307     ~AutoDrawLooper() {
    308         if (fDoClearImageFilter) {
    309             fCanvas->internalRestore();
    310         }
    311         SkASSERT(fCanvas->getSaveCount() == fSaveCount);
    312     }
    313 
    314     const SkPaint& paint() const {
    315         SkASSERT(fPaint);
    316         return *fPaint;
    317     }
    318 
    319     bool next(SkDrawFilter::Type drawType) {
    320         if (fDone) {
    321             return false;
    322         } else if (fIsSimple) {
    323             fDone = true;
    324             return !fPaint->nothingToDraw();
    325         } else {
    326             return this->doNext(drawType);
    327         }
    328     }
    329 
    330 private:
    331     SkLazyPaint     fLazyPaint;
    332     SkCanvas*       fCanvas;
    333     const SkPaint&  fOrigPaint;
    334     SkDrawFilter*   fFilter;
    335     const SkPaint*  fPaint;
    336     int             fSaveCount;
    337     uint32_t        fNewPaintFlags;
    338     bool            fDoClearImageFilter;
    339     bool            fDone;
    340     bool            fIsSimple;
    341     SkDrawLooper::Context* fLooperContext;
    342     SkSmallAllocator<1, 32> fLooperContextAllocator;
    343 
    344     bool doNext(SkDrawFilter::Type drawType);
    345 };
    346 
    347 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
    348     fPaint = NULL;
    349     SkASSERT(!fIsSimple);
    350     SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
    351 
    352     SkPaint* paint = fLazyPaint.set(fOrigPaint);
    353     paint->setFlags(fNewPaintFlags);
    354 
    355     if (fDoClearImageFilter) {
    356         paint->setImageFilter(NULL);
    357     }
    358 
    359     if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
    360         fDone = true;
    361         return false;
    362     }
    363     if (fFilter) {
    364         if (!fFilter->filter(paint, drawType)) {
    365             fDone = true;
    366             return false;
    367         }
    368         if (NULL == fLooperContext) {
    369             // no looper means we only draw once
    370             fDone = true;
    371         }
    372     }
    373     fPaint = paint;
    374 
    375     // if we only came in here for the imagefilter, mark us as done
    376     if (!fLooperContext && !fFilter) {
    377         fDone = true;
    378     }
    379 
    380     // call this after any possible paint modifiers
    381     if (fPaint->nothingToDraw()) {
    382         fPaint = NULL;
    383         return false;
    384     }
    385     return true;
    386 }
    387 
    388 ////////// macros to place around the internal draw calls //////////////////
    389 
    390 #define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
    391     this->predrawNotify();                                          \
    392     AutoDrawLooper  looper(this, fProps, paint, true);              \
    393     while (looper.next(type)) {                                     \
    394         SkDrawIter          iter(this);
    395 
    396 #define LOOPER_BEGIN(paint, type, bounds)                           \
    397     this->predrawNotify();                                          \
    398     AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
    399     while (looper.next(type)) {                                     \
    400         SkDrawIter          iter(this);
    401 
    402 #define LOOPER_END    }
    403 
    404 ////////////////////////////////////////////////////////////////////////////
    405 
    406 void SkCanvas::setupDevice(SkBaseDevice* device) {
    407     device->setPixelGeometry(fProps.pixelGeometry());
    408 }
    409 
    410 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
    411     fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
    412     fCachedLocalClipBounds.setEmpty();
    413     fCachedLocalClipBoundsDirty = true;
    414     fAllowSoftClip = true;
    415     fAllowSimplifyClip = false;
    416     fDeviceCMDirty = true;
    417     fSaveLayerCount = 0;
    418     fCullCount = 0;
    419     fMetaData = NULL;
    420 
    421     fMCRec = (MCRec*)fMCStack.push_back();
    422     new (fMCRec) MCRec(fConservativeRasterClip);
    423 
    424     fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
    425     fMCRec->fTopLayer = fMCRec->fLayer;
    426 
    427     fSurfaceBase = NULL;
    428 
    429     if (device) {
    430         this->setupDevice(device);
    431         if (device->forceConservativeRasterClip()) {
    432             fConservativeRasterClip = true;
    433         }
    434         device->onAttachToCanvas(this);
    435         fMCRec->fLayer->fDevice = SkRef(device);
    436         fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->height()));
    437     }
    438     return device;
    439 }
    440 
    441 SkCanvas::SkCanvas()
    442     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    443     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    444 {
    445     inc_canvas();
    446 
    447     this->init(NULL, kDefault_InitFlags);
    448 }
    449 
    450 static SkBitmap make_nopixels(int width, int height) {
    451     SkBitmap bitmap;
    452     bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
    453     return bitmap;
    454 }
    455 
    456 class SkNoPixelsBitmapDevice : public SkBitmapDevice {
    457 public:
    458     SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(width, height)) {}
    459 
    460 private:
    461 
    462     typedef SkBitmapDevice INHERITED;
    463 };
    464 
    465 SkCanvas::SkCanvas(int width, int height)
    466     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    467     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    468 {
    469     inc_canvas();
    470 
    471     this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_InitFlags)->unref();
    472 }
    473 
    474 SkCanvas::SkCanvas(int width, int height, InitFlags flags)
    475     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    476     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    477 {
    478     inc_canvas();
    479 
    480     this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref();
    481 }
    482 
    483 SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
    484     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    485     , fProps(SkSurfacePropsCopyOrDefault(props))
    486 {
    487     inc_canvas();
    488 
    489     this->init(device, flags);
    490 }
    491 
    492 SkCanvas::SkCanvas(SkBaseDevice* device)
    493     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    494     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    495 {
    496     inc_canvas();
    497 
    498     this->init(device, kDefault_InitFlags);
    499 }
    500 
    501 SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
    502     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    503     , fProps(props)
    504 {
    505     inc_canvas();
    506 
    507     SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
    508     this->init(device, kDefault_InitFlags);
    509 }
    510 
    511 SkCanvas::SkCanvas(const SkBitmap& bitmap)
    512     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    513     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    514 {
    515     inc_canvas();
    516 
    517     SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
    518     this->init(device, kDefault_InitFlags);
    519 }
    520 
    521 SkCanvas::~SkCanvas() {
    522     // free up the contents of our deque
    523     this->restoreToCount(1);    // restore everything but the last
    524     SkASSERT(0 == fSaveLayerCount);
    525 
    526     this->internalRestore();    // restore the last, since we're going away
    527 
    528     SkDELETE(fMetaData);
    529 
    530     dec_canvas();
    531 }
    532 
    533 SkDrawFilter* SkCanvas::getDrawFilter() const {
    534     return fMCRec->fFilter;
    535 }
    536 
    537 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
    538     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
    539     return filter;
    540 }
    541 
    542 SkMetaData& SkCanvas::getMetaData() {
    543     // metadata users are rare, so we lazily allocate it. If that changes we
    544     // can decide to just make it a field in the device (rather than a ptr)
    545     if (NULL == fMetaData) {
    546         fMetaData = new SkMetaData;
    547     }
    548     return *fMetaData;
    549 }
    550 
    551 ///////////////////////////////////////////////////////////////////////////////
    552 
    553 void SkCanvas::flush() {
    554     SkBaseDevice* device = this->getDevice();
    555     if (device) {
    556         device->flush();
    557     }
    558 }
    559 
    560 SkISize SkCanvas::getTopLayerSize() const {
    561     SkBaseDevice* d = this->getTopDevice();
    562     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
    563 }
    564 
    565 SkIPoint SkCanvas::getTopLayerOrigin() const {
    566     SkBaseDevice* d = this->getTopDevice();
    567     return d ? d->getOrigin() : SkIPoint::Make(0, 0);
    568 }
    569 
    570 SkISize SkCanvas::getBaseLayerSize() const {
    571     SkBaseDevice* d = this->getDevice();
    572     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
    573 }
    574 
    575 SkBaseDevice* SkCanvas::getDevice() const {
    576     // return root device
    577     MCRec* rec = (MCRec*) fMCStack.front();
    578     SkASSERT(rec && rec->fLayer);
    579     return rec->fLayer->fDevice;
    580 }
    581 
    582 SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
    583     if (updateMatrixClip) {
    584         const_cast<SkCanvas*>(this)->updateDeviceCMCache();
    585     }
    586     return fMCRec->fTopLayer->fDevice;
    587 }
    588 
    589 SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
    590     // return root device
    591     SkDeque::F2BIter iter(fMCStack);
    592     MCRec*           rec = (MCRec*)iter.next();
    593     SkASSERT(rec && rec->fLayer);
    594     SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
    595 
    596     if (rootDevice == device) {
    597         return device;
    598     }
    599 
    600     if (device) {
    601         device->onAttachToCanvas(this);
    602     }
    603     if (rootDevice) {
    604         rootDevice->onDetachFromCanvas();
    605     }
    606 
    607     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
    608     rootDevice = device;
    609     this->setupDevice(device);
    610 
    611     fDeviceCMDirty = true;
    612 
    613     /*  Now we update our initial region to have the bounds of the new device,
    614         and then intersect all of the clips in our stack with these bounds,
    615         to ensure that we can't draw outside of the device's bounds (and trash
    616                                                                      memory).
    617 
    618     NOTE: this is only a partial-fix, since if the new device is larger than
    619         the previous one, we don't know how to "enlarge" the clips in our stack,
    620         so drawing may be artificially restricted. Without keeping a history of
    621         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
    622         reconstruct the correct clips, so this approximation will have to do.
    623         The caller really needs to restore() back to the base if they want to
    624         accurately take advantage of the new device bounds.
    625     */
    626 
    627     SkIRect bounds;
    628     if (device) {
    629         bounds.set(0, 0, device->width(), device->height());
    630     } else {
    631         bounds.setEmpty();
    632     }
    633     // now jam our 1st clip to be bounds, and intersect the rest with that
    634     rec->fRasterClip.setRect(bounds);
    635     while ((rec = (MCRec*)iter.next()) != NULL) {
    636         (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op);
    637     }
    638 
    639     return device;
    640 }
    641 
    642 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
    643     if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
    644         return false;
    645     }
    646 
    647     bool weAllocated = false;
    648     if (NULL == bitmap->pixelRef()) {
    649         if (!bitmap->tryAllocPixels()) {
    650             return false;
    651         }
    652         weAllocated = true;
    653     }
    654 
    655     SkBitmap bm(*bitmap);
    656     bm.lockPixels();
    657     if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
    658         return true;
    659     }
    660 
    661     if (weAllocated) {
    662         bitmap->setPixelRef(NULL);
    663     }
    664     return false;
    665 }
    666 
    667 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
    668     SkIRect r = srcRect;
    669     const SkISize size = this->getBaseLayerSize();
    670     if (!r.intersect(0, 0, size.width(), size.height())) {
    671         bitmap->reset();
    672         return false;
    673     }
    674 
    675     if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
    676         // bitmap will already be reset.
    677         return false;
    678     }
    679     if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
    680         bitmap->reset();
    681         return false;
    682     }
    683     return true;
    684 }
    685 
    686 bool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
    687     switch (origInfo.colorType()) {
    688         case kUnknown_SkColorType:
    689         case kIndex_8_SkColorType:
    690             return false;
    691         default:
    692             break;
    693     }
    694     if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
    695         return false;
    696     }
    697     if (0 == origInfo.width() || 0 == origInfo.height()) {
    698         return false;
    699     }
    700 
    701     SkBaseDevice* device = this->getDevice();
    702     if (!device) {
    703         return false;
    704     }
    705 
    706     const SkISize size = this->getBaseLayerSize();
    707     SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
    708     if (!srcR.intersect(0, 0, size.width(), size.height())) {
    709         return false;
    710     }
    711 
    712     // the intersect may have shrunk info's logical size
    713     const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height());
    714 
    715     // if x or y are negative, then we have to adjust pixels
    716     if (x > 0) {
    717         x = 0;
    718     }
    719     if (y > 0) {
    720         y = 0;
    721     }
    722     // here x,y are either 0 or negative
    723     dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
    724 
    725     // The device can assert that the requested area is always contained in its bounds
    726     return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
    727 }
    728 
    729 bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
    730     if (bitmap.getTexture()) {
    731         return false;
    732     }
    733     SkBitmap bm(bitmap);
    734     bm.lockPixels();
    735     if (bm.getPixels()) {
    736         return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
    737     }
    738     return false;
    739 }
    740 
    741 bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
    742                            int x, int y) {
    743     switch (origInfo.colorType()) {
    744         case kUnknown_SkColorType:
    745         case kIndex_8_SkColorType:
    746             return false;
    747         default:
    748             break;
    749     }
    750     if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
    751         return false;
    752     }
    753 
    754     const SkISize size = this->getBaseLayerSize();
    755     SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
    756     if (!target.intersect(0, 0, size.width(), size.height())) {
    757         return false;
    758     }
    759 
    760     SkBaseDevice* device = this->getDevice();
    761     if (!device) {
    762         return false;
    763     }
    764 
    765     // the intersect may have shrunk info's logical size
    766     const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
    767 
    768     // if x or y are negative, then we have to adjust pixels
    769     if (x > 0) {
    770         x = 0;
    771     }
    772     if (y > 0) {
    773         y = 0;
    774     }
    775     // here x,y are either 0 or negative
    776     pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
    777 
    778     // Tell our owning surface to bump its generation ID
    779     this->predrawNotify();
    780 
    781     // The device can assert that the requested area is always contained in its bounds
    782     return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
    783 }
    784 
    785 SkCanvas* SkCanvas::canvasForDrawIter() {
    786     return this;
    787 }
    788 
    789 //////////////////////////////////////////////////////////////////////////////
    790 
    791 void SkCanvas::updateDeviceCMCache() {
    792     if (fDeviceCMDirty) {
    793         const SkMatrix& totalMatrix = this->getTotalMatrix();
    794         const SkRasterClip& totalClip = fMCRec->fRasterClip;
    795         DeviceCM*       layer = fMCRec->fTopLayer;
    796 
    797         if (NULL == layer->fNext) {   // only one layer
    798             layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
    799         } else {
    800             SkRasterClip clip(totalClip);
    801             do {
    802                 layer->updateMC(totalMatrix, clip, fClipStack, &clip);
    803             } while ((layer = layer->fNext) != NULL);
    804         }
    805         fDeviceCMDirty = false;
    806     }
    807 }
    808 
    809 ///////////////////////////////////////////////////////////////////////////////
    810 
    811 int SkCanvas::internalSave() {
    812     int saveCount = this->getSaveCount(); // record this before the actual save
    813 
    814     MCRec* newTop = (MCRec*)fMCStack.push_back();
    815     new (newTop) MCRec(*fMCRec);    // balanced in restore()
    816     fMCRec = newTop;
    817 
    818     fClipStack.save();
    819 
    820     return saveCount;
    821 }
    822 
    823 int SkCanvas::save() {
    824     this->willSave();
    825     return this->internalSave();
    826 }
    827 
    828 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
    829 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
    830     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
    831 #else
    832     return true;
    833 #endif
    834 }
    835 
    836 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
    837                                SkIRect* intersection, const SkImageFilter* imageFilter) {
    838     SkIRect clipBounds;
    839     SkRegion::Op op = SkRegion::kIntersect_Op;
    840     if (!this->getClipDeviceBounds(&clipBounds)) {
    841         return false;
    842     }
    843 
    844     if (imageFilter) {
    845         imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
    846         // Filters may grow the bounds beyond the device bounds.
    847         op = SkRegion::kReplace_Op;
    848     }
    849     SkIRect ir;
    850     if (bounds) {
    851         SkRect r;
    852 
    853         this->getTotalMatrix().mapRect(&r, *bounds);
    854         r.roundOut(&ir);
    855         // early exit if the layer's bounds are clipped out
    856         if (!ir.intersect(clipBounds)) {
    857             if (bounds_affects_clip(flags)) {
    858                 fMCRec->fRasterClip.setEmpty();
    859             }
    860             return false;
    861         }
    862     } else {    // no user bounds, so just use the clip
    863         ir = clipBounds;
    864     }
    865 
    866     if (bounds_affects_clip(flags)) {
    867         fClipStack.clipDevRect(ir, op);
    868         // early exit if the clip is now empty
    869         if (!fMCRec->fRasterClip.op(ir, op)) {
    870             return false;
    871         }
    872     }
    873 
    874     if (intersection) {
    875         *intersection = ir;
    876     }
    877     return true;
    878 }
    879 
    880 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
    881     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
    882     return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
    883 }
    884 
    885 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
    886                         SaveFlags flags) {
    887     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
    888     return this->internalSaveLayer(bounds, paint, flags, false, strategy);
    889 }
    890 
    891 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
    892                                 bool justForImageFilter, SaveLayerStrategy strategy) {
    893 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
    894     flags |= kClipToLayer_SaveFlag;
    895 #endif
    896 
    897     // do this before we create the layer. We don't call the public save() since
    898     // that would invoke a possibly overridden virtual
    899     int count = this->internalSave();
    900 
    901     fDeviceCMDirty = true;
    902 
    903     SkIRect ir;
    904     if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
    905         return count;
    906     }
    907 
    908     // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
    909     // the clipRectBounds() call above?
    910     if (kNoLayer_SaveLayerStrategy == strategy) {
    911         return count;
    912     }
    913 
    914     // Kill the imagefilter if our device doesn't allow it
    915     SkLazyPaint lazyP;
    916     if (paint && paint->getImageFilter()) {
    917         if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
    918             if (justForImageFilter) {
    919                 // early exit if the layer was just for the imageFilter
    920                 return count;
    921             }
    922             SkPaint* p = lazyP.set(*paint);
    923             p->setImageFilter(NULL);
    924             paint = p;
    925         }
    926     }
    927 
    928     bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
    929     SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
    930                         isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
    931 
    932     SkBaseDevice* device;
    933     if (paint && paint->getImageFilter()) {
    934         device = this->getDevice();
    935         if (device) {
    936             device = device->createCompatibleDeviceForImageFilter(info);
    937         }
    938     } else {
    939         device = this->createLayerDevice(info);
    940     }
    941     if (NULL == device) {
    942         SkDebugf("Unable to create device for layer.");
    943         return count;
    944     }
    945     this->setupDevice(device);
    946 
    947     device->setOrigin(ir.fLeft, ir.fTop);
    948     DeviceCM* layer = SkNEW_ARGS(DeviceCM,
    949                                  (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
    950     device->unref();
    951 
    952     layer->fNext = fMCRec->fTopLayer;
    953     fMCRec->fLayer = layer;
    954     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
    955 
    956     fSaveLayerCount += 1;
    957     return count;
    958 }
    959 
    960 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
    961     return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
    962 }
    963 
    964 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
    965                              SaveFlags flags) {
    966     if (0xFF == alpha) {
    967         return this->saveLayer(bounds, NULL, flags);
    968     } else {
    969         SkPaint tmpPaint;
    970         tmpPaint.setAlpha(alpha);
    971         return this->saveLayer(bounds, &tmpPaint, flags);
    972     }
    973 }
    974 
    975 void SkCanvas::restore() {
    976     // check for underflow
    977     if (fMCStack.count() > 1) {
    978         this->willRestore();
    979         this->internalRestore();
    980         this->didRestore();
    981     }
    982 }
    983 
    984 void SkCanvas::internalRestore() {
    985     SkASSERT(fMCStack.count() != 0);
    986 
    987     fDeviceCMDirty = true;
    988     fCachedLocalClipBoundsDirty = true;
    989 
    990     fClipStack.restore();
    991 
    992     // reserve our layer (if any)
    993     DeviceCM* layer = fMCRec->fLayer;   // may be null
    994     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
    995     fMCRec->fLayer = NULL;
    996 
    997     // now do the normal restore()
    998     fMCRec->~MCRec();       // balanced in save()
    999     fMCStack.pop_back();
   1000     fMCRec = (MCRec*)fMCStack.back();
   1001 
   1002     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
   1003         since if we're being recorded, we don't want to record this (the
   1004         recorder will have already recorded the restore).
   1005     */
   1006     if (layer) {
   1007         if (layer->fNext) {
   1008             const SkIPoint& origin = layer->fDevice->getOrigin();
   1009             this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
   1010                                      layer->fPaint);
   1011             // reset this, since internalDrawDevice will have set it to true
   1012             fDeviceCMDirty = true;
   1013 
   1014             SkASSERT(fSaveLayerCount > 0);
   1015             fSaveLayerCount -= 1;
   1016         }
   1017         SkDELETE(layer);
   1018     }
   1019 }
   1020 
   1021 int SkCanvas::getSaveCount() const {
   1022     return fMCStack.count();
   1023 }
   1024 
   1025 void SkCanvas::restoreToCount(int count) {
   1026     // sanity check
   1027     if (count < 1) {
   1028         count = 1;
   1029     }
   1030 
   1031     int n = this->getSaveCount() - count;
   1032     for (int i = 0; i < n; ++i) {
   1033         this->restore();
   1034     }
   1035 }
   1036 
   1037 bool SkCanvas::isDrawingToLayer() const {
   1038     return fSaveLayerCount > 0;
   1039 }
   1040 
   1041 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
   1042     if (NULL == props) {
   1043         props = &fProps;
   1044     }
   1045     return this->onNewSurface(info, *props);
   1046 }
   1047 
   1048 SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
   1049     SkBaseDevice* dev = this->getDevice();
   1050     return dev ? dev->newSurface(info, props) : NULL;
   1051 }
   1052 
   1053 SkImageInfo SkCanvas::imageInfo() const {
   1054     SkBaseDevice* dev = this->getDevice();
   1055     if (dev) {
   1056         return dev->imageInfo();
   1057     } else {
   1058         return SkImageInfo::MakeUnknown(0, 0);
   1059     }
   1060 }
   1061 
   1062 const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
   1063     return this->onPeekPixels(info, rowBytes);
   1064 }
   1065 
   1066 const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
   1067     SkBaseDevice* dev = this->getDevice();
   1068     return dev ? dev->peekPixels(info, rowBytes) : NULL;
   1069 }
   1070 
   1071 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
   1072     void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
   1073     if (pixels && origin) {
   1074         *origin = this->getTopDevice(false)->getOrigin();
   1075     }
   1076     return pixels;
   1077 }
   1078 
   1079 void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
   1080     SkBaseDevice* dev = this->getTopDevice();
   1081     return dev ? dev->accessPixels(info, rowBytes) : NULL;
   1082 }
   1083 
   1084 SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
   1085     fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
   1086     if (NULL == fAddr) {
   1087         fInfo = canvas->imageInfo();
   1088         if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
   1089             return; // failure, fAddr is NULL
   1090         }
   1091         if (!canvas->readPixels(&fBitmap, 0, 0)) {
   1092             return; // failure, fAddr is NULL
   1093         }
   1094         fAddr = fBitmap.getPixels();
   1095         fRowBytes = fBitmap.rowBytes();
   1096     }
   1097     SkASSERT(fAddr);    // success
   1098 }
   1099 
   1100 bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
   1101     if (fAddr) {
   1102         return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
   1103     } else {
   1104         bitmap->reset();
   1105         return false;
   1106     }
   1107 }
   1108 
   1109 void SkCanvas::onPushCull(const SkRect& cullRect) {
   1110     // do nothing. Subclasses may do something
   1111 }
   1112 
   1113 void SkCanvas::onPopCull() {
   1114     // do nothing. Subclasses may do something
   1115 }
   1116 
   1117 /////////////////////////////////////////////////////////////////////////////
   1118 #ifdef SK_DEBUG
   1119 // Ensure that cull rects are monotonically nested in device space.
   1120 void SkCanvas::validateCull(const SkIRect& devCull) {
   1121     if (fCullStack.isEmpty()
   1122         || devCull.isEmpty()
   1123         || fCullStack.top().contains(devCull)) {
   1124         return;
   1125     }
   1126 
   1127     SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
   1128               devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
   1129               fCullStack.top().x(), fCullStack.top().y(),
   1130               fCullStack.top().right(), fCullStack.top().bottom()));
   1131 
   1132 #ifdef ASSERT_NESTED_CULLING
   1133     SkDEBUGFAIL("Invalid cull.");
   1134 #endif
   1135 }
   1136 #endif
   1137 
   1138 void SkCanvas::pushCull(const SkRect& cullRect) {
   1139     ++fCullCount;
   1140     this->onPushCull(cullRect);
   1141 
   1142 #ifdef SK_DEBUG
   1143     // Map the cull rect into device space.
   1144     SkRect mappedCull;
   1145     this->getTotalMatrix().mapRect(&mappedCull, cullRect);
   1146 
   1147     // Take clipping into account.
   1148     SkIRect devClip, devCull;
   1149     mappedCull.roundOut(&devCull);
   1150     this->getClipDeviceBounds(&devClip);
   1151     if (!devCull.intersect(devClip)) {
   1152         devCull.setEmpty();
   1153     }
   1154 
   1155     this->validateCull(devCull);
   1156     fCullStack.push(devCull); // balanced in popCull
   1157 #endif
   1158 }
   1159 
   1160 void SkCanvas::popCull() {
   1161     SkASSERT(fCullStack.count() == fCullCount);
   1162 
   1163     if (fCullCount > 0) {
   1164         --fCullCount;
   1165         this->onPopCull();
   1166 
   1167         SkDEBUGCODE(fCullStack.pop());
   1168     }
   1169 }
   1170 
   1171 /////////////////////////////////////////////////////////////////////////////
   1172 
   1173 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
   1174                                 const SkMatrix& matrix, const SkPaint* paint) {
   1175     if (bitmap.drawsNothing()) {
   1176         return;
   1177     }
   1178 
   1179     SkLazyPaint lazy;
   1180     if (NULL == paint) {
   1181         paint = lazy.init();
   1182     }
   1183 
   1184     SkDEBUGCODE(bitmap.validate();)
   1185 
   1186     SkRect storage;
   1187     const SkRect* bounds = NULL;
   1188     if (paint && paint->canComputeFastBounds()) {
   1189         bitmap.getBounds(&storage);
   1190         matrix.mapRect(&storage);
   1191         bounds = &paint->computeFastBounds(storage, &storage);
   1192     }
   1193 
   1194     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
   1195 
   1196     while (iter.next()) {
   1197         iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
   1198     }
   1199 
   1200     LOOPER_END
   1201 }
   1202 
   1203 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
   1204                                   const SkPaint* paint) {
   1205     SkPaint tmp;
   1206     if (NULL == paint) {
   1207         tmp.setDither(true);
   1208         paint = &tmp;
   1209     }
   1210 
   1211     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
   1212     while (iter.next()) {
   1213         SkBaseDevice* dstDev = iter.fDevice;
   1214         paint = &looper.paint();
   1215         SkImageFilter* filter = paint->getImageFilter();
   1216         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
   1217         if (filter && !dstDev->canHandleImageFilter(filter)) {
   1218             SkDeviceImageFilterProxy proxy(dstDev);
   1219             SkBitmap dst;
   1220             SkIPoint offset = SkIPoint::Make(0, 0);
   1221             const SkBitmap& src = srcDev->accessBitmap(false);
   1222             SkMatrix matrix = *iter.fMatrix;
   1223             matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
   1224             SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
   1225             SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
   1226             SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
   1227             if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
   1228                 SkPaint tmpUnfiltered(*paint);
   1229                 tmpUnfiltered.setImageFilter(NULL);
   1230                 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
   1231                                    tmpUnfiltered);
   1232             }
   1233         } else {
   1234             dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
   1235         }
   1236     }
   1237     LOOPER_END
   1238 }
   1239 
   1240 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
   1241                           const SkPaint* paint) {
   1242     if (bitmap.drawsNothing()) {
   1243         return;
   1244     }
   1245     SkDEBUGCODE(bitmap.validate();)
   1246 
   1247     SkPaint tmp;
   1248     if (NULL == paint) {
   1249         paint = &tmp;
   1250     }
   1251 
   1252     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
   1253 
   1254     while (iter.next()) {
   1255         paint = &looper.paint();
   1256         SkImageFilter* filter = paint->getImageFilter();
   1257         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
   1258         if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
   1259             SkDeviceImageFilterProxy proxy(iter.fDevice);
   1260             SkBitmap dst;
   1261             SkIPoint offset = SkIPoint::Make(0, 0);
   1262             SkMatrix matrix = *iter.fMatrix;
   1263             matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
   1264             SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1265             SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
   1266             SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
   1267             if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
   1268                 SkPaint tmpUnfiltered(*paint);
   1269                 tmpUnfiltered.setImageFilter(NULL);
   1270                 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
   1271                                          tmpUnfiltered);
   1272             }
   1273         } else {
   1274             iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
   1275         }
   1276     }
   1277     LOOPER_END
   1278 }
   1279 
   1280 /////////////////////////////////////////////////////////////////////////////
   1281 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
   1282     SkMatrix m;
   1283     m.setTranslate(dx, dy);
   1284     this->concat(m);
   1285 }
   1286 
   1287 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
   1288     SkMatrix m;
   1289     m.setScale(sx, sy);
   1290     this->concat(m);
   1291 }
   1292 
   1293 void SkCanvas::rotate(SkScalar degrees) {
   1294     SkMatrix m;
   1295     m.setRotate(degrees);
   1296     this->concat(m);
   1297 }
   1298 
   1299 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
   1300     SkMatrix m;
   1301     m.setSkew(sx, sy);
   1302     this->concat(m);
   1303 }
   1304 
   1305 void SkCanvas::concat(const SkMatrix& matrix) {
   1306     if (matrix.isIdentity()) {
   1307         return;
   1308     }
   1309 
   1310     fDeviceCMDirty = true;
   1311     fCachedLocalClipBoundsDirty = true;
   1312     fMCRec->fMatrix.preConcat(matrix);
   1313 
   1314     this->didConcat(matrix);
   1315 }
   1316 
   1317 void SkCanvas::setMatrix(const SkMatrix& matrix) {
   1318     fDeviceCMDirty = true;
   1319     fCachedLocalClipBoundsDirty = true;
   1320     fMCRec->fMatrix = matrix;
   1321     this->didSetMatrix(matrix);
   1322 }
   1323 
   1324 void SkCanvas::resetMatrix() {
   1325     SkMatrix matrix;
   1326 
   1327     matrix.reset();
   1328     this->setMatrix(matrix);
   1329 }
   1330 
   1331 //////////////////////////////////////////////////////////////////////////////
   1332 
   1333 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
   1334     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1335     this->onClipRect(rect, op, edgeStyle);
   1336 }
   1337 
   1338 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   1339 #ifdef SK_ENABLE_CLIP_QUICKREJECT
   1340     if (SkRegion::kIntersect_Op == op) {
   1341         if (fMCRec->fRasterClip.isEmpty()) {
   1342             return false;
   1343         }
   1344 
   1345         if (this->quickReject(rect)) {
   1346             fDeviceCMDirty = true;
   1347             fCachedLocalClipBoundsDirty = true;
   1348 
   1349             fClipStack.clipEmpty();
   1350             return fMCRec->fRasterClip.setEmpty();
   1351         }
   1352     }
   1353 #endif
   1354 
   1355     AutoValidateClip avc(this);
   1356 
   1357     fDeviceCMDirty = true;
   1358     fCachedLocalClipBoundsDirty = true;
   1359     if (!fAllowSoftClip) {
   1360         edgeStyle = kHard_ClipEdgeStyle;
   1361     }
   1362 
   1363     if (fMCRec->fMatrix.rectStaysRect()) {
   1364         // for these simpler matrices, we can stay a rect even after applying
   1365         // the matrix. This means we don't have to a) make a path, and b) tell
   1366         // the region code to scan-convert the path, only to discover that it
   1367         // is really just a rect.
   1368         SkRect      r;
   1369 
   1370         fMCRec->fMatrix.mapRect(&r, rect);
   1371         fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
   1372         fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
   1373     } else {
   1374         // since we're rotated or some such thing, we convert the rect to a path
   1375         // and clip against that, since it can handle any matrix. However, to
   1376         // avoid recursion in the case where we are subclassed (e.g. Pictures)
   1377         // we explicitly call "our" version of clipPath.
   1378         SkPath  path;
   1379 
   1380         path.addRect(rect);
   1381         this->SkCanvas::onClipPath(path, op, edgeStyle);
   1382     }
   1383 }
   1384 
   1385 static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
   1386                             SkRegion::Op op, bool doAA) {
   1387     rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
   1388 }
   1389 
   1390 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
   1391     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1392     if (rrect.isRect()) {
   1393         this->onClipRect(rrect.getBounds(), op, edgeStyle);
   1394     } else {
   1395         this->onClipRRect(rrect, op, edgeStyle);
   1396     }
   1397 }
   1398 
   1399 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   1400     SkRRect transformedRRect;
   1401     if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
   1402         AutoValidateClip avc(this);
   1403 
   1404         fDeviceCMDirty = true;
   1405         fCachedLocalClipBoundsDirty = true;
   1406         if (!fAllowSoftClip) {
   1407             edgeStyle = kHard_ClipEdgeStyle;
   1408         }
   1409 
   1410         fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
   1411 
   1412         SkPath devPath;
   1413         devPath.addRRect(transformedRRect);
   1414 
   1415         rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
   1416         return;
   1417     }
   1418 
   1419     SkPath path;
   1420     path.addRRect(rrect);
   1421     // call the non-virtual version
   1422     this->SkCanvas::onClipPath(path, op, edgeStyle);
   1423 }
   1424 
   1425 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
   1426     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1427     SkRect r;
   1428     if (!path.isInverseFillType() && path.isRect(&r)) {
   1429         this->onClipRect(r, op, edgeStyle);
   1430     } else {
   1431         this->onClipPath(path, op, edgeStyle);
   1432     }
   1433 }
   1434 
   1435 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   1436 #ifdef SK_ENABLE_CLIP_QUICKREJECT
   1437     if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
   1438         if (fMCRec->fRasterClip.isEmpty()) {
   1439             return false;
   1440         }
   1441 
   1442         if (this->quickReject(path.getBounds())) {
   1443             fDeviceCMDirty = true;
   1444             fCachedLocalClipBoundsDirty = true;
   1445 
   1446             fClipStack.clipEmpty();
   1447             return fMCRec->fRasterClip.setEmpty();
   1448         }
   1449     }
   1450 #endif
   1451 
   1452     AutoValidateClip avc(this);
   1453 
   1454     fDeviceCMDirty = true;
   1455     fCachedLocalClipBoundsDirty = true;
   1456     if (!fAllowSoftClip) {
   1457         edgeStyle = kHard_ClipEdgeStyle;
   1458     }
   1459 
   1460     SkPath devPath;
   1461     path.transform(fMCRec->fMatrix, &devPath);
   1462 
   1463     // Check if the transfomation, or the original path itself
   1464     // made us empty. Note this can also happen if we contained NaN
   1465     // values. computing the bounds detects this, and will set our
   1466     // bounds to empty if that is the case. (see SkRect::set(pts, count))
   1467     if (devPath.getBounds().isEmpty()) {
   1468         // resetting the path will remove any NaN or other wanky values
   1469         // that might upset our scan converter.
   1470         devPath.reset();
   1471     }
   1472 
   1473     // if we called path.swap() we could avoid a deep copy of this path
   1474     fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
   1475 
   1476     if (fAllowSimplifyClip) {
   1477         devPath.reset();
   1478         devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
   1479         const SkClipStack* clipStack = getClipStack();
   1480         SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
   1481         const SkClipStack::Element* element;
   1482         while ((element = iter.next())) {
   1483             SkClipStack::Element::Type type = element->getType();
   1484             SkPath operand;
   1485             if (type != SkClipStack::Element::kEmpty_Type) {
   1486                 element->asPath(&operand);
   1487             }
   1488             SkRegion::Op elementOp = element->getOp();
   1489             if (elementOp == SkRegion::kReplace_Op) {
   1490                 devPath = operand;
   1491             } else {
   1492                 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
   1493             }
   1494             // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
   1495             // perhaps we need an API change to avoid this sort of mixed-signals about
   1496             // clipping.
   1497             if (element->isAA()) {
   1498                 edgeStyle = kSoft_ClipEdgeStyle;
   1499             }
   1500         }
   1501         op = SkRegion::kReplace_Op;
   1502     }
   1503 
   1504     rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
   1505 }
   1506 
   1507 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
   1508     this->onClipRegion(rgn, op);
   1509 }
   1510 
   1511 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
   1512     AutoValidateClip avc(this);
   1513 
   1514     fDeviceCMDirty = true;
   1515     fCachedLocalClipBoundsDirty = true;
   1516 
   1517     // todo: signal fClipStack that we have a region, and therefore (I guess)
   1518     // we have to ignore it, and use the region directly?
   1519     fClipStack.clipDevRect(rgn.getBounds(), op);
   1520 
   1521     fMCRec->fRasterClip.op(rgn, op);
   1522 }
   1523 
   1524 #ifdef SK_DEBUG
   1525 void SkCanvas::validateClip() const {
   1526     // construct clipRgn from the clipstack
   1527     const SkBaseDevice* device = this->getDevice();
   1528     if (!device) {
   1529         SkASSERT(this->isClipEmpty());
   1530         return;
   1531     }
   1532 
   1533     SkIRect ir;
   1534     ir.set(0, 0, device->width(), device->height());
   1535     SkRasterClip tmpClip(ir, fConservativeRasterClip);
   1536 
   1537     SkClipStack::B2TIter                iter(fClipStack);
   1538     const SkClipStack::Element* element;
   1539     while ((element = iter.next()) != NULL) {
   1540         switch (element->getType()) {
   1541             case SkClipStack::Element::kRect_Type:
   1542                 element->getRect().round(&ir);
   1543                 tmpClip.op(ir, element->getOp());
   1544                 break;
   1545             case SkClipStack::Element::kEmpty_Type:
   1546                 tmpClip.setEmpty();
   1547                 break;
   1548             default: {
   1549                 SkPath path;
   1550                 element->asPath(&path);
   1551                 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
   1552                 break;
   1553             }
   1554         }
   1555     }
   1556 }
   1557 #endif
   1558 
   1559 void SkCanvas::replayClips(ClipVisitor* visitor) const {
   1560     SkClipStack::B2TIter                iter(fClipStack);
   1561     const SkClipStack::Element*         element;
   1562 
   1563     while ((element = iter.next()) != NULL) {
   1564         element->replay(visitor);
   1565     }
   1566 }
   1567 
   1568 ///////////////////////////////////////////////////////////////////////////////
   1569 
   1570 bool SkCanvas::isClipEmpty() const {
   1571     return fMCRec->fRasterClip.isEmpty();
   1572 }
   1573 
   1574 bool SkCanvas::isClipRect() const {
   1575     return fMCRec->fRasterClip.isRect();
   1576 }
   1577 
   1578 bool SkCanvas::quickReject(const SkRect& rect) const {
   1579     if (!rect.isFinite())
   1580         return true;
   1581 
   1582     if (fMCRec->fRasterClip.isEmpty()) {
   1583         return true;
   1584     }
   1585 
   1586     if (fMCRec->fMatrix.hasPerspective()) {
   1587         SkRect dst;
   1588         fMCRec->fMatrix.mapRect(&dst, rect);
   1589         SkIRect idst;
   1590         dst.roundOut(&idst);
   1591         return !SkIRect::Intersects(idst, fMCRec->fRasterClip.getBounds());
   1592     } else {
   1593         const SkRect& clipR = this->getLocalClipBounds();
   1594 
   1595         // for speed, do the most likely reject compares first
   1596         // TODO: should we use | instead, or compare all 4 at once?
   1597         if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
   1598             return true;
   1599         }
   1600         if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
   1601             return true;
   1602         }
   1603         return false;
   1604     }
   1605 }
   1606 
   1607 bool SkCanvas::quickReject(const SkPath& path) const {
   1608     return path.isEmpty() || this->quickReject(path.getBounds());
   1609 }
   1610 
   1611 bool SkCanvas::getClipBounds(SkRect* bounds) const {
   1612     SkIRect ibounds;
   1613     if (!this->getClipDeviceBounds(&ibounds)) {
   1614         return false;
   1615     }
   1616 
   1617     SkMatrix inverse;
   1618     // if we can't invert the CTM, we can't return local clip bounds
   1619     if (!fMCRec->fMatrix.invert(&inverse)) {
   1620         if (bounds) {
   1621             bounds->setEmpty();
   1622         }
   1623         return false;
   1624     }
   1625 
   1626     if (bounds) {
   1627         SkRect r;
   1628         // adjust it outwards in case we are antialiasing
   1629         const int inset = 1;
   1630 
   1631         r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
   1632                ibounds.fRight + inset, ibounds.fBottom + inset);
   1633         inverse.mapRect(bounds, r);
   1634     }
   1635     return true;
   1636 }
   1637 
   1638 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
   1639     const SkRasterClip& clip = fMCRec->fRasterClip;
   1640     if (clip.isEmpty()) {
   1641         if (bounds) {
   1642             bounds->setEmpty();
   1643         }
   1644         return false;
   1645     }
   1646 
   1647     if (bounds) {
   1648         *bounds = clip.getBounds();
   1649     }
   1650     return true;
   1651 }
   1652 
   1653 const SkMatrix& SkCanvas::getTotalMatrix() const {
   1654     return fMCRec->fMatrix;
   1655 }
   1656 
   1657 const SkRegion& SkCanvas::internal_private_getTotalClip() const {
   1658     return fMCRec->fRasterClip.forceGetBW();
   1659 }
   1660 
   1661 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
   1662     SkBaseDevice* dev = this->getTopDevice();
   1663     return dev ? dev->accessRenderTarget() : NULL;
   1664 }
   1665 
   1666 SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
   1667     SkBaseDevice* device = this->getTopDevice();
   1668     return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
   1669 }
   1670 
   1671 GrContext* SkCanvas::getGrContext() {
   1672 #if SK_SUPPORT_GPU
   1673     SkBaseDevice* device = this->getTopDevice();
   1674     if (device) {
   1675         GrRenderTarget* renderTarget = device->accessRenderTarget();
   1676         if (renderTarget) {
   1677             return renderTarget->getContext();
   1678         }
   1679     }
   1680 #endif
   1681 
   1682     return NULL;
   1683 
   1684 }
   1685 
   1686 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
   1687                           const SkPaint& paint) {
   1688     if (outer.isEmpty()) {
   1689         return;
   1690     }
   1691     if (inner.isEmpty()) {
   1692         this->drawRRect(outer, paint);
   1693         return;
   1694     }
   1695 
   1696     // We don't have this method (yet), but technically this is what we should
   1697     // be able to assert...
   1698     // SkASSERT(outer.contains(inner));
   1699     //
   1700     // For now at least check for containment of bounds
   1701     SkASSERT(outer.getBounds().contains(inner.getBounds()));
   1702 
   1703     this->onDrawDRRect(outer, inner, paint);
   1704 }
   1705 
   1706 //////////////////////////////////////////////////////////////////////////////
   1707 //  These are the virtual drawing methods
   1708 //////////////////////////////////////////////////////////////////////////////
   1709 
   1710 void SkCanvas::clear(SkColor color) {
   1711     SkDrawIter  iter(this);
   1712     this->predrawNotify();
   1713     while (iter.next()) {
   1714         iter.fDevice->clear(color);
   1715     }
   1716 }
   1717 
   1718 void SkCanvas::onDiscard() {
   1719     if (fSurfaceBase) {
   1720         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
   1721     }
   1722 }
   1723 
   1724 void SkCanvas::drawPaint(const SkPaint& paint) {
   1725     this->internalDrawPaint(paint);
   1726 }
   1727 
   1728 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
   1729     LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
   1730 
   1731     while (iter.next()) {
   1732         iter.fDevice->drawPaint(iter, looper.paint());
   1733     }
   1734 
   1735     LOOPER_END
   1736 }
   1737 
   1738 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
   1739                           const SkPaint& paint) {
   1740     if ((long)count <= 0) {
   1741         return;
   1742     }
   1743 
   1744     SkRect r, storage;
   1745     const SkRect* bounds = NULL;
   1746     if (paint.canComputeFastBounds()) {
   1747         // special-case 2 points (common for drawing a single line)
   1748         if (2 == count) {
   1749             r.set(pts[0], pts[1]);
   1750         } else {
   1751             r.set(pts, SkToInt(count));
   1752         }
   1753         bounds = &paint.computeFastStrokeBounds(r, &storage);
   1754         if (this->quickReject(*bounds)) {
   1755             return;
   1756         }
   1757     }
   1758 
   1759     SkASSERT(pts != NULL);
   1760 
   1761     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
   1762 
   1763     while (iter.next()) {
   1764         iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
   1765     }
   1766 
   1767     LOOPER_END
   1768 }
   1769 
   1770 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
   1771     SkRect storage;
   1772     const SkRect* bounds = NULL;
   1773     if (paint.canComputeFastBounds()) {
   1774         bounds = &paint.computeFastBounds(r, &storage);
   1775         if (this->quickReject(*bounds)) {
   1776             return;
   1777         }
   1778     }
   1779 
   1780     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
   1781 
   1782     while (iter.next()) {
   1783         iter.fDevice->drawRect(iter, r, looper.paint());
   1784     }
   1785 
   1786     LOOPER_END
   1787 }
   1788 
   1789 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
   1790     SkRect storage;
   1791     const SkRect* bounds = NULL;
   1792     if (paint.canComputeFastBounds()) {
   1793         bounds = &paint.computeFastBounds(oval, &storage);
   1794         if (this->quickReject(*bounds)) {
   1795             return;
   1796         }
   1797     }
   1798 
   1799     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
   1800 
   1801     while (iter.next()) {
   1802         iter.fDevice->drawOval(iter, oval, looper.paint());
   1803     }
   1804 
   1805     LOOPER_END
   1806 }
   1807 
   1808 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   1809     SkRect storage;
   1810     const SkRect* bounds = NULL;
   1811     if (paint.canComputeFastBounds()) {
   1812         bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
   1813         if (this->quickReject(*bounds)) {
   1814             return;
   1815         }
   1816     }
   1817 
   1818     if (rrect.isRect()) {
   1819         // call the non-virtual version
   1820         this->SkCanvas::drawRect(rrect.getBounds(), paint);
   1821         return;
   1822     } else if (rrect.isOval()) {
   1823         // call the non-virtual version
   1824         this->SkCanvas::drawOval(rrect.getBounds(), paint);
   1825         return;
   1826     }
   1827 
   1828     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
   1829 
   1830     while (iter.next()) {
   1831         iter.fDevice->drawRRect(iter, rrect, looper.paint());
   1832     }
   1833 
   1834     LOOPER_END
   1835 }
   1836 
   1837 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
   1838                             const SkPaint& paint) {
   1839     SkRect storage;
   1840     const SkRect* bounds = NULL;
   1841     if (paint.canComputeFastBounds()) {
   1842         bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
   1843         if (this->quickReject(*bounds)) {
   1844             return;
   1845         }
   1846     }
   1847 
   1848     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
   1849 
   1850     while (iter.next()) {
   1851         iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
   1852     }
   1853 
   1854     LOOPER_END
   1855 }
   1856 
   1857 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   1858     if (!path.isFinite()) {
   1859         return;
   1860     }
   1861 
   1862     SkRect storage;
   1863     const SkRect* bounds = NULL;
   1864     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
   1865         const SkRect& pathBounds = path.getBounds();
   1866         bounds = &paint.computeFastBounds(pathBounds, &storage);
   1867         if (this->quickReject(*bounds)) {
   1868             return;
   1869         }
   1870     }
   1871 
   1872     const SkRect& r = path.getBounds();
   1873     if (r.width() <= 0 && r.height() <= 0) {
   1874         if (path.isInverseFillType()) {
   1875             this->internalDrawPaint(paint);
   1876         }
   1877         return;
   1878     }
   1879 
   1880     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
   1881 
   1882     while (iter.next()) {
   1883         iter.fDevice->drawPath(iter, path, looper.paint());
   1884     }
   1885 
   1886     LOOPER_END
   1887 }
   1888 
   1889 void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top,
   1890                        const SkPaint* paint) {
   1891     image->draw(this, left, top, paint);
   1892 }
   1893 
   1894 void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src,
   1895                            const SkRect& dst,
   1896                            const SkPaint* paint) {
   1897     image->draw(this, src, dst, paint);
   1898 }
   1899 
   1900 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
   1901                           const SkPaint* paint) {
   1902     SkDEBUGCODE(bitmap.validate();)
   1903 
   1904     if (NULL == paint || paint->canComputeFastBounds()) {
   1905         SkRect bounds = {
   1906             x, y,
   1907             x + SkIntToScalar(bitmap.width()),
   1908             y + SkIntToScalar(bitmap.height())
   1909         };
   1910         if (paint) {
   1911             (void)paint->computeFastBounds(bounds, &bounds);
   1912         }
   1913         if (this->quickReject(bounds)) {
   1914             return;
   1915         }
   1916     }
   1917 
   1918     SkMatrix matrix;
   1919     matrix.setTranslate(x, y);
   1920     this->internalDrawBitmap(bitmap, matrix, paint);
   1921 }
   1922 
   1923 // this one is non-virtual, so it can be called safely by other canvas apis
   1924 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
   1925                                       const SkRect& dst, const SkPaint* paint,
   1926                                       DrawBitmapRectFlags flags) {
   1927     if (bitmap.drawsNothing() || dst.isEmpty()) {
   1928         return;
   1929     }
   1930 
   1931     SkRect storage;
   1932     const SkRect* bounds = &dst;
   1933     if (NULL == paint || paint->canComputeFastBounds()) {
   1934         if (paint) {
   1935             bounds = &paint->computeFastBounds(dst, &storage);
   1936         }
   1937         if (this->quickReject(*bounds)) {
   1938             return;
   1939         }
   1940     }
   1941 
   1942     SkLazyPaint lazy;
   1943     if (NULL == paint) {
   1944         paint = lazy.init();
   1945     }
   1946 
   1947     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
   1948 
   1949     while (iter.next()) {
   1950         iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
   1951     }
   1952 
   1953     LOOPER_END
   1954 }
   1955 
   1956 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
   1957                                     const SkRect& dst, const SkPaint* paint,
   1958                                     DrawBitmapRectFlags flags) {
   1959     SkDEBUGCODE(bitmap.validate();)
   1960     this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
   1961 }
   1962 
   1963 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
   1964                                 const SkPaint* paint) {
   1965     SkDEBUGCODE(bitmap.validate();)
   1966     this->internalDrawBitmap(bitmap, matrix, paint);
   1967 }
   1968 
   1969 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
   1970                                       const SkIRect& center, const SkRect& dst,
   1971                                       const SkPaint* paint) {
   1972     if (bitmap.drawsNothing()) {
   1973         return;
   1974     }
   1975     if (NULL == paint || paint->canComputeFastBounds()) {
   1976         SkRect storage;
   1977         const SkRect* bounds = &dst;
   1978         if (paint) {
   1979             bounds = &paint->computeFastBounds(dst, &storage);
   1980         }
   1981         if (this->quickReject(*bounds)) {
   1982             return;
   1983         }
   1984     }
   1985 
   1986     const int32_t w = bitmap.width();
   1987     const int32_t h = bitmap.height();
   1988 
   1989     SkIRect c = center;
   1990     // pin center to the bounds of the bitmap
   1991     c.fLeft = SkMax32(0, center.fLeft);
   1992     c.fTop = SkMax32(0, center.fTop);
   1993     c.fRight = SkPin32(center.fRight, c.fLeft, w);
   1994     c.fBottom = SkPin32(center.fBottom, c.fTop, h);
   1995 
   1996     const SkScalar srcX[4] = {
   1997         0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
   1998     };
   1999     const SkScalar srcY[4] = {
   2000         0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
   2001     };
   2002     SkScalar dstX[4] = {
   2003         dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
   2004         dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
   2005     };
   2006     SkScalar dstY[4] = {
   2007         dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
   2008         dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
   2009     };
   2010 
   2011     if (dstX[1] > dstX[2]) {
   2012         dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
   2013         dstX[2] = dstX[1];
   2014     }
   2015 
   2016     if (dstY[1] > dstY[2]) {
   2017         dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
   2018         dstY[2] = dstY[1];
   2019     }
   2020 
   2021     for (int y = 0; y < 3; y++) {
   2022         SkRect s, d;
   2023 
   2024         s.fTop = srcY[y];
   2025         s.fBottom = srcY[y+1];
   2026         d.fTop = dstY[y];
   2027         d.fBottom = dstY[y+1];
   2028         for (int x = 0; x < 3; x++) {
   2029             s.fLeft = srcX[x];
   2030             s.fRight = srcX[x+1];
   2031             d.fLeft = dstX[x];
   2032             d.fRight = dstX[x+1];
   2033             this->internalDrawBitmapRect(bitmap, &s, d, paint,
   2034                                          kNone_DrawBitmapRectFlag);
   2035         }
   2036     }
   2037 }
   2038 
   2039 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
   2040                               const SkRect& dst, const SkPaint* paint) {
   2041     SkDEBUGCODE(bitmap.validate();)
   2042 
   2043     // Need a device entry-point, so gpu can use a mesh
   2044     this->internalDrawBitmapNine(bitmap, center, dst, paint);
   2045 }
   2046 
   2047 class SkDeviceFilteredPaint {
   2048 public:
   2049     SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
   2050         SkBaseDevice::TextFlags flags;
   2051         if (device->filterTextFlags(paint, &flags)) {
   2052             SkPaint* newPaint = fLazy.set(paint);
   2053             newPaint->setFlags(flags.fFlags);
   2054             fPaint = newPaint;
   2055         } else {
   2056             fPaint = &paint;
   2057         }
   2058     }
   2059 
   2060     const SkPaint& paint() const { return *fPaint; }
   2061 
   2062 private:
   2063     const SkPaint*  fPaint;
   2064     SkLazyPaint     fLazy;
   2065 };
   2066 
   2067 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
   2068                         const SkRect& r, SkScalar textSize) {
   2069     if (paint.getStyle() == SkPaint::kFill_Style) {
   2070         draw.fDevice->drawRect(draw, r, paint);
   2071     } else {
   2072         SkPaint p(paint);
   2073         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
   2074         draw.fDevice->drawRect(draw, r, p);
   2075     }
   2076 }
   2077 
   2078 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
   2079                                    const char text[], size_t byteLength,
   2080                                    SkScalar x, SkScalar y) {
   2081     SkASSERT(byteLength == 0 || text != NULL);
   2082 
   2083     // nothing to draw
   2084     if (text == NULL || byteLength == 0 ||
   2085         draw.fClip->isEmpty() ||
   2086         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
   2087         return;
   2088     }
   2089 
   2090     SkScalar    width = 0;
   2091     SkPoint     start;
   2092 
   2093     start.set(0, 0);    // to avoid warning
   2094     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
   2095                             SkPaint::kStrikeThruText_Flag)) {
   2096         width = paint.measureText(text, byteLength);
   2097 
   2098         SkScalar offsetX = 0;
   2099         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   2100             offsetX = SkScalarHalf(width);
   2101         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
   2102             offsetX = width;
   2103         }
   2104         start.set(x - offsetX, y);
   2105     }
   2106 
   2107     if (0 == width) {
   2108         return;
   2109     }
   2110 
   2111     uint32_t flags = paint.getFlags();
   2112 
   2113     if (flags & (SkPaint::kUnderlineText_Flag |
   2114                  SkPaint::kStrikeThruText_Flag)) {
   2115         SkScalar textSize = paint.getTextSize();
   2116         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
   2117         SkRect   r;
   2118 
   2119         r.fLeft = start.fX;
   2120         r.fRight = start.fX + width;
   2121 
   2122         if (flags & SkPaint::kUnderlineText_Flag) {
   2123             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
   2124                                              start.fY);
   2125             r.fTop = offset;
   2126             r.fBottom = offset + height;
   2127             DrawRect(draw, paint, r, textSize);
   2128         }
   2129         if (flags & SkPaint::kStrikeThruText_Flag) {
   2130             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
   2131                                              start.fY);
   2132             r.fTop = offset;
   2133             r.fBottom = offset + height;
   2134             DrawRect(draw, paint, r, textSize);
   2135         }
   2136     }
   2137 }
   2138 
   2139 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
   2140                           const SkPaint& paint) {
   2141     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2142 
   2143     while (iter.next()) {
   2144         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2145         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
   2146         DrawTextDecorations(iter, dfp.paint(),
   2147                             static_cast<const char*>(text), byteLength, x, y);
   2148     }
   2149 
   2150     LOOPER_END
   2151 }
   2152 
   2153 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
   2154                              const SkPaint& paint) {
   2155     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2156 
   2157     while (iter.next()) {
   2158         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2159         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
   2160                                   dfp.paint());
   2161     }
   2162 
   2163     LOOPER_END
   2164 }
   2165 
   2166 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
   2167                               SkScalar constY, const SkPaint& paint) {
   2168     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2169 
   2170     while (iter.next()) {
   2171         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2172         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
   2173                                   dfp.paint());
   2174     }
   2175 
   2176     LOOPER_END
   2177 }
   2178 
   2179 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
   2180                                 const SkMatrix* matrix, const SkPaint& paint) {
   2181     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2182 
   2183     while (iter.next()) {
   2184         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
   2185                                      matrix, looper.paint());
   2186     }
   2187 
   2188     LOOPER_END
   2189 }
   2190 
   2191 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
   2192                               const SkPaint& paint) {
   2193 
   2194     // FIXME: temporarily disable quickreject for empty bounds,
   2195     // pending implicit blob bounds implementation.
   2196     if (!blob->bounds().isEmpty() && paint.canComputeFastBounds()) {
   2197         SkRect storage;
   2198 
   2199         if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
   2200             return;
   2201         }
   2202     }
   2203 
   2204     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
   2205 
   2206     while (iter.next()) {
   2207         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
   2208         iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
   2209     }
   2210 
   2211     LOOPER_END
   2212 }
   2213 
   2214 // These will become non-virtual, so they always call the (virtual) onDraw... method
   2215 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
   2216                         const SkPaint& paint) {
   2217     this->onDrawText(text, byteLength, x, y, paint);
   2218 }
   2219 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
   2220                            const SkPaint& paint) {
   2221     this->onDrawPosText(text, byteLength, pos, paint);
   2222 }
   2223 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
   2224                             SkScalar constY, const SkPaint& paint) {
   2225     this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
   2226 }
   2227 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
   2228                               const SkMatrix* matrix, const SkPaint& paint) {
   2229     this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
   2230 }
   2231 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
   2232                             const SkPaint& paint) {
   2233     if (blob) {
   2234         this->onDrawTextBlob(blob, x, y, paint);
   2235     }
   2236 }
   2237 
   2238 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
   2239                             const SkPoint verts[], const SkPoint texs[],
   2240                             const SkColor colors[], SkXfermode* xmode,
   2241                             const uint16_t indices[], int indexCount,
   2242                             const SkPaint& paint) {
   2243     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
   2244 
   2245     while (iter.next()) {
   2246         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
   2247                                    colors, xmode, indices, indexCount,
   2248                                    looper.paint());
   2249     }
   2250 
   2251     LOOPER_END
   2252 }
   2253 
   2254 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
   2255                          const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
   2256     if (NULL == cubics) {
   2257         return;
   2258     }
   2259 
   2260     // Since a patch is always within the convex hull of the control points, we discard it when its
   2261     // bounding rectangle is completely outside the current clip.
   2262     SkRect bounds;
   2263     bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
   2264     if (this->quickReject(bounds)) {
   2265         return;
   2266     }
   2267 
   2268     this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
   2269 }
   2270 
   2271 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
   2272                            const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
   2273 
   2274     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
   2275 
   2276     while (iter.next()) {
   2277         iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
   2278     }
   2279 
   2280     LOOPER_END
   2281 }
   2282 
   2283 //////////////////////////////////////////////////////////////////////////////
   2284 // These methods are NOT virtual, and therefore must call back into virtual
   2285 // methods, rather than actually drawing themselves.
   2286 //////////////////////////////////////////////////////////////////////////////
   2287 
   2288 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
   2289                         SkXfermode::Mode mode) {
   2290     SkPaint paint;
   2291 
   2292     paint.setARGB(a, r, g, b);
   2293     if (SkXfermode::kSrcOver_Mode != mode) {
   2294         paint.setXfermodeMode(mode);
   2295     }
   2296     this->drawPaint(paint);
   2297 }
   2298 
   2299 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
   2300     SkPaint paint;
   2301 
   2302     paint.setColor(c);
   2303     if (SkXfermode::kSrcOver_Mode != mode) {
   2304         paint.setXfermodeMode(mode);
   2305     }
   2306     this->drawPaint(paint);
   2307 }
   2308 
   2309 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
   2310     SkPoint pt;
   2311 
   2312     pt.set(x, y);
   2313     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   2314 }
   2315 
   2316 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
   2317     SkPoint pt;
   2318     SkPaint paint;
   2319 
   2320     pt.set(x, y);
   2321     paint.setColor(color);
   2322     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   2323 }
   2324 
   2325 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
   2326                         const SkPaint& paint) {
   2327     SkPoint pts[2];
   2328 
   2329     pts[0].set(x0, y0);
   2330     pts[1].set(x1, y1);
   2331     this->drawPoints(kLines_PointMode, 2, pts, paint);
   2332 }
   2333 
   2334 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
   2335                               SkScalar right, SkScalar bottom,
   2336                               const SkPaint& paint) {
   2337     SkRect  r;
   2338 
   2339     r.set(left, top, right, bottom);
   2340     this->drawRect(r, paint);
   2341 }
   2342 
   2343 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
   2344                           const SkPaint& paint) {
   2345     if (radius < 0) {
   2346         radius = 0;
   2347     }
   2348 
   2349     SkRect  r;
   2350     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
   2351     this->drawOval(r, paint);
   2352 }
   2353 
   2354 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
   2355                              const SkPaint& paint) {
   2356     if (rx > 0 && ry > 0) {
   2357         if (paint.canComputeFastBounds()) {
   2358             SkRect storage;
   2359             if (this->quickReject(paint.computeFastBounds(r, &storage))) {
   2360                 return;
   2361             }
   2362         }
   2363         SkRRect rrect;
   2364         rrect.setRectXY(r, rx, ry);
   2365         this->drawRRect(rrect, paint);
   2366     } else {
   2367         this->drawRect(r, paint);
   2368     }
   2369 }
   2370 
   2371 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
   2372                        SkScalar sweepAngle, bool useCenter,
   2373                        const SkPaint& paint) {
   2374     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
   2375         this->drawOval(oval, paint);
   2376     } else {
   2377         SkPath  path;
   2378         if (useCenter) {
   2379             path.moveTo(oval.centerX(), oval.centerY());
   2380         }
   2381         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
   2382         if (useCenter) {
   2383             path.close();
   2384         }
   2385         this->drawPath(path, paint);
   2386     }
   2387 }
   2388 
   2389 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
   2390                                 const SkPath& path, SkScalar hOffset,
   2391                                 SkScalar vOffset, const SkPaint& paint) {
   2392     SkMatrix    matrix;
   2393 
   2394     matrix.setTranslate(hOffset, vOffset);
   2395     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
   2396 }
   2397 
   2398 ///////////////////////////////////////////////////////////////////////////////
   2399 void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
   2400     SkBaseDevice* device = this->getDevice();
   2401     if (device) {
   2402         device->EXPERIMENTAL_optimize(picture);
   2403     }
   2404 }
   2405 
   2406 void SkCanvas::drawPicture(const SkPicture* picture) {
   2407     if (picture) {
   2408         this->onDrawPicture(picture, NULL, NULL);
   2409     }
   2410 }
   2411 
   2412 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
   2413     if (picture) {
   2414         if (matrix && matrix->isIdentity()) {
   2415             matrix = NULL;
   2416         }
   2417         this->onDrawPicture(picture, matrix, paint);
   2418     }
   2419 }
   2420 
   2421 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
   2422                              const SkPaint* paint) {
   2423     SkBaseDevice* device = this->getTopDevice();
   2424     if (device) {
   2425         // Canvas has to first give the device the opportunity to render
   2426         // the picture itself.
   2427         if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
   2428             return; // the device has rendered the entire picture
   2429         }
   2430     }
   2431 
   2432     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
   2433 
   2434     picture->playback(this);
   2435 }
   2436 
   2437 ///////////////////////////////////////////////////////////////////////////////
   2438 ///////////////////////////////////////////////////////////////////////////////
   2439 
   2440 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
   2441     SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
   2442 
   2443     SkASSERT(canvas);
   2444 
   2445     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
   2446     fDone = !fImpl->next();
   2447 }
   2448 
   2449 SkCanvas::LayerIter::~LayerIter() {
   2450     fImpl->~SkDrawIter();
   2451 }
   2452 
   2453 void SkCanvas::LayerIter::next() {
   2454     fDone = !fImpl->next();
   2455 }
   2456 
   2457 SkBaseDevice* SkCanvas::LayerIter::device() const {
   2458     return fImpl->getDevice();
   2459 }
   2460 
   2461 const SkMatrix& SkCanvas::LayerIter::matrix() const {
   2462     return fImpl->getMatrix();
   2463 }
   2464 
   2465 const SkPaint& SkCanvas::LayerIter::paint() const {
   2466     const SkPaint* paint = fImpl->getPaint();
   2467     if (NULL == paint) {
   2468         paint = &fDefaultPaint;
   2469     }
   2470     return *paint;
   2471 }
   2472 
   2473 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
   2474 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
   2475 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
   2476 
   2477 ///////////////////////////////////////////////////////////////////////////////
   2478 
   2479 SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
   2480 
   2481 ///////////////////////////////////////////////////////////////////////////////
   2482 
   2483 static bool supported_for_raster_canvas(const SkImageInfo& info) {
   2484     switch (info.alphaType()) {
   2485         case kPremul_SkAlphaType:
   2486         case kOpaque_SkAlphaType:
   2487             break;
   2488         default:
   2489             return false;
   2490     }
   2491 
   2492     switch (info.colorType()) {
   2493         case kAlpha_8_SkColorType:
   2494         case kRGB_565_SkColorType:
   2495         case kN32_SkColorType:
   2496             break;
   2497         default:
   2498             return false;
   2499     }
   2500 
   2501     return true;
   2502 }
   2503 
   2504 SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
   2505     if (!supported_for_raster_canvas(info)) {
   2506         return NULL;
   2507     }
   2508 
   2509     SkBitmap bitmap;
   2510     if (!bitmap.tryAllocPixels(info)) {
   2511         return NULL;
   2512     }
   2513 
   2514     // should this functionality be moved into allocPixels()?
   2515     if (!bitmap.info().isOpaque()) {
   2516         bitmap.eraseColor(0);
   2517     }
   2518     return SkNEW_ARGS(SkCanvas, (bitmap));
   2519 }
   2520 
   2521 SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
   2522     if (!supported_for_raster_canvas(info)) {
   2523         return NULL;
   2524     }
   2525 
   2526     SkBitmap bitmap;
   2527     if (!bitmap.installPixels(info, pixels, rowBytes)) {
   2528         return NULL;
   2529     }
   2530     return SkNEW_ARGS(SkCanvas, (bitmap));
   2531 }
   2532 
   2533 ///////////////////////////////////////////////////////////////////////////////
   2534 
   2535 SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
   2536                                                  const SkPaint* paint, const SkRect& bounds)
   2537     : fCanvas(canvas)
   2538     , fSaveCount(canvas->getSaveCount())
   2539 {
   2540     if (paint) {
   2541         SkRect newBounds = bounds;
   2542         if (matrix) {
   2543             matrix->mapRect(&newBounds);
   2544         }
   2545         canvas->saveLayer(&newBounds, paint);
   2546     } else if (matrix) {
   2547         canvas->save();
   2548     }
   2549 
   2550     if (matrix) {
   2551         canvas->concat(*matrix);
   2552     }
   2553 }
   2554 
   2555 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
   2556     fCanvas->restoreToCount(fSaveCount);
   2557 }
   2558