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