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::drawVertices(VertexMode vmode, int vertexCount,
   1242                             const SkPoint verts[], const SkPoint texs[],
   1243                             const SkColor colors[], SkXfermode* xmode,
   1244                             const uint16_t indices[], int indexCount,
   1245                             const SkPaint& paint) {
   1246     ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
   1247 
   1248     while (iter.next()) {
   1249         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
   1250                                    colors, xmode, indices, indexCount, paint);
   1251     }
   1252 
   1253     ITER_END
   1254 }
   1255 
   1256 void SkCanvas::drawData(const void* data, size_t length) {
   1257     // do nothing. Subclasses may do something with the data
   1258 }
   1259 
   1260 //////////////////////////////////////////////////////////////////////////////
   1261 // These methods are NOT virtual, and therefore must call back into virtual
   1262 // methods, rather than actually drawing themselves.
   1263 //////////////////////////////////////////////////////////////////////////////
   1264 
   1265 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
   1266                         SkXfermode::Mode mode) {
   1267     SkPaint paint;
   1268 
   1269     paint.setARGB(a, r, g, b);
   1270     if (SkXfermode::kSrcOver_Mode != mode) {
   1271         paint.setXfermodeMode(mode);
   1272     }
   1273     this->drawPaint(paint);
   1274 }
   1275 
   1276 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
   1277     SkPaint paint;
   1278 
   1279     paint.setColor(c);
   1280     if (SkXfermode::kSrcOver_Mode != mode) {
   1281         paint.setXfermodeMode(mode);
   1282     }
   1283     this->drawPaint(paint);
   1284 }
   1285 
   1286 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
   1287     SkPoint pt;
   1288 
   1289     pt.set(x, y);
   1290     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   1291 }
   1292 
   1293 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
   1294     SkPoint pt;
   1295     SkPaint paint;
   1296 
   1297     pt.set(x, y);
   1298     paint.setColor(color);
   1299     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   1300 }
   1301 
   1302 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
   1303                         const SkPaint& paint) {
   1304     SkPoint pts[2];
   1305 
   1306     pts[0].set(x0, y0);
   1307     pts[1].set(x1, y1);
   1308     this->drawPoints(kLines_PointMode, 2, pts, paint);
   1309 }
   1310 
   1311 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
   1312                               SkScalar right, SkScalar bottom,
   1313                               const SkPaint& paint) {
   1314     SkRect  r;
   1315 
   1316     r.set(left, top, right, bottom);
   1317     this->drawRect(r, paint);
   1318 }
   1319 
   1320 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
   1321                           const SkPaint& paint) {
   1322     if (radius < 0) {
   1323         radius = 0;
   1324     }
   1325 
   1326     SkRect  r;
   1327     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
   1328 
   1329     if (paint.canComputeFastBounds()) {
   1330         SkRect storage;
   1331         if (this->quickReject(paint.computeFastBounds(r, &storage),
   1332                               paint2EdgeType(&paint))) {
   1333             return;
   1334         }
   1335     }
   1336 
   1337     SkPath  path;
   1338     path.addOval(r);
   1339     this->drawPath(path, paint);
   1340 }
   1341 
   1342 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
   1343                              const SkPaint& paint) {
   1344     if (rx > 0 && ry > 0) {
   1345         if (paint.canComputeFastBounds()) {
   1346             SkRect storage;
   1347             if (this->quickReject(paint.computeFastBounds(r, &storage),
   1348                                   paint2EdgeType(&paint))) {
   1349                 return;
   1350             }
   1351         }
   1352 
   1353         SkPath  path;
   1354         path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
   1355         this->drawPath(path, paint);
   1356     } else {
   1357         this->drawRect(r, paint);
   1358     }
   1359 }
   1360 
   1361 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
   1362     if (paint.canComputeFastBounds()) {
   1363         SkRect storage;
   1364         if (this->quickReject(paint.computeFastBounds(oval, &storage),
   1365                               paint2EdgeType(&paint))) {
   1366             return;
   1367         }
   1368     }
   1369 
   1370     SkPath  path;
   1371     path.addOval(oval);
   1372     this->drawPath(path, paint);
   1373 }
   1374 
   1375 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
   1376                        SkScalar sweepAngle, bool useCenter,
   1377                        const SkPaint& paint) {
   1378     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
   1379         this->drawOval(oval, paint);
   1380     } else {
   1381         SkPath  path;
   1382         if (useCenter) {
   1383             path.moveTo(oval.centerX(), oval.centerY());
   1384         }
   1385         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
   1386         if (useCenter) {
   1387             path.close();
   1388         }
   1389         this->drawPath(path, paint);
   1390     }
   1391 }
   1392 
   1393 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
   1394                                 const SkPath& path, SkScalar hOffset,
   1395                                 SkScalar vOffset, const SkPaint& paint) {
   1396     SkMatrix    matrix;
   1397 
   1398     matrix.setTranslate(hOffset, vOffset);
   1399     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
   1400 }
   1401 
   1402 ///////////////////////////////////////////////////////////////////////////////
   1403 
   1404 void SkCanvas::drawPicture(SkPicture& picture) {
   1405     int saveCount = save();
   1406     picture.draw(this);
   1407     restoreToCount(saveCount);
   1408 }
   1409 
   1410 void SkCanvas::drawShape(SkShape* shape) {
   1411     // shape baseclass takes care of save/restore
   1412     shape->draw(this);
   1413 }
   1414 
   1415 ///////////////////////////////////////////////////////////////////////////////
   1416 ///////////////////////////////////////////////////////////////////////////////
   1417 
   1418 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
   1419     // need COMPILE_TIME_ASSERT
   1420     SkASSERT(sizeof(fStorage) >= sizeof(SkDrawIter));
   1421 
   1422     SkASSERT(canvas);
   1423 
   1424     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
   1425     fDone = !fImpl->next();
   1426 }
   1427 
   1428 SkCanvas::LayerIter::~LayerIter() {
   1429     fImpl->~SkDrawIter();
   1430 }
   1431 
   1432 void SkCanvas::LayerIter::next() {
   1433     fDone = !fImpl->next();
   1434 }
   1435 
   1436 SkDevice* SkCanvas::LayerIter::device() const {
   1437     return fImpl->getDevice();
   1438 }
   1439 
   1440 const SkMatrix& SkCanvas::LayerIter::matrix() const {
   1441     return fImpl->getMatrix();
   1442 }
   1443 
   1444 const SkPaint& SkCanvas::LayerIter::paint() const {
   1445     const SkPaint* paint = fImpl->getPaint();
   1446     if (NULL == paint) {
   1447         paint = &fDefaultPaint;
   1448     }
   1449     return *paint;
   1450 }
   1451 
   1452 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
   1453 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
   1454 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
   1455 
   1456