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