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