SkCanvas.cpp revision 6f09709519b79a1159f3826645f1c5fbc101ee11
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 (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 (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 (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->tryAllocPixels()) {
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->tryAllocN32Pixels(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    // the intersect may have shrunk info's logical size
635    const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height());
636
637    // if x or y are negative, then we have to adjust pixels
638    if (x > 0) {
639        x = 0;
640    }
641    if (y > 0) {
642        y = 0;
643    }
644    // here x,y are either 0 or negative
645    dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
646
647    // The device can assert that the requested area is always contained in its bounds
648    return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
649}
650
651bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
652    if (bitmap.getTexture()) {
653        return false;
654    }
655    SkBitmap bm(bitmap);
656    bm.lockPixels();
657    if (bm.getPixels()) {
658        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
659    }
660    return false;
661}
662
663bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
664                           int x, int y) {
665    switch (origInfo.colorType()) {
666        case kUnknown_SkColorType:
667        case kIndex_8_SkColorType:
668            return false;
669        default:
670            break;
671    }
672    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
673        return false;
674    }
675
676    const SkISize size = this->getBaseLayerSize();
677    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
678    if (!target.intersect(0, 0, size.width(), size.height())) {
679        return false;
680    }
681
682    SkBaseDevice* device = this->getDevice();
683    if (!device) {
684        return false;
685    }
686
687    // the intersect may have shrunk info's logical size
688    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
689
690    // if x or y are negative, then we have to adjust pixels
691    if (x > 0) {
692        x = 0;
693    }
694    if (y > 0) {
695        y = 0;
696    }
697    // here x,y are either 0 or negative
698    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
699
700    // Tell our owning surface to bump its generation ID
701    this->predrawNotify();
702
703    // The device can assert that the requested area is always contained in its bounds
704    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
705}
706
707SkCanvas* SkCanvas::canvasForDrawIter() {
708    return this;
709}
710
711//////////////////////////////////////////////////////////////////////////////
712
713void SkCanvas::updateDeviceCMCache() {
714    if (fDeviceCMDirty) {
715        const SkMatrix& totalMatrix = this->getTotalMatrix();
716        const SkRasterClip& totalClip = fMCRec->fRasterClip;
717        DeviceCM*       layer = fMCRec->fTopLayer;
718
719        if (NULL == layer->fNext) {   // only one layer
720            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
721        } else {
722            SkRasterClip clip(totalClip);
723            do {
724                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
725            } while ((layer = layer->fNext) != NULL);
726        }
727        fDeviceCMDirty = false;
728    }
729}
730
731///////////////////////////////////////////////////////////////////////////////
732
733int SkCanvas::internalSave() {
734    int saveCount = this->getSaveCount(); // record this before the actual save
735
736    MCRec* newTop = (MCRec*)fMCStack.push_back();
737    new (newTop) MCRec(fMCRec);    // balanced in restore()
738    fMCRec = newTop;
739
740    fClipStack.save();
741
742    return saveCount;
743}
744
745int SkCanvas::save() {
746    this->willSave();
747    return this->internalSave();
748}
749
750static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
751#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
752    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
753#else
754    return true;
755#endif
756}
757
758bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
759                               SkIRect* intersection, const SkImageFilter* imageFilter) {
760    SkIRect clipBounds;
761    SkRegion::Op op = SkRegion::kIntersect_Op;
762    if (!this->getClipDeviceBounds(&clipBounds)) {
763        return false;
764    }
765
766    if (imageFilter) {
767        imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
768        // Filters may grow the bounds beyond the device bounds.
769        op = SkRegion::kReplace_Op;
770    }
771    SkIRect ir;
772    if (bounds) {
773        SkRect r;
774
775        this->getTotalMatrix().mapRect(&r, *bounds);
776        r.roundOut(&ir);
777        // early exit if the layer's bounds are clipped out
778        if (!ir.intersect(clipBounds)) {
779            if (bounds_affects_clip(flags)) {
780                fMCRec->fRasterClip.setEmpty();
781            }
782            return false;
783        }
784    } else {    // no user bounds, so just use the clip
785        ir = clipBounds;
786    }
787
788    if (bounds_affects_clip(flags)) {
789        fClipStack.clipDevRect(ir, op);
790        // early exit if the clip is now empty
791        if (!fMCRec->fRasterClip.op(ir, op)) {
792            return false;
793        }
794    }
795
796    if (intersection) {
797        *intersection = ir;
798    }
799    return true;
800}
801
802int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
803    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
804    return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
805}
806
807int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
808                        SaveFlags flags) {
809    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
810    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
811}
812
813int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
814                                bool justForImageFilter, SaveLayerStrategy strategy) {
815#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
816    flags |= kClipToLayer_SaveFlag;
817#endif
818
819    // do this before we create the layer. We don't call the public save() since
820    // that would invoke a possibly overridden virtual
821    int count = this->internalSave();
822
823    fDeviceCMDirty = true;
824
825    SkIRect ir;
826    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
827        return count;
828    }
829
830    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
831    // the clipRectBounds() call above?
832    if (kNoLayer_SaveLayerStrategy == strategy) {
833        return count;
834    }
835
836    // Kill the imagefilter if our device doesn't allow it
837    SkLazyPaint lazyP;
838    if (paint && paint->getImageFilter()) {
839        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
840            if (justForImageFilter) {
841                // early exit if the layer was just for the imageFilter
842                return count;
843            }
844            SkPaint* p = lazyP.set(*paint);
845            p->setImageFilter(NULL);
846            paint = p;
847        }
848    }
849
850    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
851    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
852                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
853
854    SkBaseDevice* device;
855    if (paint && paint->getImageFilter()) {
856        device = this->getDevice();
857        if (device) {
858            device = device->createCompatibleDevice(info);
859        }
860    } else {
861        device = this->createLayerDevice(info);
862    }
863    if (NULL == device) {
864        SkDebugf("Unable to create device for layer.");
865        return count;
866    }
867
868    device->setOrigin(ir.fLeft, ir.fTop);
869    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
870    device->unref();
871
872    layer->fNext = fMCRec->fTopLayer;
873    fMCRec->fLayer = layer;
874    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
875
876    fSaveLayerCount += 1;
877    return count;
878}
879
880int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
881    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
882}
883
884int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
885                             SaveFlags flags) {
886    if (0xFF == alpha) {
887        return this->saveLayer(bounds, NULL, flags);
888    } else {
889        SkPaint tmpPaint;
890        tmpPaint.setAlpha(alpha);
891        return this->saveLayer(bounds, &tmpPaint, flags);
892    }
893}
894
895void SkCanvas::restore() {
896    // check for underflow
897    if (fMCStack.count() > 1) {
898        this->willRestore();
899        this->internalRestore();
900        this->didRestore();
901    }
902}
903
904void SkCanvas::internalRestore() {
905    SkASSERT(fMCStack.count() != 0);
906
907    fDeviceCMDirty = true;
908    fCachedLocalClipBoundsDirty = true;
909
910    fClipStack.restore();
911
912    // reserve our layer (if any)
913    DeviceCM* layer = fMCRec->fLayer;   // may be null
914    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
915    fMCRec->fLayer = NULL;
916
917    // now do the normal restore()
918    fMCRec->~MCRec();       // balanced in save()
919    fMCStack.pop_back();
920    fMCRec = (MCRec*)fMCStack.back();
921
922    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
923        since if we're being recorded, we don't want to record this (the
924        recorder will have already recorded the restore).
925    */
926    if (layer) {
927        if (layer->fNext) {
928            const SkIPoint& origin = layer->fDevice->getOrigin();
929            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
930                                     layer->fPaint);
931            // reset this, since internalDrawDevice will have set it to true
932            fDeviceCMDirty = true;
933
934            SkASSERT(fSaveLayerCount > 0);
935            fSaveLayerCount -= 1;
936        }
937        SkDELETE(layer);
938    }
939}
940
941int SkCanvas::getSaveCount() const {
942    return fMCStack.count();
943}
944
945void SkCanvas::restoreToCount(int count) {
946    // sanity check
947    if (count < 1) {
948        count = 1;
949    }
950
951    int n = this->getSaveCount() - count;
952    for (int i = 0; i < n; ++i) {
953        this->restore();
954    }
955}
956
957bool SkCanvas::isDrawingToLayer() const {
958    return fSaveLayerCount > 0;
959}
960
961SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
962    return this->onNewSurface(info);
963}
964
965SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
966    SkBaseDevice* dev = this->getDevice();
967    return dev ? dev->newSurface(info) : NULL;
968}
969
970SkImageInfo SkCanvas::imageInfo() const {
971    SkBaseDevice* dev = this->getDevice();
972    if (dev) {
973        return dev->imageInfo();
974    } else {
975        return SkImageInfo::MakeUnknown(0, 0);
976    }
977}
978
979const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
980    return this->onPeekPixels(info, rowBytes);
981}
982
983const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
984    SkBaseDevice* dev = this->getDevice();
985    return dev ? dev->peekPixels(info, rowBytes) : NULL;
986}
987
988void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
989    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
990    if (pixels && origin) {
991        *origin = this->getTopDevice(false)->getOrigin();
992    }
993    return pixels;
994}
995
996void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
997    SkBaseDevice* dev = this->getTopDevice();
998    return dev ? dev->accessPixels(info, rowBytes) : NULL;
999}
1000
1001SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1002    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1003    if (NULL == fAddr) {
1004        fInfo = canvas->imageInfo();
1005        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1006            return; // failure, fAddr is NULL
1007        }
1008        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1009            return; // failure, fAddr is NULL
1010        }
1011        fAddr = fBitmap.getPixels();
1012        fRowBytes = fBitmap.rowBytes();
1013    }
1014    SkASSERT(fAddr);    // success
1015}
1016
1017bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1018    if (fAddr) {
1019        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1020    } else {
1021        bitmap->reset();
1022        return false;
1023    }
1024}
1025
1026void SkCanvas::onPushCull(const SkRect& cullRect) {
1027    // do nothing. Subclasses may do something
1028}
1029
1030void SkCanvas::onPopCull() {
1031    // do nothing. Subclasses may do something
1032}
1033
1034/////////////////////////////////////////////////////////////////////////////
1035#ifdef SK_DEBUG
1036// Ensure that cull rects are monotonically nested in device space.
1037void SkCanvas::validateCull(const SkIRect& devCull) {
1038    if (fCullStack.isEmpty()
1039        || devCull.isEmpty()
1040        || fCullStack.top().contains(devCull)) {
1041        return;
1042    }
1043
1044    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1045              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1046              fCullStack.top().x(), fCullStack.top().y(),
1047              fCullStack.top().right(), fCullStack.top().bottom()));
1048
1049#ifdef ASSERT_NESTED_CULLING
1050    SkDEBUGFAIL("Invalid cull.");
1051#endif
1052}
1053#endif
1054
1055void SkCanvas::pushCull(const SkRect& cullRect) {
1056    ++fCullCount;
1057    this->onPushCull(cullRect);
1058
1059#ifdef SK_DEBUG
1060    // Map the cull rect into device space.
1061    SkRect mappedCull;
1062    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1063
1064    // Take clipping into account.
1065    SkIRect devClip, devCull;
1066    mappedCull.roundOut(&devCull);
1067    this->getClipDeviceBounds(&devClip);
1068    if (!devCull.intersect(devClip)) {
1069        devCull.setEmpty();
1070    }
1071
1072    this->validateCull(devCull);
1073    fCullStack.push(devCull); // balanced in popCull
1074#endif
1075}
1076
1077void SkCanvas::popCull() {
1078    SkASSERT(fCullStack.count() == fCullCount);
1079
1080    if (fCullCount > 0) {
1081        --fCullCount;
1082        this->onPopCull();
1083
1084        SkDEBUGCODE(fCullStack.pop());
1085    }
1086}
1087
1088/////////////////////////////////////////////////////////////////////////////
1089
1090void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1091                                const SkMatrix& matrix, const SkPaint* paint) {
1092    if (bitmap.drawsNothing()) {
1093        return;
1094    }
1095
1096    SkLazyPaint lazy;
1097    if (NULL == paint) {
1098        paint = lazy.init();
1099    }
1100
1101    SkDEBUGCODE(bitmap.validate();)
1102
1103    SkRect storage;
1104    const SkRect* bounds = NULL;
1105    if (paint && paint->canComputeFastBounds()) {
1106        bitmap.getBounds(&storage);
1107        matrix.mapRect(&storage);
1108        bounds = &paint->computeFastBounds(storage, &storage);
1109    }
1110
1111    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1112
1113    while (iter.next()) {
1114        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1115    }
1116
1117    LOOPER_END
1118}
1119
1120void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1121                                  const SkPaint* paint) {
1122    SkPaint tmp;
1123    if (NULL == paint) {
1124        tmp.setDither(true);
1125        paint = &tmp;
1126    }
1127
1128    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1129    while (iter.next()) {
1130        SkBaseDevice* dstDev = iter.fDevice;
1131        paint = &looper.paint();
1132        SkImageFilter* filter = paint->getImageFilter();
1133        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1134        if (filter && !dstDev->canHandleImageFilter(filter)) {
1135            SkDeviceImageFilterProxy proxy(dstDev);
1136            SkBitmap dst;
1137            SkIPoint offset = SkIPoint::Make(0, 0);
1138            const SkBitmap& src = srcDev->accessBitmap(false);
1139            SkMatrix matrix = *iter.fMatrix;
1140            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1141            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1142            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1143            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1144            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1145                SkPaint tmpUnfiltered(*paint);
1146                tmpUnfiltered.setImageFilter(NULL);
1147                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1148                                   tmpUnfiltered);
1149            }
1150        } else {
1151            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1152        }
1153    }
1154    LOOPER_END
1155}
1156
1157void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1158                          const SkPaint* paint) {
1159    if (bitmap.drawsNothing()) {
1160        return;
1161    }
1162    SkDEBUGCODE(bitmap.validate();)
1163
1164    SkPaint tmp;
1165    if (NULL == paint) {
1166        paint = &tmp;
1167    }
1168
1169    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1170
1171    while (iter.next()) {
1172        paint = &looper.paint();
1173        SkImageFilter* filter = paint->getImageFilter();
1174        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1175        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1176            SkDeviceImageFilterProxy proxy(iter.fDevice);
1177            SkBitmap dst;
1178            SkIPoint offset = SkIPoint::Make(0, 0);
1179            SkMatrix matrix = *iter.fMatrix;
1180            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1181            SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1182            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
1183            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1184            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1185                SkPaint tmpUnfiltered(*paint);
1186                tmpUnfiltered.setImageFilter(NULL);
1187                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1188                                         tmpUnfiltered);
1189            }
1190        } else {
1191            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1192        }
1193    }
1194    LOOPER_END
1195}
1196
1197/////////////////////////////////////////////////////////////////////////////
1198void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1199    SkMatrix m;
1200    m.setTranslate(dx, dy);
1201    this->concat(m);
1202}
1203
1204void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1205    SkMatrix m;
1206    m.setScale(sx, sy);
1207    this->concat(m);
1208}
1209
1210void SkCanvas::rotate(SkScalar degrees) {
1211    SkMatrix m;
1212    m.setRotate(degrees);
1213    this->concat(m);
1214}
1215
1216void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1217    SkMatrix m;
1218    m.setSkew(sx, sy);
1219    this->concat(m);
1220}
1221
1222void SkCanvas::concat(const SkMatrix& matrix) {
1223    if (matrix.isIdentity()) {
1224        return;
1225    }
1226
1227    fDeviceCMDirty = true;
1228    fCachedLocalClipBoundsDirty = true;
1229    fMCRec->fMatrix.preConcat(matrix);
1230
1231    this->didConcat(matrix);
1232}
1233
1234void SkCanvas::setMatrix(const SkMatrix& matrix) {
1235    fDeviceCMDirty = true;
1236    fCachedLocalClipBoundsDirty = true;
1237    fMCRec->fMatrix = matrix;
1238    this->didSetMatrix(matrix);
1239}
1240
1241void SkCanvas::resetMatrix() {
1242    SkMatrix matrix;
1243
1244    matrix.reset();
1245    this->setMatrix(matrix);
1246}
1247
1248//////////////////////////////////////////////////////////////////////////////
1249
1250void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1251    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1252    this->onClipRect(rect, op, edgeStyle);
1253}
1254
1255void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1256#ifdef SK_ENABLE_CLIP_QUICKREJECT
1257    if (SkRegion::kIntersect_Op == op) {
1258        if (fMCRec->fRasterClip.isEmpty()) {
1259            return false;
1260        }
1261
1262        if (this->quickReject(rect)) {
1263            fDeviceCMDirty = true;
1264            fCachedLocalClipBoundsDirty = true;
1265
1266            fClipStack.clipEmpty();
1267            return fMCRec->fRasterClip.setEmpty();
1268        }
1269    }
1270#endif
1271
1272    AutoValidateClip avc(this);
1273
1274    fDeviceCMDirty = true;
1275    fCachedLocalClipBoundsDirty = true;
1276    if (!fAllowSoftClip) {
1277        edgeStyle = kHard_ClipEdgeStyle;
1278    }
1279
1280    if (fMCRec->fMatrix.rectStaysRect()) {
1281        // for these simpler matrices, we can stay a rect even after applying
1282        // the matrix. This means we don't have to a) make a path, and b) tell
1283        // the region code to scan-convert the path, only to discover that it
1284        // is really just a rect.
1285        SkRect      r;
1286
1287        fMCRec->fMatrix.mapRect(&r, rect);
1288        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1289        fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1290    } else {
1291        // since we're rotated or some such thing, we convert the rect to a path
1292        // and clip against that, since it can handle any matrix. However, to
1293        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1294        // we explicitly call "our" version of clipPath.
1295        SkPath  path;
1296
1297        path.addRect(rect);
1298        this->SkCanvas::onClipPath(path, op, edgeStyle);
1299    }
1300}
1301
1302static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
1303                            SkRegion::Op op, bool doAA) {
1304    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1305}
1306
1307void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1308    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1309    if (rrect.isRect()) {
1310        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1311    } else {
1312        this->onClipRRect(rrect, op, edgeStyle);
1313    }
1314}
1315
1316void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1317    SkRRect transformedRRect;
1318    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1319        AutoValidateClip avc(this);
1320
1321        fDeviceCMDirty = true;
1322        fCachedLocalClipBoundsDirty = true;
1323        if (!fAllowSoftClip) {
1324            edgeStyle = kHard_ClipEdgeStyle;
1325        }
1326
1327        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1328
1329        SkPath devPath;
1330        devPath.addRRect(transformedRRect);
1331
1332        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1333        return;
1334    }
1335
1336    SkPath path;
1337    path.addRRect(rrect);
1338    // call the non-virtual version
1339    this->SkCanvas::onClipPath(path, op, edgeStyle);
1340}
1341
1342void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1343    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1344    SkRect r;
1345    if (!path.isInverseFillType() && path.isRect(&r)) {
1346        this->onClipRect(r, op, edgeStyle);
1347    } else {
1348        this->onClipPath(path, op, edgeStyle);
1349    }
1350}
1351
1352void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1353#ifdef SK_ENABLE_CLIP_QUICKREJECT
1354    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1355        if (fMCRec->fRasterClip.isEmpty()) {
1356            return false;
1357        }
1358
1359        if (this->quickReject(path.getBounds())) {
1360            fDeviceCMDirty = true;
1361            fCachedLocalClipBoundsDirty = true;
1362
1363            fClipStack.clipEmpty();
1364            return fMCRec->fRasterClip.setEmpty();
1365        }
1366    }
1367#endif
1368
1369    AutoValidateClip avc(this);
1370
1371    fDeviceCMDirty = true;
1372    fCachedLocalClipBoundsDirty = true;
1373    if (!fAllowSoftClip) {
1374        edgeStyle = kHard_ClipEdgeStyle;
1375    }
1376
1377    SkPath devPath;
1378    path.transform(fMCRec->fMatrix, &devPath);
1379
1380    // Check if the transfomation, or the original path itself
1381    // made us empty. Note this can also happen if we contained NaN
1382    // values. computing the bounds detects this, and will set our
1383    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1384    if (devPath.getBounds().isEmpty()) {
1385        // resetting the path will remove any NaN or other wanky values
1386        // that might upset our scan converter.
1387        devPath.reset();
1388    }
1389
1390    // if we called path.swap() we could avoid a deep copy of this path
1391    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1392
1393    if (fAllowSimplifyClip) {
1394        devPath.reset();
1395        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1396        const SkClipStack* clipStack = getClipStack();
1397        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
1398        const SkClipStack::Element* element;
1399        while ((element = iter.next())) {
1400            SkClipStack::Element::Type type = element->getType();
1401            SkPath operand;
1402            if (type != SkClipStack::Element::kEmpty_Type) {
1403                element->asPath(&operand);
1404            }
1405            SkRegion::Op elementOp = element->getOp();
1406            if (elementOp == SkRegion::kReplace_Op) {
1407                devPath = operand;
1408            } else {
1409                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1410            }
1411            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1412            // perhaps we need an API change to avoid this sort of mixed-signals about
1413            // clipping.
1414            if (element->isAA()) {
1415                edgeStyle = kSoft_ClipEdgeStyle;
1416            }
1417        }
1418        op = SkRegion::kReplace_Op;
1419    }
1420
1421    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1422}
1423
1424void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1425                                                   bool inverseFilled) {
1426    // This is for updating the clip conservatively using only bounds
1427    // information.
1428    // Contract:
1429    //    The current clip must contain the true clip. The true
1430    //    clip is the clip that would have normally been computed
1431    //    by calls to clipPath and clipRRect
1432    // Objective:
1433    //    Keep the current clip as small as possible without
1434    //    breaking the contract, using only clip bounding rectangles
1435    //    (for performance).
1436
1437    // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1438    // don't have to worry about getting caught in a loop. Thus anywhere
1439    // we call a virtual method, we explicitly prefix it with
1440    // SkCanvas:: to be sure to call the base-class.
1441
1442    if (inverseFilled) {
1443        switch (op) {
1444            case SkRegion::kIntersect_Op:
1445            case SkRegion::kDifference_Op:
1446                // These ops can only shrink the current clip. So leaving
1447                // the clip unchanged conservatively respects the contract.
1448                break;
1449            case SkRegion::kUnion_Op:
1450            case SkRegion::kReplace_Op:
1451            case SkRegion::kReverseDifference_Op:
1452            case SkRegion::kXOR_Op: {
1453                    // These ops can grow the current clip up to the extents of
1454                    // the input clip, which is inverse filled, so we just set
1455                    // the current clip to the device bounds.
1456                    SkRect deviceBounds;
1457                    SkIRect deviceIBounds;
1458                    this->getDevice()->getGlobalBounds(&deviceIBounds);
1459                    deviceBounds = SkRect::Make(deviceIBounds);
1460
1461                    // set the clip in device space
1462                    SkMatrix savedMatrix = this->getTotalMatrix();
1463                    this->SkCanvas::setMatrix(SkMatrix::I());
1464                    this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
1465                                               kHard_ClipEdgeStyle);
1466                    this->setMatrix(savedMatrix);
1467                    break;
1468            }
1469            default:
1470                SkASSERT(0); // unhandled op?
1471        }
1472    } else {
1473        // Not inverse filled
1474        switch (op) {
1475            case SkRegion::kIntersect_Op:
1476            case SkRegion::kUnion_Op:
1477            case SkRegion::kReplace_Op:
1478                this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
1479                break;
1480            case SkRegion::kDifference_Op:
1481                // Difference can only shrink the current clip.
1482                // Leaving clip unchanged conservatively fullfills the contract.
1483                break;
1484            case SkRegion::kReverseDifference_Op:
1485                // To reverse, we swap in the bounds with a replace op.
1486                // As with difference, leave it unchanged.
1487                this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
1488                break;
1489            case SkRegion::kXOR_Op:
1490                // Be conservative, based on (A XOR B) always included in (A union B),
1491                // which is always included in (bounds(A) union bounds(B))
1492                this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
1493                break;
1494            default:
1495                SkASSERT(0); // unhandled op?
1496        }
1497    }
1498}
1499
1500void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1501    this->onClipRegion(rgn, op);
1502}
1503
1504void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1505    AutoValidateClip avc(this);
1506
1507    fDeviceCMDirty = true;
1508    fCachedLocalClipBoundsDirty = true;
1509
1510    // todo: signal fClipStack that we have a region, and therefore (I guess)
1511    // we have to ignore it, and use the region directly?
1512    fClipStack.clipDevRect(rgn.getBounds(), op);
1513
1514    fMCRec->fRasterClip.op(rgn, op);
1515}
1516
1517#ifdef SK_DEBUG
1518void SkCanvas::validateClip() const {
1519    // construct clipRgn from the clipstack
1520    const SkBaseDevice* device = this->getDevice();
1521    if (!device) {
1522        SkASSERT(this->isClipEmpty());
1523        return;
1524    }
1525
1526    SkIRect ir;
1527    ir.set(0, 0, device->width(), device->height());
1528    SkRasterClip tmpClip(ir);
1529
1530    SkClipStack::B2TIter                iter(fClipStack);
1531    const SkClipStack::Element* element;
1532    while ((element = iter.next()) != NULL) {
1533        switch (element->getType()) {
1534            case SkClipStack::Element::kRect_Type:
1535                element->getRect().round(&ir);
1536                tmpClip.op(ir, element->getOp());
1537                break;
1538            case SkClipStack::Element::kEmpty_Type:
1539                tmpClip.setEmpty();
1540                break;
1541            default: {
1542                SkPath path;
1543                element->asPath(&path);
1544                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
1545                break;
1546            }
1547        }
1548    }
1549}
1550#endif
1551
1552void SkCanvas::replayClips(ClipVisitor* visitor) const {
1553    SkClipStack::B2TIter                iter(fClipStack);
1554    const SkClipStack::Element*         element;
1555
1556    while ((element = iter.next()) != NULL) {
1557        element->replay(visitor);
1558    }
1559}
1560
1561///////////////////////////////////////////////////////////////////////////////
1562
1563bool SkCanvas::isClipEmpty() const {
1564    return fMCRec->fRasterClip.isEmpty();
1565}
1566
1567bool SkCanvas::isClipRect() const {
1568    return fMCRec->fRasterClip.isRect();
1569}
1570
1571bool SkCanvas::quickReject(const SkRect& rect) const {
1572
1573    if (!rect.isFinite())
1574        return true;
1575
1576    if (fMCRec->fRasterClip.isEmpty()) {
1577        return true;
1578    }
1579
1580    if (fMCRec->fMatrix.hasPerspective()) {
1581        SkRect dst;
1582        fMCRec->fMatrix.mapRect(&dst, rect);
1583        SkIRect idst;
1584        dst.roundOut(&idst);
1585        return !SkIRect::Intersects(idst, fMCRec->fRasterClip.getBounds());
1586    } else {
1587        const SkRect& clipR = this->getLocalClipBounds();
1588
1589        // for speed, do the most likely reject compares first
1590        // TODO: should we use | instead, or compare all 4 at once?
1591        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1592            return true;
1593        }
1594        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1595            return true;
1596        }
1597        return false;
1598    }
1599}
1600
1601bool SkCanvas::quickReject(const SkPath& path) const {
1602    return path.isEmpty() || this->quickReject(path.getBounds());
1603}
1604
1605bool SkCanvas::getClipBounds(SkRect* bounds) const {
1606    SkIRect ibounds;
1607    if (!this->getClipDeviceBounds(&ibounds)) {
1608        return false;
1609    }
1610
1611    SkMatrix inverse;
1612    // if we can't invert the CTM, we can't return local clip bounds
1613    if (!fMCRec->fMatrix.invert(&inverse)) {
1614        if (bounds) {
1615            bounds->setEmpty();
1616        }
1617        return false;
1618    }
1619
1620    if (bounds) {
1621        SkRect r;
1622        // adjust it outwards in case we are antialiasing
1623        const int inset = 1;
1624
1625        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1626               ibounds.fRight + inset, ibounds.fBottom + inset);
1627        inverse.mapRect(bounds, r);
1628    }
1629    return true;
1630}
1631
1632bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1633    const SkRasterClip& clip = fMCRec->fRasterClip;
1634    if (clip.isEmpty()) {
1635        if (bounds) {
1636            bounds->setEmpty();
1637        }
1638        return false;
1639    }
1640
1641    if (bounds) {
1642        *bounds = clip.getBounds();
1643    }
1644    return true;
1645}
1646
1647const SkMatrix& SkCanvas::getTotalMatrix() const {
1648    return fMCRec->fMatrix;
1649}
1650
1651const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1652    return fMCRec->fRasterClip.forceGetBW();
1653}
1654
1655GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1656    SkBaseDevice* dev = this->getTopDevice();
1657    return dev ? dev->accessRenderTarget() : NULL;
1658}
1659
1660SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
1661    SkBaseDevice* device = this->getTopDevice();
1662    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
1663}
1664
1665GrContext* SkCanvas::getGrContext() {
1666#if SK_SUPPORT_GPU
1667    SkBaseDevice* device = this->getTopDevice();
1668    if (device) {
1669        GrRenderTarget* renderTarget = device->accessRenderTarget();
1670        if (renderTarget) {
1671            return renderTarget->getContext();
1672        }
1673    }
1674#endif
1675
1676    return NULL;
1677
1678}
1679
1680void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1681                          const SkPaint& paint) {
1682    if (outer.isEmpty()) {
1683        return;
1684    }
1685    if (inner.isEmpty()) {
1686        this->drawRRect(outer, paint);
1687        return;
1688    }
1689
1690    // We don't have this method (yet), but technically this is what we should
1691    // be able to assert...
1692    // SkASSERT(outer.contains(inner));
1693    //
1694    // For now at least check for containment of bounds
1695    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1696
1697    this->onDrawDRRect(outer, inner, paint);
1698}
1699
1700//////////////////////////////////////////////////////////////////////////////
1701//  These are the virtual drawing methods
1702//////////////////////////////////////////////////////////////////////////////
1703
1704void SkCanvas::clear(SkColor color) {
1705    SkDrawIter  iter(this);
1706    this->predrawNotify();
1707    while (iter.next()) {
1708        iter.fDevice->clear(color);
1709    }
1710}
1711
1712void SkCanvas::onDiscard() {
1713    if (fSurfaceBase) {
1714        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1715    }
1716}
1717
1718void SkCanvas::drawPaint(const SkPaint& paint) {
1719    this->internalDrawPaint(paint);
1720}
1721
1722void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1723    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1724
1725    while (iter.next()) {
1726        iter.fDevice->drawPaint(iter, looper.paint());
1727    }
1728
1729    LOOPER_END
1730}
1731
1732void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1733                          const SkPaint& paint) {
1734    if ((long)count <= 0) {
1735        return;
1736    }
1737
1738    SkRect r, storage;
1739    const SkRect* bounds = NULL;
1740    if (paint.canComputeFastBounds()) {
1741        // special-case 2 points (common for drawing a single line)
1742        if (2 == count) {
1743            r.set(pts[0], pts[1]);
1744        } else {
1745            r.set(pts, SkToInt(count));
1746        }
1747        bounds = &paint.computeFastStrokeBounds(r, &storage);
1748        if (this->quickReject(*bounds)) {
1749            return;
1750        }
1751    }
1752
1753    SkASSERT(pts != NULL);
1754
1755    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1756
1757    while (iter.next()) {
1758        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1759    }
1760
1761    LOOPER_END
1762}
1763
1764void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1765    SkRect storage;
1766    const SkRect* bounds = NULL;
1767    if (paint.canComputeFastBounds()) {
1768        bounds = &paint.computeFastBounds(r, &storage);
1769        if (this->quickReject(*bounds)) {
1770            return;
1771        }
1772    }
1773
1774    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1775
1776    while (iter.next()) {
1777        iter.fDevice->drawRect(iter, r, looper.paint());
1778    }
1779
1780    LOOPER_END
1781}
1782
1783void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1784    SkRect storage;
1785    const SkRect* bounds = NULL;
1786    if (paint.canComputeFastBounds()) {
1787        bounds = &paint.computeFastBounds(oval, &storage);
1788        if (this->quickReject(*bounds)) {
1789            return;
1790        }
1791    }
1792
1793    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1794
1795    while (iter.next()) {
1796        iter.fDevice->drawOval(iter, oval, looper.paint());
1797    }
1798
1799    LOOPER_END
1800}
1801
1802void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1803    SkRect storage;
1804    const SkRect* bounds = NULL;
1805    if (paint.canComputeFastBounds()) {
1806        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1807        if (this->quickReject(*bounds)) {
1808            return;
1809        }
1810    }
1811
1812    if (rrect.isRect()) {
1813        // call the non-virtual version
1814        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1815        return;
1816    } else if (rrect.isOval()) {
1817        // call the non-virtual version
1818        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1819        return;
1820    }
1821
1822    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1823
1824    while (iter.next()) {
1825        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1826    }
1827
1828    LOOPER_END
1829}
1830
1831void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1832                            const SkPaint& paint) {
1833    SkRect storage;
1834    const SkRect* bounds = NULL;
1835    if (paint.canComputeFastBounds()) {
1836        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1837        if (this->quickReject(*bounds)) {
1838            return;
1839        }
1840    }
1841
1842    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1843
1844    while (iter.next()) {
1845        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1846    }
1847
1848    LOOPER_END
1849}
1850
1851void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1852    if (!path.isFinite()) {
1853        return;
1854    }
1855
1856    SkRect storage;
1857    const SkRect* bounds = NULL;
1858    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1859        const SkRect& pathBounds = path.getBounds();
1860        bounds = &paint.computeFastBounds(pathBounds, &storage);
1861        if (this->quickReject(*bounds)) {
1862            return;
1863        }
1864    }
1865
1866    const SkRect& r = path.getBounds();
1867    if (r.width() <= 0 && r.height() <= 0) {
1868        if (path.isInverseFillType()) {
1869            this->internalDrawPaint(paint);
1870        }
1871        return;
1872    }
1873
1874    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1875
1876    while (iter.next()) {
1877        iter.fDevice->drawPath(iter, path, looper.paint());
1878    }
1879
1880    LOOPER_END
1881}
1882
1883void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1884                          const SkPaint* paint) {
1885    SkDEBUGCODE(bitmap.validate();)
1886
1887    if (NULL == paint || paint->canComputeFastBounds()) {
1888        SkRect bounds = {
1889            x, y,
1890            x + SkIntToScalar(bitmap.width()),
1891            y + SkIntToScalar(bitmap.height())
1892        };
1893        if (paint) {
1894            (void)paint->computeFastBounds(bounds, &bounds);
1895        }
1896        if (this->quickReject(bounds)) {
1897            return;
1898        }
1899    }
1900
1901    SkMatrix matrix;
1902    matrix.setTranslate(x, y);
1903    this->internalDrawBitmap(bitmap, matrix, paint);
1904}
1905
1906// this one is non-virtual, so it can be called safely by other canvas apis
1907void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1908                                      const SkRect& dst, const SkPaint* paint,
1909                                      DrawBitmapRectFlags flags) {
1910    if (bitmap.drawsNothing() || dst.isEmpty()) {
1911        return;
1912    }
1913
1914    SkRect storage;
1915    const SkRect* bounds = &dst;
1916    if (NULL == paint || paint->canComputeFastBounds()) {
1917        if (paint) {
1918            bounds = &paint->computeFastBounds(dst, &storage);
1919        }
1920        if (this->quickReject(*bounds)) {
1921            return;
1922        }
1923    }
1924
1925    SkLazyPaint lazy;
1926    if (NULL == paint) {
1927        paint = lazy.init();
1928    }
1929
1930    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1931
1932    while (iter.next()) {
1933        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1934    }
1935
1936    LOOPER_END
1937}
1938
1939void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1940                                    const SkRect& dst, const SkPaint* paint,
1941                                    DrawBitmapRectFlags flags) {
1942    SkDEBUGCODE(bitmap.validate();)
1943    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
1944}
1945
1946void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1947                                const SkPaint* paint) {
1948    SkDEBUGCODE(bitmap.validate();)
1949    this->internalDrawBitmap(bitmap, matrix, paint);
1950}
1951
1952void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1953                                      const SkIRect& center, const SkRect& dst,
1954                                      const SkPaint* paint) {
1955    if (bitmap.drawsNothing()) {
1956        return;
1957    }
1958    if (NULL == paint || paint->canComputeFastBounds()) {
1959        SkRect storage;
1960        const SkRect* bounds = &dst;
1961        if (paint) {
1962            bounds = &paint->computeFastBounds(dst, &storage);
1963        }
1964        if (this->quickReject(*bounds)) {
1965            return;
1966        }
1967    }
1968
1969    const int32_t w = bitmap.width();
1970    const int32_t h = bitmap.height();
1971
1972    SkIRect c = center;
1973    // pin center to the bounds of the bitmap
1974    c.fLeft = SkMax32(0, center.fLeft);
1975    c.fTop = SkMax32(0, center.fTop);
1976    c.fRight = SkPin32(center.fRight, c.fLeft, w);
1977    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1978
1979    const SkScalar srcX[4] = {
1980        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
1981    };
1982    const SkScalar srcY[4] = {
1983        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
1984    };
1985    SkScalar dstX[4] = {
1986        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1987        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1988    };
1989    SkScalar dstY[4] = {
1990        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1991        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1992    };
1993
1994    if (dstX[1] > dstX[2]) {
1995        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1996        dstX[2] = dstX[1];
1997    }
1998
1999    if (dstY[1] > dstY[2]) {
2000        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2001        dstY[2] = dstY[1];
2002    }
2003
2004    for (int y = 0; y < 3; y++) {
2005        SkRect s, d;
2006
2007        s.fTop = srcY[y];
2008        s.fBottom = srcY[y+1];
2009        d.fTop = dstY[y];
2010        d.fBottom = dstY[y+1];
2011        for (int x = 0; x < 3; x++) {
2012            s.fLeft = srcX[x];
2013            s.fRight = srcX[x+1];
2014            d.fLeft = dstX[x];
2015            d.fRight = dstX[x+1];
2016            this->internalDrawBitmapRect(bitmap, &s, d, paint,
2017                                         kNone_DrawBitmapRectFlag);
2018        }
2019    }
2020}
2021
2022void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
2023                              const SkRect& dst, const SkPaint* paint) {
2024    SkDEBUGCODE(bitmap.validate();)
2025
2026    // Need a device entry-point, so gpu can use a mesh
2027    this->internalDrawBitmapNine(bitmap, center, dst, paint);
2028}
2029
2030class SkDeviceFilteredPaint {
2031public:
2032    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2033        SkBaseDevice::TextFlags flags;
2034        if (device->filterTextFlags(paint, &flags)) {
2035            SkPaint* newPaint = fLazy.set(paint);
2036            newPaint->setFlags(flags.fFlags);
2037            newPaint->setHinting(flags.fHinting);
2038            fPaint = newPaint;
2039        } else {
2040            fPaint = &paint;
2041        }
2042    }
2043
2044    const SkPaint& paint() const { return *fPaint; }
2045
2046private:
2047    const SkPaint*  fPaint;
2048    SkLazyPaint     fLazy;
2049};
2050
2051void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2052                        const SkRect& r, SkScalar textSize) {
2053    if (paint.getStyle() == SkPaint::kFill_Style) {
2054        draw.fDevice->drawRect(draw, r, paint);
2055    } else {
2056        SkPaint p(paint);
2057        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2058        draw.fDevice->drawRect(draw, r, p);
2059    }
2060}
2061
2062void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2063                                   const char text[], size_t byteLength,
2064                                   SkScalar x, SkScalar y) {
2065    SkASSERT(byteLength == 0 || text != NULL);
2066
2067    // nothing to draw
2068    if (text == NULL || byteLength == 0 ||
2069        draw.fClip->isEmpty() ||
2070        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2071        return;
2072    }
2073
2074    SkScalar    width = 0;
2075    SkPoint     start;
2076
2077    start.set(0, 0);    // to avoid warning
2078    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2079                            SkPaint::kStrikeThruText_Flag)) {
2080        width = paint.measureText(text, byteLength);
2081
2082        SkScalar offsetX = 0;
2083        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2084            offsetX = SkScalarHalf(width);
2085        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2086            offsetX = width;
2087        }
2088        start.set(x - offsetX, y);
2089    }
2090
2091    if (0 == width) {
2092        return;
2093    }
2094
2095    uint32_t flags = paint.getFlags();
2096
2097    if (flags & (SkPaint::kUnderlineText_Flag |
2098                 SkPaint::kStrikeThruText_Flag)) {
2099        SkScalar textSize = paint.getTextSize();
2100        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2101        SkRect   r;
2102
2103        r.fLeft = start.fX;
2104        r.fRight = start.fX + width;
2105
2106        if (flags & SkPaint::kUnderlineText_Flag) {
2107            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2108                                             start.fY);
2109            r.fTop = offset;
2110            r.fBottom = offset + height;
2111            DrawRect(draw, paint, r, textSize);
2112        }
2113        if (flags & SkPaint::kStrikeThruText_Flag) {
2114            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2115                                             start.fY);
2116            r.fTop = offset;
2117            r.fBottom = offset + height;
2118            DrawRect(draw, paint, r, textSize);
2119        }
2120    }
2121}
2122
2123void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2124                          const SkPaint& paint) {
2125    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2126
2127    while (iter.next()) {
2128        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2129        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2130        DrawTextDecorations(iter, dfp.paint(),
2131                            static_cast<const char*>(text), byteLength, x, y);
2132    }
2133
2134    LOOPER_END
2135}
2136
2137void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2138                             const SkPaint& paint) {
2139    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2140
2141    while (iter.next()) {
2142        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2143        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2144                                  dfp.paint());
2145    }
2146
2147    LOOPER_END
2148}
2149
2150void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2151                              SkScalar constY, const SkPaint& paint) {
2152    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2153
2154    while (iter.next()) {
2155        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2156        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2157                                  dfp.paint());
2158    }
2159
2160    LOOPER_END
2161}
2162
2163void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2164                                const SkMatrix* matrix, const SkPaint& paint) {
2165    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2166
2167    while (iter.next()) {
2168        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2169                                     matrix, looper.paint());
2170    }
2171
2172    LOOPER_END
2173}
2174
2175void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2176                              const SkPaint& paint) {
2177
2178    // FIXME: temporarily disable quickreject for empty bounds,
2179    // pending implicit blob bounds implementation.
2180    if (!blob->bounds().isEmpty() && paint.canComputeFastBounds()) {
2181        SkRect storage;
2182
2183        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
2184            return;
2185        }
2186    }
2187
2188    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2189
2190    while (iter.next()) {
2191        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2192        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
2193    }
2194
2195    LOOPER_END
2196}
2197
2198// These will become non-virtual, so they always call the (virtual) onDraw... method
2199void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2200                        const SkPaint& paint) {
2201    this->onDrawText(text, byteLength, x, y, paint);
2202}
2203void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2204                           const SkPaint& paint) {
2205    this->onDrawPosText(text, byteLength, pos, paint);
2206}
2207void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2208                            SkScalar constY, const SkPaint& paint) {
2209    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2210}
2211void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2212                              const SkMatrix* matrix, const SkPaint& paint) {
2213    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2214}
2215void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2216                            const SkPaint& paint) {
2217    if (blob) {
2218        this->onDrawTextBlob(blob, x, y, paint);
2219    }
2220}
2221
2222void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
2223                            const SkPoint verts[], const SkPoint texs[],
2224                            const SkColor colors[], SkXfermode* xmode,
2225                            const uint16_t indices[], int indexCount,
2226                            const SkPaint& paint) {
2227    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2228
2229    while (iter.next()) {
2230        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2231                                   colors, xmode, indices, indexCount,
2232                                   looper.paint());
2233    }
2234
2235    LOOPER_END
2236}
2237
2238void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2239                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2240    if (NULL == cubics) {
2241        return;
2242    }
2243
2244    // Since a patch is always within the convex hull of the control points, we discard it when its
2245    // bounding rectangle is completely outside the current clip.
2246    SkRect bounds;
2247    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2248    if (this->quickReject(bounds)) {
2249        return;
2250    }
2251
2252    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2253}
2254
2255void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2256                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2257
2258    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2259
2260    while (iter.next()) {
2261        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2262    }
2263
2264    LOOPER_END
2265}
2266
2267//////////////////////////////////////////////////////////////////////////////
2268// These methods are NOT virtual, and therefore must call back into virtual
2269// methods, rather than actually drawing themselves.
2270//////////////////////////////////////////////////////////////////////////////
2271
2272void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2273                        SkXfermode::Mode mode) {
2274    SkPaint paint;
2275
2276    paint.setARGB(a, r, g, b);
2277    if (SkXfermode::kSrcOver_Mode != mode) {
2278        paint.setXfermodeMode(mode);
2279    }
2280    this->drawPaint(paint);
2281}
2282
2283void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2284    SkPaint paint;
2285
2286    paint.setColor(c);
2287    if (SkXfermode::kSrcOver_Mode != mode) {
2288        paint.setXfermodeMode(mode);
2289    }
2290    this->drawPaint(paint);
2291}
2292
2293void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2294    SkPoint pt;
2295
2296    pt.set(x, y);
2297    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2298}
2299
2300void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2301    SkPoint pt;
2302    SkPaint paint;
2303
2304    pt.set(x, y);
2305    paint.setColor(color);
2306    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2307}
2308
2309void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2310                        const SkPaint& paint) {
2311    SkPoint pts[2];
2312
2313    pts[0].set(x0, y0);
2314    pts[1].set(x1, y1);
2315    this->drawPoints(kLines_PointMode, 2, pts, paint);
2316}
2317
2318void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2319                              SkScalar right, SkScalar bottom,
2320                              const SkPaint& paint) {
2321    SkRect  r;
2322
2323    r.set(left, top, right, bottom);
2324    this->drawRect(r, paint);
2325}
2326
2327void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2328                          const SkPaint& paint) {
2329    if (radius < 0) {
2330        radius = 0;
2331    }
2332
2333    SkRect  r;
2334    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2335    this->drawOval(r, paint);
2336}
2337
2338void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2339                             const SkPaint& paint) {
2340    if (rx > 0 && ry > 0) {
2341        if (paint.canComputeFastBounds()) {
2342            SkRect storage;
2343            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2344                return;
2345            }
2346        }
2347        SkRRect rrect;
2348        rrect.setRectXY(r, rx, ry);
2349        this->drawRRect(rrect, paint);
2350    } else {
2351        this->drawRect(r, paint);
2352    }
2353}
2354
2355void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2356                       SkScalar sweepAngle, bool useCenter,
2357                       const SkPaint& paint) {
2358    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2359        this->drawOval(oval, paint);
2360    } else {
2361        SkPath  path;
2362        if (useCenter) {
2363            path.moveTo(oval.centerX(), oval.centerY());
2364        }
2365        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2366        if (useCenter) {
2367            path.close();
2368        }
2369        this->drawPath(path, paint);
2370    }
2371}
2372
2373void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2374                                const SkPath& path, SkScalar hOffset,
2375                                SkScalar vOffset, const SkPaint& paint) {
2376    SkMatrix    matrix;
2377
2378    matrix.setTranslate(hOffset, vOffset);
2379    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2380}
2381
2382///////////////////////////////////////////////////////////////////////////////
2383void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
2384    SkBaseDevice* device = this->getDevice();
2385    if (device) {
2386        device->EXPERIMENTAL_optimize(picture);
2387    }
2388}
2389
2390void SkCanvas::drawPicture(const SkPicture* picture) {
2391    if (picture) {
2392        this->onDrawPicture(picture, NULL, NULL);
2393    }
2394}
2395
2396void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2397    if (picture) {
2398        if (matrix && matrix->isIdentity()) {
2399            matrix = NULL;
2400        }
2401        this->onDrawPicture(picture, matrix, paint);
2402    }
2403}
2404
2405void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2406                             const SkPaint* paint) {
2407    SkBaseDevice* device = this->getTopDevice();
2408    if (device) {
2409        // Canvas has to first give the device the opportunity to render
2410        // the picture itself.
2411        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2412            return; // the device has rendered the entire picture
2413        }
2414    }
2415
2416    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2417
2418    picture->playback(this);
2419}
2420
2421///////////////////////////////////////////////////////////////////////////////
2422///////////////////////////////////////////////////////////////////////////////
2423
2424SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2425    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2426
2427    SkASSERT(canvas);
2428
2429    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2430    fDone = !fImpl->next();
2431}
2432
2433SkCanvas::LayerIter::~LayerIter() {
2434    fImpl->~SkDrawIter();
2435}
2436
2437void SkCanvas::LayerIter::next() {
2438    fDone = !fImpl->next();
2439}
2440
2441SkBaseDevice* SkCanvas::LayerIter::device() const {
2442    return fImpl->getDevice();
2443}
2444
2445const SkMatrix& SkCanvas::LayerIter::matrix() const {
2446    return fImpl->getMatrix();
2447}
2448
2449const SkPaint& SkCanvas::LayerIter::paint() const {
2450    const SkPaint* paint = fImpl->getPaint();
2451    if (NULL == paint) {
2452        paint = &fDefaultPaint;
2453    }
2454    return *paint;
2455}
2456
2457const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2458int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2459int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2460
2461///////////////////////////////////////////////////////////////////////////////
2462
2463SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2464
2465///////////////////////////////////////////////////////////////////////////////
2466
2467static bool supported_for_raster_canvas(const SkImageInfo& info) {
2468    switch (info.alphaType()) {
2469        case kPremul_SkAlphaType:
2470        case kOpaque_SkAlphaType:
2471            break;
2472        default:
2473            return false;
2474    }
2475
2476    switch (info.colorType()) {
2477        case kAlpha_8_SkColorType:
2478        case kRGB_565_SkColorType:
2479        case kN32_SkColorType:
2480            break;
2481        default:
2482            return false;
2483    }
2484
2485    return true;
2486}
2487
2488SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
2489    if (!supported_for_raster_canvas(info)) {
2490        return NULL;
2491    }
2492
2493    SkBitmap bitmap;
2494    if (!bitmap.tryAllocPixels(info)) {
2495        return NULL;
2496    }
2497
2498    // should this functionality be moved into allocPixels()?
2499    if (!bitmap.info().isOpaque()) {
2500        bitmap.eraseColor(0);
2501    }
2502    return SkNEW_ARGS(SkCanvas, (bitmap));
2503}
2504
2505SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2506    if (!supported_for_raster_canvas(info)) {
2507        return NULL;
2508    }
2509
2510    SkBitmap bitmap;
2511    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2512        return NULL;
2513    }
2514    return SkNEW_ARGS(SkCanvas, (bitmap));
2515}
2516
2517///////////////////////////////////////////////////////////////////////////////
2518
2519SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2520                                                 const SkPaint* paint, const SkRect& bounds)
2521    : fCanvas(canvas)
2522    , fSaveCount(canvas->getSaveCount())
2523{
2524    if (paint) {
2525        SkRect newBounds = bounds;
2526        if (matrix) {
2527            matrix->mapRect(&newBounds);
2528        }
2529        canvas->saveLayer(&newBounds, paint);
2530    } else if (matrix) {
2531        canvas->save();
2532    }
2533
2534    if (matrix) {
2535        canvas->concat(*matrix);
2536    }
2537}
2538
2539SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2540    fCanvas->restoreToCount(fSaveCount);
2541}
2542