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