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