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