Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006-2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SkCanvas.h"
     18 #include "SkBounder.h"
     19 #include "SkDevice.h"
     20 #include "SkDraw.h"
     21 #include "SkDrawFilter.h"
     22 #include "SkDrawLooper.h"
     23 #include "SkPicture.h"
     24 #include "SkScalarCompare.h"
     25 #include "SkShape.h"
     26 #include "SkTemplates.h"
     27 #include "SkUtils.h"
     28 #include <new>
     29 
     30 //#define SK_TRACE_SAVERESTORE
     31 
     32 #ifdef SK_TRACE_SAVERESTORE
     33     static int gLayerCounter;
     34     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
     35     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
     36 
     37     static int gRecCounter;
     38     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
     39     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
     40 
     41     static int gCanvasCounter;
     42     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
     43     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
     44 #else
     45     #define inc_layer()
     46     #define dec_layer()
     47     #define inc_rec()
     48     #define dec_rec()
     49     #define inc_canvas()
     50     #define dec_canvas()
     51 #endif
     52 
     53 ///////////////////////////////////////////////////////////////////////////////
     54 // Helpers for computing fast bounds for quickReject tests
     55 
     56 static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) {
     57     return paint != NULL && paint->isAntiAlias() ?
     58             SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType;
     59 }
     60 
     61 ///////////////////////////////////////////////////////////////////////////////
     62 
     63 /*  This is the record we keep for each SkDevice that the user installs.
     64     The clip/matrix/proc are fields that reflect the top of the save/restore
     65     stack. Whenever the canvas changes, it marks a dirty flag, and then before
     66     these are used (assuming we're not on a layer) we rebuild these cache
     67     values: they reflect the top of the save stack, but translated and clipped
     68     by the device's XY offset and bitmap-bounds.
     69 */
     70 struct DeviceCM {
     71     DeviceCM*           fNext;
     72     SkDevice*           fDevice;
     73     SkRegion            fClip;
     74     const SkMatrix*     fMatrix;
     75 	SkPaint*			fPaint;	// may be null (in the future)
     76     int16_t             fX, fY; // relative to base matrix/clip
     77 
     78 	DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
     79             : fNext(NULL) {
     80         if (NULL != device) {
     81             device->ref();
     82             device->lockPixels();
     83         }
     84         fDevice = device;
     85         fX = SkToS16(x);
     86         fY = SkToS16(y);
     87         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
     88 	}
     89 
     90 	~DeviceCM() {
     91         if (NULL != fDevice) {
     92             fDevice->unlockPixels();
     93             fDevice->unref();
     94         }
     95 		SkDELETE(fPaint);
     96 	}
     97 
     98     void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip,
     99                   SkRegion* updateClip) {
    100         int x = fX;
    101         int y = fY;
    102         int width = fDevice->width();
    103         int height = fDevice->height();
    104 
    105         if ((x | y) == 0) {
    106             fMatrix = &totalMatrix;
    107             fClip = totalClip;
    108         } else {
    109             fMatrixStorage = totalMatrix;
    110             fMatrixStorage.postTranslate(SkIntToScalar(-x),
    111                                          SkIntToScalar(-y));
    112             fMatrix = &fMatrixStorage;
    113 
    114             totalClip.translate(-x, -y, &fClip);
    115         }
    116 
    117         fClip.op(0, 0, width, height, SkRegion::kIntersect_Op);
    118 
    119         // intersect clip, but don't translate it (yet)
    120 
    121         if (updateClip) {
    122             updateClip->op(x, y, x + width, y + height,
    123                            SkRegion::kDifference_Op);
    124         }
    125 
    126         fDevice->setMatrixClip(*fMatrix, fClip);
    127 
    128 #ifdef SK_DEBUG
    129         if (!fClip.isEmpty()) {
    130             SkIRect deviceR;
    131             deviceR.set(0, 0, width, height);
    132             SkASSERT(deviceR.contains(fClip.getBounds()));
    133         }
    134 #endif
    135     }
    136 
    137     void translateClip() {
    138         if (fX | fY) {
    139             fClip.translate(fX, fY);
    140         }
    141     }
    142 
    143 private:
    144     SkMatrix    fMatrixStorage;
    145 };
    146 
    147 /*  This is the record we keep for each save/restore level in the stack.
    148     Since a level optionally copies the matrix and/or stack, we have pointers
    149     for these fields. If the value is copied for this level, the copy is
    150     stored in the ...Storage field, and the pointer points to that. If the
    151     value is not copied for this level, we ignore ...Storage, and just point
    152     at the corresponding value in the previous level in the stack.
    153 */
    154 class SkCanvas::MCRec {
    155 public:
    156     MCRec*          fNext;
    157     SkMatrix*       fMatrix;    // points to either fMatrixStorage or prev MCRec
    158     SkRegion*       fRegion;    // points to either fRegionStorage or prev MCRec
    159     SkDrawFilter*   fFilter;    // the current filter (or null)
    160 
    161     DeviceCM*   fLayer;
    162     /*  If there are any layers in the stack, this points to the top-most
    163         one that is at or below this level in the stack (so we know what
    164         bitmap/device to draw into from this level. This value is NOT
    165         reference counted, since the real owner is either our fLayer field,
    166         or a previous one in a lower level.)
    167     */
    168     DeviceCM*	fTopLayer;
    169 
    170     MCRec(const MCRec* prev, int flags) {
    171         if (NULL != prev) {
    172             if (flags & SkCanvas::kMatrix_SaveFlag) {
    173                 fMatrixStorage = *prev->fMatrix;
    174                 fMatrix = &fMatrixStorage;
    175             } else {
    176                 fMatrix = prev->fMatrix;
    177             }
    178 
    179             if (flags & SkCanvas::kClip_SaveFlag) {
    180                 fRegionStorage = *prev->fRegion;
    181                 fRegion = &fRegionStorage;
    182             } else {
    183                 fRegion = prev->fRegion;
    184             }
    185 
    186             fFilter = prev->fFilter;
    187             fFilter->safeRef();
    188 
    189             fTopLayer = prev->fTopLayer;
    190         } else {   // no prev
    191             fMatrixStorage.reset();
    192 
    193             fMatrix     = &fMatrixStorage;
    194             fRegion     = &fRegionStorage;
    195             fFilter     = NULL;
    196             fTopLayer   = NULL;
    197         }
    198         fLayer = NULL;
    199 
    200         // don't bother initializing fNext
    201         inc_rec();
    202     }
    203     ~MCRec() {
    204         fFilter->safeUnref();
    205         SkDELETE(fLayer);
    206         dec_rec();
    207     }
    208 
    209 private:
    210     SkMatrix    fMatrixStorage;
    211     SkRegion    fRegionStorage;
    212 };
    213 
    214 class SkDrawIter : public SkDraw {
    215 public:
    216     SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
    217         fCanvas = canvas;
    218         canvas->updateDeviceCMCache();
    219 
    220         fBounder = canvas->getBounder();
    221         fCurrLayer = canvas->fMCRec->fTopLayer;
    222         fSkipEmptyClips = skipEmptyClips;
    223     }
    224 
    225     bool next() {
    226         // skip over recs with empty clips
    227         if (fSkipEmptyClips) {
    228             while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
    229                 fCurrLayer = fCurrLayer->fNext;
    230             }
    231         }
    232 
    233         if (NULL != fCurrLayer) {
    234             const DeviceCM* rec = fCurrLayer;
    235 
    236             fMatrix = rec->fMatrix;
    237             fClip   = &rec->fClip;
    238             fDevice = rec->fDevice;
    239             fBitmap = &fDevice->accessBitmap(true);
    240             fLayerX = rec->fX;
    241             fLayerY = rec->fY;
    242             fPaint  = rec->fPaint;
    243             SkDEBUGCODE(this->validate();)
    244 
    245             fCurrLayer = rec->fNext;
    246             if (fBounder) {
    247                 fBounder->setClip(fClip);
    248             }
    249 
    250             // fCurrLayer may be NULL now
    251 
    252             fCanvas->prepareForDeviceDraw(fDevice);
    253             return true;
    254         }
    255         return false;
    256     }
    257 
    258     int getX() const { return fLayerX; }
    259     int getY() const { return fLayerY; }
    260     SkDevice* getDevice() const { return fDevice; }
    261     const SkMatrix& getMatrix() const { return *fMatrix; }
    262     const SkRegion& getClip() const { return *fClip; }
    263     const SkPaint* getPaint() const { return fPaint; }
    264 private:
    265     SkCanvas*       fCanvas;
    266     const DeviceCM* fCurrLayer;
    267     const SkPaint*  fPaint;     // May be null.
    268     int             fLayerX;
    269     int             fLayerY;
    270     SkBool8         fSkipEmptyClips;
    271 
    272     typedef SkDraw INHERITED;
    273 };
    274 
    275 /////////////////////////////////////////////////////////////////////////////
    276 
    277 class AutoDrawLooper {
    278 public:
    279     AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
    280             : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
    281         if ((fLooper = paint.getLooper()) != NULL) {
    282             fLooper->init(canvas, (SkPaint*)&paint);
    283         } else {
    284             fOnce = true;
    285         }
    286         fFilter = canvas->getDrawFilter();
    287         fNeedFilterRestore = false;
    288     }
    289 
    290     ~AutoDrawLooper() {
    291         if (fNeedFilterRestore) {
    292             SkASSERT(fFilter);
    293             fFilter->restore(fCanvas, fPaint, fType);
    294         }
    295         if (NULL != fLooper) {
    296             fLooper->restore();
    297         }
    298     }
    299 
    300     bool next() {
    301         SkDrawFilter* filter = fFilter;
    302 
    303         // if we drew earlier with a filter, then we need to restore first
    304         if (fNeedFilterRestore) {
    305             SkASSERT(filter);
    306             filter->restore(fCanvas, fPaint, fType);
    307             fNeedFilterRestore = false;
    308         }
    309 
    310         bool result;
    311 
    312         if (NULL != fLooper) {
    313             result = fLooper->next();
    314         } else {
    315             result = fOnce;
    316             fOnce = false;
    317         }
    318 
    319         // if we're gonna draw, give the filter a chance to do its work
    320         if (result && NULL != filter) {
    321             fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
    322                                                          fType);
    323         }
    324         return result;
    325     }
    326 
    327 private:
    328     SkDrawLooper*   fLooper;
    329     SkDrawFilter*   fFilter;
    330     SkCanvas*       fCanvas;
    331     SkPaint*        fPaint;
    332     SkDrawFilter::Type  fType;
    333     bool            fOnce;
    334     bool            fNeedFilterRestore;
    335 
    336 };
    337 
    338 /*  Stack helper for managing a SkBounder. In the destructor, if we were
    339     given a bounder, we call its commit() method, signifying that we are
    340     done accumulating bounds for that draw.
    341 */
    342 class SkAutoBounderCommit {
    343 public:
    344     SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
    345     ~SkAutoBounderCommit() {
    346         if (NULL != fBounder) {
    347             fBounder->commit();
    348         }
    349     }
    350 private:
    351     SkBounder*  fBounder;
    352 };
    353 
    354 #include "SkColorPriv.h"
    355 
    356 class AutoValidator {
    357 public:
    358     AutoValidator(SkDevice* device) : fDevice(device) {}
    359     ~AutoValidator() {
    360 #ifdef SK_DEBUG
    361         const SkBitmap& bm = fDevice->accessBitmap(false);
    362         if (bm.config() == SkBitmap::kARGB_4444_Config) {
    363             for (int y = 0; y < bm.height(); y++) {
    364                 const SkPMColor16* p = bm.getAddr16(0, y);
    365                 for (int x = 0; x < bm.width(); x++) {
    366                     SkPMColor16 c = p[x];
    367                     SkPMColor16Assert(c);
    368                 }
    369             }
    370         }
    371 #endif
    372     }
    373 private:
    374     SkDevice* fDevice;
    375 };
    376 
    377 ////////// macros to place around the internal draw calls //////////////////
    378 
    379 #define ITER_BEGIN(paint, type)                                     \
    380 /*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
    381     AutoDrawLooper  looper(this, paint, type);                      \
    382     while (looper.next()) {                                         \
    383         SkAutoBounderCommit ac(fBounder);                           \
    384         SkDrawIter          iter(this);
    385 
    386 #define ITER_END    }
    387 
    388 ////////////////////////////////////////////////////////////////////////////
    389 
    390 SkDevice* SkCanvas::init(SkDevice* device) {
    391     fBounder = NULL;
    392     fLocalBoundsCompareTypeDirty = true;
    393     fLocalBoundsCompareTypeDirtyBW = true;
    394     fLastDeviceToGainFocus = NULL;
    395     fDeviceCMDirty = false;
    396 
    397     fMCRec = (MCRec*)fMCStack.push_back();
    398     new (fMCRec) MCRec(NULL, 0);
    399 
    400     fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
    401     fMCRec->fTopLayer = fMCRec->fLayer;
    402     fMCRec->fNext = NULL;
    403 
    404     return this->setDevice(device);
    405 }
    406 
    407 SkCanvas::SkCanvas(SkDevice* device)
    408         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
    409     inc_canvas();
    410 
    411     this->init(device);
    412 }
    413 
    414 SkCanvas::SkCanvas(const SkBitmap& bitmap)
    415         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
    416     inc_canvas();
    417 
    418     this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
    419 }
    420 
    421 SkCanvas::~SkCanvas() {
    422     // free up the contents of our deque
    423     this->restoreToCount(1);    // restore everything but the last
    424     this->internalRestore();    // restore the last, since we're going away
    425 
    426     fBounder->safeUnref();
    427 
    428     dec_canvas();
    429 }
    430 
    431 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
    432     SkRefCnt_SafeAssign(fBounder, bounder);
    433     return bounder;
    434 }
    435 
    436 SkDrawFilter* SkCanvas::getDrawFilter() const {
    437     return fMCRec->fFilter;
    438 }
    439 
    440 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
    441     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
    442     return filter;
    443 }
    444 
    445 ///////////////////////////////////////////////////////////////////////////////
    446 
    447 SkDevice* SkCanvas::getDevice() const {
    448     // return root device
    449     SkDeque::Iter   iter(fMCStack);
    450     MCRec*          rec = (MCRec*)iter.next();
    451     SkASSERT(rec && rec->fLayer);
    452     return rec->fLayer->fDevice;
    453 }
    454 
    455 SkDevice* SkCanvas::setDevice(SkDevice* device) {
    456     // return root device
    457     SkDeque::Iter   iter(fMCStack);
    458     MCRec*          rec = (MCRec*)iter.next();
    459     SkASSERT(rec && rec->fLayer);
    460     SkDevice*       rootDevice = rec->fLayer->fDevice;
    461 
    462     if (rootDevice == device) {
    463         return device;
    464     }
    465 
    466     /* Notify the devices that they are going in/out of scope, so they can do
    467        things like lock/unlock their pixels, etc.
    468     */
    469     if (device) {
    470         device->lockPixels();
    471     }
    472     if (rootDevice) {
    473         rootDevice->unlockPixels();
    474     }
    475 
    476     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
    477     rootDevice = device;
    478 
    479     fDeviceCMDirty = true;
    480 
    481     /*  Now we update our initial region to have the bounds of the new device,
    482         and then intersect all of the clips in our stack with these bounds,
    483         to ensure that we can't draw outside of the device's bounds (and trash
    484                                                                      memory).
    485 
    486     NOTE: this is only a partial-fix, since if the new device is larger than
    487         the previous one, we don't know how to "enlarge" the clips in our stack,
    488         so drawing may be artificially restricted. Without keeping a history of
    489         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
    490         reconstruct the correct clips, so this approximation will have to do.
    491         The caller really needs to restore() back to the base if they want to
    492         accurately take advantage of the new device bounds.
    493     */
    494 
    495     if (NULL == device) {
    496         rec->fRegion->setEmpty();
    497         while ((rec = (MCRec*)iter.next()) != NULL) {
    498             (void)rec->fRegion->setEmpty();
    499         }
    500     } else {
    501         // compute our total bounds for all devices
    502         SkIRect bounds;
    503 
    504         bounds.set(0, 0, device->width(), device->height());
    505 
    506         // now jam our 1st clip to be bounds, and intersect the rest with that
    507         rec->fRegion->setRect(bounds);
    508         while ((rec = (MCRec*)iter.next()) != NULL) {
    509             (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op);
    510         }
    511     }
    512     return device;
    513 }
    514 
    515 SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
    516     SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
    517     device->unref();
    518     return device;
    519 }
    520 
    521 //////////////////////////////////////////////////////////////////////////////
    522 
    523 bool SkCanvas::getViewport(SkIPoint* size) const {
    524     return false;
    525 }
    526 
    527 bool SkCanvas::setViewport(int width, int height) {
    528     return false;
    529 }
    530 
    531 void SkCanvas::updateDeviceCMCache() {
    532     if (fDeviceCMDirty) {
    533         const SkMatrix& totalMatrix = this->getTotalMatrix();
    534         const SkRegion& totalClip = this->getTotalClip();
    535         DeviceCM*       layer = fMCRec->fTopLayer;
    536 
    537         if (NULL == layer->fNext) {   // only one layer
    538             layer->updateMC(totalMatrix, totalClip, NULL);
    539         } else {
    540             SkRegion clip;
    541             clip = totalClip;  // make a copy
    542             do {
    543                 layer->updateMC(totalMatrix, clip, &clip);
    544             } while ((layer = layer->fNext) != NULL);
    545         }
    546         fDeviceCMDirty = false;
    547     }
    548 }
    549 
    550 void SkCanvas::prepareForDeviceDraw(SkDevice* device) {
    551     SkASSERT(device);
    552     if (fLastDeviceToGainFocus != device) {
    553         device->gainFocus(this);
    554         fLastDeviceToGainFocus = device;
    555     }
    556 }
    557 
    558 ///////////////////////////////////////////////////////////////////////////////
    559 
    560 int SkCanvas::internalSave(SaveFlags flags) {
    561     int saveCount = this->getSaveCount(); // record this before the actual save
    562 
    563     MCRec* newTop = (MCRec*)fMCStack.push_back();
    564     new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
    565 
    566     newTop->fNext = fMCRec;
    567     fMCRec = newTop;
    568 
    569     return saveCount;
    570 }
    571 
    572 int SkCanvas::save(SaveFlags flags) {
    573     // call shared impl
    574     return this->internalSave(flags);
    575 }
    576 
    577 #define C32MASK (1 << SkBitmap::kARGB_8888_Config)
    578 #define C16MASK (1 << SkBitmap::kRGB_565_Config)
    579 #define C8MASK  (1 << SkBitmap::kA8_Config)
    580 
    581 static SkBitmap::Config resolve_config(SkCanvas* canvas,
    582                                        const SkIRect& bounds,
    583                                        SkCanvas::SaveFlags flags,
    584                                        bool* isOpaque) {
    585     *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
    586 
    587 #if 0
    588     // loop through and union all the configs we may draw into
    589     uint32_t configMask = 0;
    590     for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
    591     {
    592         SkDevice* device = canvas->getLayerDevice(i);
    593         if (device->intersects(bounds))
    594             configMask |= 1 << device->config();
    595     }
    596 
    597     // if the caller wants alpha or fullcolor, we can't return 565
    598     if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
    599                  SkCanvas::kHasAlphaLayer_SaveFlag))
    600         configMask &= ~C16MASK;
    601 
    602     switch (configMask) {
    603     case C8MASK:    // if we only have A8, return that
    604         return SkBitmap::kA8_Config;
    605 
    606     case C16MASK:   // if we only have 565, return that
    607         return SkBitmap::kRGB_565_Config;
    608 
    609     default:
    610         return SkBitmap::kARGB_8888_Config; // default answer
    611     }
    612 #else
    613     return SkBitmap::kARGB_8888_Config; // default answer
    614 #endif
    615 }
    616 
    617 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
    618     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
    619 }
    620 
    621 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
    622                         SaveFlags flags) {
    623     // do this before we create the layer. We don't call the public save() since
    624     // that would invoke a possibly overridden virtual
    625     int count = this->internalSave(flags);
    626 
    627     fDeviceCMDirty = true;
    628 
    629     SkIRect         ir;
    630     const SkIRect&  clipBounds = this->getTotalClip().getBounds();
    631 
    632     if (NULL != bounds) {
    633         SkRect r;
    634 
    635         this->getTotalMatrix().mapRect(&r, *bounds);
    636         r.roundOut(&ir);
    637         // early exit if the layer's bounds are clipped out
    638         if (!ir.intersect(clipBounds)) {
    639             if (bounds_affects_clip(flags))
    640                 fMCRec->fRegion->setEmpty();
    641             return count;
    642         }
    643     } else {    // no user bounds, so just use the clip
    644         ir = clipBounds;
    645     }
    646 
    647     // early exit if the clip is now empty
    648     if (bounds_affects_clip(flags) &&
    649         !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) {
    650         return count;
    651     }
    652 
    653     bool isOpaque;
    654     SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
    655 
    656     SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
    657                                           isOpaque, true);
    658     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
    659     device->unref();
    660 
    661     layer->fNext = fMCRec->fTopLayer;
    662     fMCRec->fLayer = layer;
    663     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
    664 
    665     return count;
    666 }
    667 
    668 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
    669                              SaveFlags flags) {
    670     if (0xFF == alpha) {
    671         return this->saveLayer(bounds, NULL, flags);
    672     } else {
    673         SkPaint tmpPaint;
    674         tmpPaint.setAlpha(alpha);
    675         return this->saveLayer(bounds, &tmpPaint, flags);
    676     }
    677 }
    678 
    679 void SkCanvas::restore() {
    680     // check for underflow
    681     if (fMCStack.count() > 1) {
    682         this->internalRestore();
    683     }
    684 }
    685 
    686 void SkCanvas::internalRestore() {
    687     SkASSERT(fMCStack.count() != 0);
    688 
    689     fDeviceCMDirty = true;
    690     fLocalBoundsCompareTypeDirty = true;
    691     fLocalBoundsCompareTypeDirtyBW = true;
    692 
    693 	// reserve our layer (if any)
    694     DeviceCM* layer = fMCRec->fLayer;   // may be null
    695     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
    696     fMCRec->fLayer = NULL;
    697 
    698     // now do the normal restore()
    699     fMCRec->~MCRec();       // balanced in save()
    700     fMCStack.pop_back();
    701     fMCRec = (MCRec*)fMCStack.back();
    702 
    703     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
    704         since if we're being recorded, we don't want to record this (the
    705         recorder will have already recorded the restore).
    706     */
    707     if (NULL != layer) {
    708         if (layer->fNext) {
    709             this->drawDevice(layer->fDevice, layer->fX, layer->fY,
    710                              layer->fPaint);
    711             // reset this, since drawDevice will have set it to true
    712             fDeviceCMDirty = true;
    713         }
    714         SkDELETE(layer);
    715 	}
    716 }
    717 
    718 int SkCanvas::getSaveCount() const {
    719     return fMCStack.count();
    720 }
    721 
    722 void SkCanvas::restoreToCount(int count) {
    723     // sanity check
    724     if (count < 1) {
    725         count = 1;
    726     }
    727     while (fMCStack.count() > count) {
    728         this->restore();
    729     }
    730 }
    731 
    732 /////////////////////////////////////////////////////////////////////////////
    733 
    734 // can't draw it if its empty, or its too big for a fixed-point width or height
    735 static bool reject_bitmap(const SkBitmap& bitmap) {
    736     return  bitmap.width() <= 0 || bitmap.height() <= 0 ||
    737             bitmap.width() > 32767 || bitmap.height() > 32767;
    738 }
    739 
    740 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
    741                                 const SkMatrix& matrix, const SkPaint* paint) {
    742     if (reject_bitmap(bitmap)) {
    743         return;
    744     }
    745 
    746     if (NULL == paint) {
    747         SkPaint tmpPaint;
    748         this->commonDrawBitmap(bitmap, matrix, tmpPaint);
    749     } else {
    750         this->commonDrawBitmap(bitmap, matrix, *paint);
    751     }
    752 }
    753 
    754 void SkCanvas::drawDevice(SkDevice* device, int x, int y,
    755                           const SkPaint* paint) {
    756     SkPaint tmp;
    757     if (NULL == paint) {
    758         tmp.setDither(true);
    759         paint = &tmp;
    760     }
    761 
    762     ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
    763     while (iter.next()) {
    764         iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
    765                                  *paint);
    766     }
    767     ITER_END
    768 }
    769 
    770 /////////////////////////////////////////////////////////////////////////////
    771 
    772 bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
    773     fDeviceCMDirty = true;
    774     fLocalBoundsCompareTypeDirty = true;
    775     fLocalBoundsCompareTypeDirtyBW = true;
    776     return fMCRec->fMatrix->preTranslate(dx, dy);
    777 }
    778 
    779 bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
    780     fDeviceCMDirty = true;
    781     fLocalBoundsCompareTypeDirty = true;
    782     fLocalBoundsCompareTypeDirtyBW = true;
    783     return fMCRec->fMatrix->preScale(sx, sy);
    784 }
    785 
    786 bool SkCanvas::rotate(SkScalar degrees) {
    787     fDeviceCMDirty = true;
    788     fLocalBoundsCompareTypeDirty = true;
    789     fLocalBoundsCompareTypeDirtyBW = true;
    790     return fMCRec->fMatrix->preRotate(degrees);
    791 }
    792 
    793 bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
    794     fDeviceCMDirty = true;
    795     fLocalBoundsCompareTypeDirty = true;
    796     fLocalBoundsCompareTypeDirtyBW = true;
    797     return fMCRec->fMatrix->preSkew(sx, sy);
    798 }
    799 
    800 bool SkCanvas::concat(const SkMatrix& matrix) {
    801     fDeviceCMDirty = true;
    802     fLocalBoundsCompareTypeDirty = true;
    803     fLocalBoundsCompareTypeDirtyBW = true;
    804     return fMCRec->fMatrix->preConcat(matrix);
    805 }
    806 
    807 void SkCanvas::setMatrix(const SkMatrix& matrix) {
    808     fDeviceCMDirty = true;
    809     fLocalBoundsCompareTypeDirty = true;
    810     fLocalBoundsCompareTypeDirtyBW = true;
    811     *fMCRec->fMatrix = matrix;
    812 }
    813 
    814 // this is not virtual, so it must call a virtual method so that subclasses
    815 // will see its action
    816 void SkCanvas::resetMatrix() {
    817     SkMatrix matrix;
    818 
    819     matrix.reset();
    820     this->setMatrix(matrix);
    821 }
    822 
    823 //////////////////////////////////////////////////////////////////////////////
    824 
    825 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
    826     fDeviceCMDirty = true;
    827     fLocalBoundsCompareTypeDirty = true;
    828     fLocalBoundsCompareTypeDirtyBW = true;
    829 
    830     if (fMCRec->fMatrix->rectStaysRect()) {
    831         // for these simpler matrices, we can stay a rect ever after applying
    832         // the matrix. This means we don't have to a) make a path, and b) tell
    833         // the region code to scan-convert the path, only to discover that it
    834         // is really just a rect.
    835         SkRect      r;
    836         SkIRect     ir;
    837 
    838         fMCRec->fMatrix->mapRect(&r, rect);
    839         r.round(&ir);
    840         return fMCRec->fRegion->op(ir, op);
    841     } else {
    842         // since we're rotate or some such thing, we convert the rect to a path
    843         // and clip against that, since it can handle any matrix. However, to
    844         // avoid recursion in the case where we are subclassed (e.g. Pictures)
    845         // we explicitly call "our" version of clipPath.
    846         SkPath  path;
    847 
    848         path.addRect(rect);
    849         return this->SkCanvas::clipPath(path, op);
    850     }
    851 }
    852 
    853 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
    854     fDeviceCMDirty = true;
    855     fLocalBoundsCompareTypeDirty = true;
    856     fLocalBoundsCompareTypeDirtyBW = true;
    857 
    858     SkPath devPath;
    859     path.transform(*fMCRec->fMatrix, &devPath);
    860 
    861     if (SkRegion::kIntersect_Op == op) {
    862         return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion);
    863     } else {
    864         SkRegion base;
    865         const SkBitmap& bm = this->getDevice()->accessBitmap(false);
    866         base.setRect(0, 0, bm.width(), bm.height());
    867 
    868         if (SkRegion::kReplace_Op == op) {
    869             return fMCRec->fRegion->setPath(devPath, base);
    870         } else {
    871             SkRegion rgn;
    872             rgn.setPath(devPath, base);
    873             return fMCRec->fRegion->op(rgn, op);
    874         }
    875     }
    876 }
    877 
    878 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
    879     fDeviceCMDirty = true;
    880     fLocalBoundsCompareTypeDirty = true;
    881     fLocalBoundsCompareTypeDirtyBW = true;
    882 
    883     return fMCRec->fRegion->op(rgn, op);
    884 }
    885 
    886 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
    887     SkRect r;
    888     SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :
    889             fLocalBoundsCompareTypeBW;
    890 
    891     if (!this->getClipBounds(&r, et)) {
    892         rCompare.setEmpty();
    893     } else {
    894         rCompare.set(SkScalarToCompareType(r.fLeft),
    895                      SkScalarToCompareType(r.fTop),
    896                      SkScalarToCompareType(r.fRight),
    897                      SkScalarToCompareType(r.fBottom));
    898     }
    899 }
    900 
    901 /*  current impl ignores edgetype, and relies on
    902     getLocalClipBoundsCompareType(), which always returns a value assuming
    903     antialiasing (worst case)
    904  */
    905 bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
    906     if (fMCRec->fRegion->isEmpty()) {
    907         return true;
    908     }
    909 
    910     if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) {
    911         SkRect dst;
    912         fMCRec->fMatrix->mapRect(&dst, rect);
    913         SkIRect idst;
    914         dst.roundOut(&idst);
    915         return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds());
    916     } else {
    917         const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et);
    918 
    919         // for speed, do the most likely reject compares first
    920         SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
    921         SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
    922         if (userT >= clipR.fBottom || userB <= clipR.fTop) {
    923             return true;
    924         }
    925         SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
    926         SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
    927         if (userL >= clipR.fRight || userR <= clipR.fLeft) {
    928             return true;
    929         }
    930         return false;
    931     }
    932 }
    933 
    934 bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
    935     return path.isEmpty() || this->quickReject(path.getBounds(), et);
    936 }
    937 
    938 bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
    939     /*  current impl ignores edgetype, and relies on
    940         getLocalClipBoundsCompareType(), which always returns a value assuming
    941         antialiasing (worst case)
    942      */
    943 
    944     if (fMCRec->fRegion->isEmpty()) {
    945         return true;
    946     }
    947 
    948     SkScalarCompareType userT = SkScalarToCompareType(top);
    949     SkScalarCompareType userB = SkScalarToCompareType(bottom);
    950 
    951     // check for invalid user Y coordinates (i.e. empty)
    952     // reed: why do we need to do this check, since it slows us down?
    953     if (userT >= userB) {
    954         return true;
    955     }
    956 
    957     // check if we are above or below the local clip bounds
    958     const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
    959     return userT >= clipR.fBottom || userB <= clipR.fTop;
    960 }
    961 
    962 bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
    963     const SkRegion& clip = *fMCRec->fRegion;
    964     if (clip.isEmpty()) {
    965         if (bounds) {
    966             bounds->setEmpty();
    967         }
    968         return false;
    969     }
    970 
    971     SkMatrix inverse;
    972     // if we can't invert the CTM, we can't return local clip bounds
    973     if (!fMCRec->fMatrix->invert(&inverse)) {
    974         if (bounds) {
    975             bounds->setEmpty();
    976         }
    977         return false;
    978     }
    979 
    980     if (NULL != bounds) {
    981         SkRect   r;
    982         // get the clip's bounds
    983         const SkIRect& ibounds = clip.getBounds();
    984         // adjust it outwards if we are antialiasing
    985         int inset = (kAA_EdgeType == et);
    986         r.iset(ibounds.fLeft - inset,  ibounds.fTop - inset,
    987                ibounds.fRight + inset, ibounds.fBottom + inset);
    988 
    989         // invert into local coordinates
    990         inverse.mapRect(bounds, r);
    991     }
    992     return true;
    993 }
    994 
    995 const SkMatrix& SkCanvas::getTotalMatrix() const {
    996     return *fMCRec->fMatrix;
    997 }
    998 
    999 const SkRegion& SkCanvas::getTotalClip() const {
   1000     return *fMCRec->fRegion;
   1001 }
   1002 
   1003 ///////////////////////////////////////////////////////////////////////////////
   1004 
   1005 SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
   1006                                  int height, bool isOpaque, bool isForLayer) {
   1007     SkBitmap bitmap;
   1008 
   1009     bitmap.setConfig(config, width, height);
   1010     bitmap.setIsOpaque(isOpaque);
   1011 
   1012     // should this happen in the device subclass?
   1013     bitmap.allocPixels();
   1014     if (!bitmap.isOpaque()) {
   1015         bitmap.eraseARGB(0, 0, 0, 0);
   1016     }
   1017 
   1018     return SkNEW_ARGS(SkDevice, (bitmap));
   1019 }
   1020 
   1021 //////////////////////////////////////////////////////////////////////////////
   1022 //  These are the virtual drawing methods
   1023 //////////////////////////////////////////////////////////////////////////////
   1024 
   1025 void SkCanvas::drawPaint(const SkPaint& paint) {
   1026     ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
   1027 
   1028     while (iter.next()) {
   1029         iter.fDevice->drawPaint(iter, paint);
   1030     }
   1031 
   1032     ITER_END
   1033 }
   1034 
   1035 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
   1036                           const SkPaint& paint) {
   1037     if ((long)count <= 0) {
   1038         return;
   1039     }
   1040 
   1041     SkASSERT(pts != NULL);
   1042 
   1043     ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
   1044 
   1045     while (iter.next()) {
   1046         iter.fDevice->drawPoints(iter, mode, count, pts, paint);
   1047     }
   1048 
   1049     ITER_END
   1050 }
   1051 
   1052 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
   1053     if (paint.canComputeFastBounds()) {
   1054         SkRect storage;
   1055         if (this->quickReject(paint.computeFastBounds(r, &storage),
   1056                               paint2EdgeType(&paint))) {
   1057             return;
   1058         }
   1059     }
   1060 
   1061     ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
   1062 
   1063     while (iter.next()) {
   1064         iter.fDevice->drawRect(iter, r, paint);
   1065     }
   1066 
   1067     ITER_END
   1068 }
   1069 
   1070 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   1071     if (paint.canComputeFastBounds()) {
   1072         SkRect storage;
   1073         const SkRect& bounds = path.getBounds();
   1074         if (this->quickReject(paint.computeFastBounds(bounds, &storage),
   1075                               paint2EdgeType(&paint))) {
   1076             return;
   1077         }
   1078     }
   1079 
   1080     ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
   1081 
   1082     while (iter.next()) {
   1083         iter.fDevice->drawPath(iter, path, paint);
   1084     }
   1085 
   1086     ITER_END
   1087 }
   1088 
   1089 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
   1090                           const SkPaint* paint) {
   1091     SkDEBUGCODE(bitmap.validate();)
   1092 
   1093     if (NULL == paint || (paint->getMaskFilter() == NULL)) {
   1094         SkRect fastBounds;
   1095         fastBounds.set(x, y,
   1096                        x + SkIntToScalar(bitmap.width()),
   1097                        y + SkIntToScalar(bitmap.height()));
   1098         if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
   1099             return;
   1100         }
   1101     }
   1102 
   1103     SkMatrix matrix;
   1104     matrix.setTranslate(x, y);
   1105     this->internalDrawBitmap(bitmap, matrix, paint);
   1106 }
   1107 
   1108 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
   1109                               const SkRect& dst, const SkPaint* paint) {
   1110     if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
   1111         return;
   1112     }
   1113 
   1114     // do this now, to avoid the cost of calling extract for RLE bitmaps
   1115     if (this->quickReject(dst, paint2EdgeType(paint))) {
   1116         return;
   1117     }
   1118 
   1119     SkBitmap        tmp;    // storage if we need a subset of bitmap
   1120     const SkBitmap* bitmapPtr = &bitmap;
   1121 
   1122     if (NULL != src) {
   1123         if (!bitmap.extractSubset(&tmp, *src)) {
   1124             return;     // extraction failed
   1125         }
   1126         bitmapPtr = &tmp;
   1127     }
   1128 
   1129     SkMatrix matrix;
   1130     SkRect tmpSrc;
   1131     if (src) {
   1132         tmpSrc.set(*src);
   1133         // if the extract process clipped off the top or left of the
   1134         // original, we adjust for that here to get the position right.
   1135         if (tmpSrc.fLeft > 0) {
   1136             tmpSrc.fRight -= tmpSrc.fLeft;
   1137             tmpSrc.fLeft = 0;
   1138         }
   1139         if (tmpSrc.fTop > 0) {
   1140             tmpSrc.fBottom -= tmpSrc.fTop;
   1141             tmpSrc.fTop = 0;
   1142         }
   1143     } else {
   1144         tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()),
   1145                    SkIntToScalar(bitmap.height()));
   1146     }
   1147     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
   1148     this->internalDrawBitmap(*bitmapPtr, matrix, paint);
   1149 }
   1150 
   1151 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
   1152                                 const SkPaint* paint) {
   1153     SkDEBUGCODE(bitmap.validate();)
   1154     this->internalDrawBitmap(bitmap, matrix, paint);
   1155 }
   1156 
   1157 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
   1158                                 const SkPaint& paint) {
   1159     SkDEBUGCODE(bitmap.validate();)
   1160 
   1161     ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
   1162 
   1163     while (iter.next()) {
   1164         iter.fDevice->drawBitmap(iter, bitmap, matrix, paint);
   1165     }
   1166 
   1167     ITER_END
   1168 }
   1169 
   1170 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
   1171                           const SkPaint* paint) {
   1172     SkDEBUGCODE(bitmap.validate();)
   1173 
   1174     if (reject_bitmap(bitmap)) {
   1175         return;
   1176     }
   1177 
   1178     SkPaint tmp;
   1179     if (NULL == paint) {
   1180         paint = &tmp;
   1181     }
   1182 
   1183     ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
   1184 
   1185     while (iter.next()) {
   1186         iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
   1187                                  *paint);
   1188     }
   1189     ITER_END
   1190 }
   1191 
   1192 void SkCanvas::drawText(const void* text, size_t byteLength,
   1193                         SkScalar x, SkScalar y, const SkPaint& paint) {
   1194     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
   1195 
   1196     while (iter.next()) {
   1197         iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
   1198     }
   1199 
   1200     ITER_END
   1201 }
   1202 
   1203 void SkCanvas::drawPosText(const void* text, size_t byteLength,
   1204                            const SkPoint pos[], const SkPaint& paint) {
   1205     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
   1206 
   1207     while (iter.next()) {
   1208         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
   1209                                   paint);
   1210     }
   1211 
   1212     ITER_END
   1213 }
   1214 
   1215 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
   1216                             const SkScalar xpos[], SkScalar constY,
   1217                             const SkPaint& paint) {
   1218     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
   1219 
   1220     while (iter.next()) {
   1221         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
   1222                                   paint);
   1223     }
   1224 
   1225     ITER_END
   1226 }
   1227 
   1228 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
   1229                               const SkPath& path, const SkMatrix* matrix,
   1230                               const SkPaint& paint) {
   1231     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
   1232 
   1233     while (iter.next()) {
   1234         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
   1235                                      matrix, paint);
   1236     }
   1237 
   1238     ITER_END
   1239 }
   1240 
   1241 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
   1242                                  const SkPoint pos[], const SkPaint& paint,
   1243                                  const SkPath& path, const SkMatrix* matrix) {
   1244 
   1245     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
   1246 
   1247     while (iter.next()) {
   1248         iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
   1249                                         paint, path, matrix);
   1250     }
   1251 
   1252     ITER_END
   1253 }
   1254 
   1255 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
   1256                             const SkPoint verts[], const SkPoint texs[],
   1257                             const SkColor colors[], SkXfermode* xmode,
   1258                             const uint16_t indices[], int indexCount,
   1259                             const SkPaint& paint) {
   1260     ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
   1261 
   1262     while (iter.next()) {
   1263         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
   1264                                    colors, xmode, indices, indexCount, paint);
   1265     }
   1266 
   1267     ITER_END
   1268 }
   1269 
   1270 void SkCanvas::drawData(const void* data, size_t length) {
   1271     // do nothing. Subclasses may do something with the data
   1272 }
   1273 
   1274 //////////////////////////////////////////////////////////////////////////////
   1275 // These methods are NOT virtual, and therefore must call back into virtual
   1276 // methods, rather than actually drawing themselves.
   1277 //////////////////////////////////////////////////////////////////////////////
   1278 
   1279 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
   1280                         SkXfermode::Mode mode) {
   1281     SkPaint paint;
   1282 
   1283     paint.setARGB(a, r, g, b);
   1284     if (SkXfermode::kSrcOver_Mode != mode) {
   1285         paint.setXfermodeMode(mode);
   1286     }
   1287     this->drawPaint(paint);
   1288 }
   1289 
   1290 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
   1291     SkPaint paint;
   1292 
   1293     paint.setColor(c);
   1294     if (SkXfermode::kSrcOver_Mode != mode) {
   1295         paint.setXfermodeMode(mode);
   1296     }
   1297     this->drawPaint(paint);
   1298 }
   1299 
   1300 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
   1301     SkPoint pt;
   1302 
   1303     pt.set(x, y);
   1304     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   1305 }
   1306 
   1307 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
   1308     SkPoint pt;
   1309     SkPaint paint;
   1310 
   1311     pt.set(x, y);
   1312     paint.setColor(color);
   1313     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   1314 }
   1315 
   1316 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
   1317                         const SkPaint& paint) {
   1318     SkPoint pts[2];
   1319 
   1320     pts[0].set(x0, y0);
   1321     pts[1].set(x1, y1);
   1322     this->drawPoints(kLines_PointMode, 2, pts, paint);
   1323 }
   1324 
   1325 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
   1326                               SkScalar right, SkScalar bottom,
   1327                               const SkPaint& paint) {
   1328     SkRect  r;
   1329 
   1330     r.set(left, top, right, bottom);
   1331     this->drawRect(r, paint);
   1332 }
   1333 
   1334 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
   1335                           const SkPaint& paint) {
   1336     if (radius < 0) {
   1337         radius = 0;
   1338     }
   1339 
   1340     SkRect  r;
   1341     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
   1342 
   1343     if (paint.canComputeFastBounds()) {
   1344         SkRect storage;
   1345         if (this->quickReject(paint.computeFastBounds(r, &storage),
   1346                               paint2EdgeType(&paint))) {
   1347             return;
   1348         }
   1349     }
   1350 
   1351     SkPath  path;
   1352     path.addOval(r);
   1353     this->drawPath(path, paint);
   1354 }
   1355 
   1356 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
   1357                              const SkPaint& paint) {
   1358     if (rx > 0 && ry > 0) {
   1359         if (paint.canComputeFastBounds()) {
   1360             SkRect storage;
   1361             if (this->quickReject(paint.computeFastBounds(r, &storage),
   1362                                   paint2EdgeType(&paint))) {
   1363                 return;
   1364             }
   1365         }
   1366 
   1367         SkPath  path;
   1368         path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
   1369         this->drawPath(path, paint);
   1370     } else {
   1371         this->drawRect(r, paint);
   1372     }
   1373 }
   1374 
   1375 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
   1376     if (paint.canComputeFastBounds()) {
   1377         SkRect storage;
   1378         if (this->quickReject(paint.computeFastBounds(oval, &storage),
   1379                               paint2EdgeType(&paint))) {
   1380             return;
   1381         }
   1382     }
   1383 
   1384     SkPath  path;
   1385     path.addOval(oval);
   1386     this->drawPath(path, paint);
   1387 }
   1388 
   1389 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
   1390                        SkScalar sweepAngle, bool useCenter,
   1391                        const SkPaint& paint) {
   1392     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
   1393         this->drawOval(oval, paint);
   1394     } else {
   1395         SkPath  path;
   1396         if (useCenter) {
   1397             path.moveTo(oval.centerX(), oval.centerY());
   1398         }
   1399         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
   1400         if (useCenter) {
   1401             path.close();
   1402         }
   1403         this->drawPath(path, paint);
   1404     }
   1405 }
   1406 
   1407 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
   1408                                 const SkPath& path, SkScalar hOffset,
   1409                                 SkScalar vOffset, const SkPaint& paint) {
   1410     SkMatrix    matrix;
   1411 
   1412     matrix.setTranslate(hOffset, vOffset);
   1413     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
   1414 }
   1415 
   1416 ///////////////////////////////////////////////////////////////////////////////
   1417 
   1418 void SkCanvas::drawPicture(SkPicture& picture) {
   1419     int saveCount = save();
   1420     picture.draw(this);
   1421     restoreToCount(saveCount);
   1422 }
   1423 
   1424 void SkCanvas::drawShape(SkShape* shape) {
   1425     // shape baseclass takes care of save/restore
   1426     shape->draw(this);
   1427 }
   1428 
   1429 ///////////////////////////////////////////////////////////////////////////////
   1430 ///////////////////////////////////////////////////////////////////////////////
   1431 
   1432 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
   1433     // need COMPILE_TIME_ASSERT
   1434     SkASSERT(sizeof(fStorage) >= sizeof(SkDrawIter));
   1435 
   1436     SkASSERT(canvas);
   1437 
   1438     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
   1439     fDone = !fImpl->next();
   1440 }
   1441 
   1442 SkCanvas::LayerIter::~LayerIter() {
   1443     fImpl->~SkDrawIter();
   1444 }
   1445 
   1446 void SkCanvas::LayerIter::next() {
   1447     fDone = !fImpl->next();
   1448 }
   1449 
   1450 SkDevice* SkCanvas::LayerIter::device() const {
   1451     return fImpl->getDevice();
   1452 }
   1453 
   1454 const SkMatrix& SkCanvas::LayerIter::matrix() const {
   1455     return fImpl->getMatrix();
   1456 }
   1457 
   1458 const SkPaint& SkCanvas::LayerIter::paint() const {
   1459     const SkPaint* paint = fImpl->getPaint();
   1460     if (NULL == paint) {
   1461         paint = &fDefaultPaint;
   1462     }
   1463     return *paint;
   1464 }
   1465 
   1466 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
   1467 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
   1468 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
   1469 
   1470