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