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