SkCanvas.cpp revision a907ac3e3e3458fbb5d673c3feafb31fd7647b38
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        const DeviceCM* rec = fCurrLayer;
236        if (rec && rec->fDevice) {
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
710bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
711                               SkIRect* intersection) {
712    SkIRect clipBounds;
713    if (!this->getClipDeviceBounds(&clipBounds)) {
714        return false;
715    }
716    SkIRect ir;
717    if (NULL != bounds) {
718        SkRect r;
719
720        this->getTotalMatrix().mapRect(&r, *bounds);
721        r.roundOut(&ir);
722        // early exit if the layer's bounds are clipped out
723        if (!ir.intersect(clipBounds)) {
724            if (bounds_affects_clip(flags)) {
725                fMCRec->fRasterClip->setEmpty();
726            }
727            return false;
728        }
729    } else {    // no user bounds, so just use the clip
730        ir = clipBounds;
731    }
732
733    fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
734
735    // early exit if the clip is now empty
736    if (bounds_affects_clip(flags) &&
737        !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
738        return false;
739    }
740
741    if (intersection) {
742        *intersection = ir;
743    }
744    return true;
745}
746
747int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
748                        SaveFlags flags) {
749    // do this before we create the layer. We don't call the public save() since
750    // that would invoke a possibly overridden virtual
751    int count = this->internalSave(flags);
752
753    fDeviceCMDirty = true;
754
755    SkIRect ir;
756    if (!this->clipRectBounds(bounds, flags, &ir)) {
757        return count;
758    }
759
760    // Kill the imagefilter if our device doesn't allow it
761    SkLazyPaint lazyP;
762    if (paint && paint->getImageFilter()) {
763        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
764            SkPaint* p = lazyP.set(*paint);
765            p->setImageFilter(NULL);
766            paint = p;
767        }
768    }
769
770    bool isOpaque;
771    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
772
773    SkDevice* device;
774    if (paint && paint->getImageFilter()) {
775        device = this->createCompatibleDevice(config, ir.width(), ir.height(),
776                                              isOpaque);
777    } else {
778        device = this->createLayerDevice(config, ir.width(), ir.height(),
779                                         isOpaque);
780    }
781    if (NULL == device) {
782        SkDebugf("Unable to create device for layer.");
783        return count;
784    }
785
786    device->setOrigin(ir.fLeft, ir.fTop);
787    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
788    device->unref();
789
790    layer->fNext = fMCRec->fTopLayer;
791    fMCRec->fLayer = layer;
792    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
793
794    fLayerCount += 1;
795    return count;
796}
797
798int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
799                             SaveFlags flags) {
800    if (0xFF == alpha) {
801        return this->saveLayer(bounds, NULL, flags);
802    } else {
803        SkPaint tmpPaint;
804        tmpPaint.setAlpha(alpha);
805        return this->saveLayer(bounds, &tmpPaint, flags);
806    }
807}
808
809void SkCanvas::restore() {
810    // check for underflow
811    if (fMCStack.count() > 1) {
812        this->internalRestore();
813    }
814}
815
816void SkCanvas::internalRestore() {
817    SkASSERT(fMCStack.count() != 0);
818
819    fDeviceCMDirty = true;
820    fLocalBoundsCompareTypeDirty = true;
821    fLocalBoundsCompareTypeDirtyBW = true;
822
823    fClipStack.restore();
824    // reserve our layer (if any)
825    DeviceCM* layer = fMCRec->fLayer;   // may be null
826    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
827    fMCRec->fLayer = NULL;
828
829    // now do the normal restore()
830    fMCRec->~MCRec();       // balanced in save()
831    fMCStack.pop_back();
832    fMCRec = (MCRec*)fMCStack.back();
833
834    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
835        since if we're being recorded, we don't want to record this (the
836        recorder will have already recorded the restore).
837    */
838    if (NULL != layer) {
839        if (layer->fNext) {
840            const SkIPoint& origin = layer->fDevice->getOrigin();
841            this->drawDevice(layer->fDevice, origin.x(), origin.y(),
842                             layer->fPaint);
843            // reset this, since drawDevice will have set it to true
844            fDeviceCMDirty = true;
845
846            SkASSERT(fLayerCount > 0);
847            fLayerCount -= 1;
848        }
849        SkDELETE(layer);
850    }
851
852    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
853}
854
855int SkCanvas::getSaveCount() const {
856    return fMCStack.count();
857}
858
859void SkCanvas::restoreToCount(int count) {
860    // sanity check
861    if (count < 1) {
862        count = 1;
863    }
864
865    int n = this->getSaveCount() - count;
866    for (int i = 0; i < n; ++i) {
867        this->restore();
868    }
869}
870
871bool SkCanvas::isDrawingToLayer() const {
872    return fLayerCount > 0;
873}
874
875/////////////////////////////////////////////////////////////////////////////
876
877// can't draw it if its empty, or its too big for a fixed-point width or height
878static bool reject_bitmap(const SkBitmap& bitmap) {
879    return  bitmap.width() <= 0 || bitmap.height() <= 0
880#ifndef SK_ALLOW_OVER_32K_BITMAPS
881            || bitmap.width() > 32767 || bitmap.height() > 32767
882#endif
883            ;
884}
885
886void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
887                                const SkMatrix& matrix, const SkPaint* paint) {
888    if (reject_bitmap(bitmap)) {
889        return;
890    }
891
892    SkLazyPaint lazy;
893    if (NULL == paint) {
894        paint = lazy.init();
895    }
896    this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
897}
898
899#include "SkImageFilter.h"
900
901class DeviceImageFilterProxy : public SkImageFilter::Proxy {
902public:
903    DeviceImageFilterProxy(SkDevice* device) : fDevice(device) {}
904
905    virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE;
906    virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
907                             const SkMatrix& ctm,
908                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
909
910private:
911    SkDevice* fDevice;
912};
913
914SkDevice* DeviceImageFilterProxy::createDevice(int w, int h) {
915    return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
916                                           w, h, false);
917}
918
919bool DeviceImageFilterProxy::filterImage(SkImageFilter* filter,
920                                         const SkBitmap& src,
921                                         const SkMatrix& ctm,
922                                         SkBitmap* result,
923                                         SkIPoint* offset) {
924    return fDevice->filterImage(filter, src, ctm, result, offset);
925}
926
927void SkCanvas::drawDevice(SkDevice* srcDev, int x, int y,
928                          const SkPaint* paint) {
929    SkPaint tmp;
930    if (NULL == paint) {
931        tmp.setDither(true);
932        paint = &tmp;
933    }
934
935    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
936    while (iter.next()) {
937        SkDevice* dstDev = iter.fDevice;
938        paint = &looper.paint();
939        SkImageFilter* filter = paint->getImageFilter();
940        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
941        if (filter) {
942            DeviceImageFilterProxy proxy(dstDev);
943            SkBitmap dst;
944            const SkBitmap& src = srcDev->accessBitmap(false);
945            if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
946                SkPaint tmp(*paint);
947                tmp.setImageFilter(NULL);
948                dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmp);
949            }
950        } else {
951            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
952        }
953    }
954    LOOPER_END
955}
956
957/////////////////////////////////////////////////////////////////////////////
958
959bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
960    fDeviceCMDirty = true;
961    fLocalBoundsCompareTypeDirty = true;
962    fLocalBoundsCompareTypeDirtyBW = true;
963    return fMCRec->fMatrix->preTranslate(dx, dy);
964}
965
966bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
967    fDeviceCMDirty = true;
968    fLocalBoundsCompareTypeDirty = true;
969    fLocalBoundsCompareTypeDirtyBW = true;
970    return fMCRec->fMatrix->preScale(sx, sy);
971}
972
973bool SkCanvas::rotate(SkScalar degrees) {
974    fDeviceCMDirty = true;
975    fLocalBoundsCompareTypeDirty = true;
976    fLocalBoundsCompareTypeDirtyBW = true;
977    return fMCRec->fMatrix->preRotate(degrees);
978}
979
980bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
981    fDeviceCMDirty = true;
982    fLocalBoundsCompareTypeDirty = true;
983    fLocalBoundsCompareTypeDirtyBW = true;
984    return fMCRec->fMatrix->preSkew(sx, sy);
985}
986
987bool SkCanvas::concat(const SkMatrix& matrix) {
988    fDeviceCMDirty = true;
989    fLocalBoundsCompareTypeDirty = true;
990    fLocalBoundsCompareTypeDirtyBW = true;
991    return fMCRec->fMatrix->preConcat(matrix);
992}
993
994void SkCanvas::setMatrix(const SkMatrix& matrix) {
995    fDeviceCMDirty = true;
996    fLocalBoundsCompareTypeDirty = true;
997    fLocalBoundsCompareTypeDirtyBW = true;
998    *fMCRec->fMatrix = matrix;
999}
1000
1001// this is not virtual, so it must call a virtual method so that subclasses
1002// will see its action
1003void SkCanvas::resetMatrix() {
1004    SkMatrix matrix;
1005
1006    matrix.reset();
1007    this->setMatrix(matrix);
1008}
1009
1010//////////////////////////////////////////////////////////////////////////////
1011
1012bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1013    AutoValidateClip avc(this);
1014
1015    fDeviceCMDirty = true;
1016    fLocalBoundsCompareTypeDirty = true;
1017    fLocalBoundsCompareTypeDirtyBW = true;
1018
1019    if (fMCRec->fMatrix->rectStaysRect()) {
1020        // for these simpler matrices, we can stay a rect ever after applying
1021        // the matrix. This means we don't have to a) make a path, and b) tell
1022        // the region code to scan-convert the path, only to discover that it
1023        // is really just a rect.
1024        SkRect      r;
1025
1026        fMCRec->fMatrix->mapRect(&r, rect);
1027        fClipStack.clipDevRect(r, op, doAA);
1028        return fMCRec->fRasterClip->op(r, op, doAA);
1029    } else {
1030        // since we're rotate or some such thing, we convert the rect to a path
1031        // and clip against that, since it can handle any matrix. However, to
1032        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1033        // we explicitly call "our" version of clipPath.
1034        SkPath  path;
1035
1036        path.addRect(rect);
1037        return this->SkCanvas::clipPath(path, op, doAA);
1038    }
1039}
1040
1041static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1042                           const SkPath& devPath, SkRegion::Op op, bool doAA) {
1043    // base is used to limit the size (and therefore memory allocation) of the
1044    // region that results from scan converting devPath.
1045    SkRegion base;
1046
1047    if (SkRegion::kIntersect_Op == op) {
1048        // since we are intersect, we can do better (tighter) with currRgn's
1049        // bounds, than just using the device. However, if currRgn is complex,
1050        // our region blitter may hork, so we do that case in two steps.
1051        if (currClip->isRect()) {
1052            return currClip->setPath(devPath, *currClip, doAA);
1053        } else {
1054            base.setRect(currClip->getBounds());
1055            SkRasterClip clip;
1056            clip.setPath(devPath, base, doAA);
1057            return currClip->op(clip, op);
1058        }
1059    } else {
1060        const SkDevice* device = canvas->getDevice();
1061        base.setRect(0, 0, device->width(), device->height());
1062
1063        if (SkRegion::kReplace_Op == op) {
1064            return currClip->setPath(devPath, base, doAA);
1065        } else {
1066            SkRasterClip clip;
1067            clip.setPath(devPath, base, doAA);
1068            return currClip->op(clip, op);
1069        }
1070    }
1071}
1072
1073bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1074    AutoValidateClip avc(this);
1075
1076    fDeviceCMDirty = true;
1077    fLocalBoundsCompareTypeDirty = true;
1078    fLocalBoundsCompareTypeDirtyBW = true;
1079
1080    SkPath devPath;
1081    path.transform(*fMCRec->fMatrix, &devPath);
1082
1083    // Check if the transfomation, or the original path itself
1084    // made us empty. Note this can also happen if we contained NaN
1085    // values. computing the bounds detects this, and will set our
1086    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1087    if (devPath.getBounds().isEmpty()) {
1088        // resetting the path will remove any NaN or other wanky values
1089        // that might upset our scan converter.
1090        devPath.reset();
1091    }
1092
1093    // if we called path.swap() we could avoid a deep copy of this path
1094    fClipStack.clipDevPath(devPath, op, doAA);
1095
1096    return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
1097}
1098
1099bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1100    AutoValidateClip avc(this);
1101
1102    fDeviceCMDirty = true;
1103    fLocalBoundsCompareTypeDirty = true;
1104    fLocalBoundsCompareTypeDirtyBW = true;
1105
1106    // todo: signal fClipStack that we have a region, and therefore (I guess)
1107    // we have to ignore it, and use the region directly?
1108    fClipStack.clipDevRect(rgn.getBounds());
1109
1110    return fMCRec->fRasterClip->op(rgn, op);
1111}
1112
1113#ifdef SK_DEBUG
1114void SkCanvas::validateClip() const {
1115    // construct clipRgn from the clipstack
1116    const SkDevice* device = this->getDevice();
1117    SkIRect ir;
1118    ir.set(0, 0, device->width(), device->height());
1119    SkRasterClip tmpClip(ir);
1120
1121    SkClipStack::B2FIter                iter(fClipStack);
1122    const SkClipStack::B2FIter::Clip*   clip;
1123    while ((clip = iter.next()) != NULL) {
1124        if (clip->fPath) {
1125            clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA);
1126        } else if (clip->fRect) {
1127            clip->fRect->round(&ir);
1128            tmpClip.op(ir, clip->fOp);
1129        } else {
1130            tmpClip.setEmpty();
1131        }
1132    }
1133
1134#if 0   // enable this locally for testing
1135    // now compare against the current rgn
1136    const SkRegion& rgn = this->getTotalClip();
1137    SkASSERT(rgn == tmpClip);
1138#endif
1139}
1140#endif
1141
1142///////////////////////////////////////////////////////////////////////////////
1143
1144void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
1145    SkRect r;
1146    SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :
1147            fLocalBoundsCompareTypeBW;
1148
1149    if (!this->getClipBounds(&r, et)) {
1150        rCompare.setEmpty();
1151    } else {
1152        rCompare.set(SkScalarToCompareType(r.fLeft),
1153                     SkScalarToCompareType(r.fTop),
1154                     SkScalarToCompareType(r.fRight),
1155                     SkScalarToCompareType(r.fBottom));
1156    }
1157}
1158
1159/*  current impl ignores edgetype, and relies on
1160    getLocalClipBoundsCompareType(), which always returns a value assuming
1161    antialiasing (worst case)
1162 */
1163bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
1164
1165    if (!rect.isFinite())
1166        return true;
1167
1168    if (fMCRec->fRasterClip->isEmpty()) {
1169        return true;
1170    }
1171
1172    if (fMCRec->fMatrix->hasPerspective()) {
1173        SkRect dst;
1174        fMCRec->fMatrix->mapRect(&dst, rect);
1175        SkIRect idst;
1176        dst.roundOut(&idst);
1177        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1178    } else {
1179        const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et);
1180
1181        // for speed, do the most likely reject compares first
1182        SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1183        SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1184        if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1185            return true;
1186        }
1187        SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1188        SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1189        if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1190            return true;
1191        }
1192        return false;
1193    }
1194}
1195
1196bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
1197    return path.isEmpty() || this->quickReject(path.getBounds(), et);
1198}
1199
1200bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
1201    /*  current impl ignores edgetype, and relies on
1202        getLocalClipBoundsCompareType(), which always returns a value assuming
1203        antialiasing (worst case)
1204     */
1205
1206    if (fMCRec->fRasterClip->isEmpty()) {
1207        return true;
1208    }
1209
1210    SkScalarCompareType userT = SkScalarToCompareType(top);
1211    SkScalarCompareType userB = SkScalarToCompareType(bottom);
1212
1213    // check for invalid user Y coordinates (i.e. empty)
1214    // reed: why do we need to do this check, since it slows us down?
1215    if (userT >= userB) {
1216        return true;
1217    }
1218
1219    // check if we are above or below the local clip bounds
1220    const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
1221    return userT >= clipR.fBottom || userB <= clipR.fTop;
1222}
1223
1224static inline int pinIntForScalar(int x) {
1225#ifdef SK_SCALAR_IS_FIXED
1226    if (x < SK_MinS16) {
1227        x = SK_MinS16;
1228    } else if (x > SK_MaxS16) {
1229        x = SK_MaxS16;
1230    }
1231#endif
1232    return x;
1233}
1234
1235bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
1236    SkIRect ibounds;
1237    if (!getClipDeviceBounds(&ibounds)) {
1238        return false;
1239    }
1240
1241    SkMatrix inverse;
1242    // if we can't invert the CTM, we can't return local clip bounds
1243    if (!fMCRec->fMatrix->invert(&inverse)) {
1244        if (bounds) {
1245            bounds->setEmpty();
1246        }
1247        return false;
1248    }
1249
1250    if (NULL != bounds) {
1251        SkRect r;
1252        // adjust it outwards if we are antialiasing
1253        int inset = (kAA_EdgeType == et);
1254
1255        // SkRect::iset() will correctly assert if we pass a value out of range
1256        // (when SkScalar==fixed), so we pin to legal values. This does not
1257        // really returnt the correct answer, but its the best we can do given
1258        // that we've promised to return SkRect (even though we support devices
1259        // that can be larger than 32K in width or height).
1260        r.iset(pinIntForScalar(ibounds.fLeft - inset),
1261               pinIntForScalar(ibounds.fTop - inset),
1262               pinIntForScalar(ibounds.fRight + inset),
1263               pinIntForScalar(ibounds.fBottom + inset));
1264        inverse.mapRect(bounds, r);
1265    }
1266    return true;
1267}
1268
1269bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1270    const SkRasterClip& clip = *fMCRec->fRasterClip;
1271    if (clip.isEmpty()) {
1272        if (bounds) {
1273            bounds->setEmpty();
1274        }
1275        return false;
1276    }
1277
1278    if (NULL != bounds) {
1279        *bounds = clip.getBounds();
1280    }
1281    return true;
1282}
1283
1284const SkMatrix& SkCanvas::getTotalMatrix() const {
1285    return *fMCRec->fMatrix;
1286}
1287
1288SkCanvas::ClipType SkCanvas::getClipType() const {
1289    if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
1290    if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1291    return kComplex_ClipType;
1292}
1293
1294const SkRegion& SkCanvas::getTotalClip() const {
1295    return fMCRec->fRasterClip->forceGetBW();
1296}
1297
1298const SkClipStack& SkCanvas::getTotalClipStack() const {
1299    return fClipStack;
1300}
1301
1302void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
1303    if (NULL == matrix || matrix->isIdentity()) {
1304        if (fUseExternalMatrix) {
1305            fDeviceCMDirty = true;
1306        }
1307        fUseExternalMatrix = false;
1308    } else {
1309        fUseExternalMatrix = true;
1310        fDeviceCMDirty = true;  // |= (fExternalMatrix != *matrix)
1311
1312        fExternalMatrix = *matrix;
1313        matrix->invert(&fExternalInverse);
1314    }
1315}
1316
1317SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
1318                                      int width, int height,
1319                                      bool isOpaque) {
1320    SkDevice* device = this->getTopDevice();
1321    if (device) {
1322        return device->createCompatibleDeviceForSaveLayer(config, width, height,
1323                                                          isOpaque);
1324    } else {
1325        return NULL;
1326    }
1327}
1328
1329SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
1330                                           int width, int height,
1331                                           bool isOpaque) {
1332    SkDevice* device = this->getDevice();
1333    if (device) {
1334        return device->createCompatibleDevice(config, width, height, isOpaque);
1335    } else {
1336        return NULL;
1337    }
1338}
1339
1340
1341//////////////////////////////////////////////////////////////////////////////
1342//  These are the virtual drawing methods
1343//////////////////////////////////////////////////////////////////////////////
1344
1345void SkCanvas::clear(SkColor color) {
1346    SkDrawIter  iter(this);
1347
1348    while (iter.next()) {
1349        iter.fDevice->clear(color);
1350    }
1351}
1352
1353void SkCanvas::drawPaint(const SkPaint& paint) {
1354    this->internalDrawPaint(paint);
1355}
1356
1357void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1358    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1359
1360    while (iter.next()) {
1361        iter.fDevice->drawPaint(iter, looper.paint());
1362    }
1363
1364    LOOPER_END
1365}
1366
1367void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1368                          const SkPaint& paint) {
1369    if ((long)count <= 0) {
1370        return;
1371    }
1372
1373    SkASSERT(pts != NULL);
1374
1375    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1376
1377    while (iter.next()) {
1378        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1379    }
1380
1381    LOOPER_END
1382}
1383
1384void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1385    if (paint.canComputeFastBounds()) {
1386        SkRect storage;
1387        if (this->quickReject(paint.computeFastBounds(r, &storage),
1388                              paint2EdgeType(&paint))) {
1389            return;
1390        }
1391    }
1392
1393    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
1394
1395    while (iter.next()) {
1396        iter.fDevice->drawRect(iter, r, looper.paint());
1397    }
1398
1399    LOOPER_END
1400}
1401
1402void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1403    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1404        SkRect storage;
1405        const SkRect& bounds = path.getBounds();
1406        if (this->quickReject(paint.computeFastBounds(bounds, &storage),
1407                              paint2EdgeType(&paint))) {
1408            return;
1409        }
1410    }
1411    if (path.isEmpty()) {
1412        if (path.isInverseFillType()) {
1413            this->internalDrawPaint(paint);
1414        }
1415        return;
1416    }
1417
1418    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1419
1420    while (iter.next()) {
1421        iter.fDevice->drawPath(iter, path, looper.paint());
1422    }
1423
1424    LOOPER_END
1425}
1426
1427void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1428                          const SkPaint* paint) {
1429    SkDEBUGCODE(bitmap.validate();)
1430
1431    if (NULL == paint || paint->canComputeFastBounds()) {
1432        SkRect bounds = {
1433            x, y,
1434            x + SkIntToScalar(bitmap.width()),
1435            y + SkIntToScalar(bitmap.height())
1436        };
1437        if (paint) {
1438            (void)paint->computeFastBounds(bounds, &bounds);
1439        }
1440        if (this->quickReject(bounds, paint2EdgeType(paint))) {
1441            return;
1442        }
1443    }
1444
1445    SkMatrix matrix;
1446    matrix.setTranslate(x, y);
1447    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1448}
1449
1450// this one is non-virtual, so it can be called safely by other canvas apis
1451void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1452                                      const SkRect& dst, const SkPaint* paint) {
1453    if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1454        return;
1455    }
1456
1457    // do this now, to avoid the cost of calling extract for RLE bitmaps
1458    if (NULL == paint || paint->canComputeFastBounds()) {
1459        SkRect storage;
1460        const SkRect* bounds = &dst;
1461        if (paint) {
1462            bounds = &paint->computeFastBounds(dst, &storage);
1463        }
1464        if (this->quickReject(*bounds, paint2EdgeType(paint))) {
1465            return;
1466        }
1467    }
1468
1469    const SkBitmap* bitmapPtr = &bitmap;
1470
1471    SkMatrix matrix;
1472    SkRect tmpSrc;
1473    if (src) {
1474        tmpSrc.set(*src);
1475        // if the extract process clipped off the top or left of the
1476        // original, we adjust for that here to get the position right.
1477        if (tmpSrc.fLeft > 0) {
1478            tmpSrc.fRight -= tmpSrc.fLeft;
1479            tmpSrc.fLeft = 0;
1480        }
1481        if (tmpSrc.fTop > 0) {
1482            tmpSrc.fBottom -= tmpSrc.fTop;
1483            tmpSrc.fTop = 0;
1484        }
1485    } else {
1486        tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()),
1487                   SkIntToScalar(bitmap.height()));
1488    }
1489    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1490
1491    // ensure that src is "valid" before we pass it to our internal routines
1492    // and to SkDevice. i.e. sure it is contained inside the original bitmap.
1493    SkIRect tmpISrc;
1494    if (src) {
1495        tmpISrc.set(0, 0, bitmap.width(), bitmap.height());
1496        if (!tmpISrc.intersect(*src)) {
1497            return;
1498        }
1499        src = &tmpISrc;
1500    }
1501    this->internalDrawBitmap(*bitmapPtr, src, matrix, paint);
1502}
1503
1504void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1505                              const SkRect& dst, const SkPaint* paint) {
1506    SkDEBUGCODE(bitmap.validate();)
1507    this->internalDrawBitmapRect(bitmap, src, dst, paint);
1508}
1509
1510void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1511                                const SkPaint* paint) {
1512    SkDEBUGCODE(bitmap.validate();)
1513    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1514}
1515
1516void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1517                                const SkMatrix& matrix, const SkPaint& paint) {
1518    SkDEBUGCODE(bitmap.validate();)
1519
1520    LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1521
1522    while (iter.next()) {
1523        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
1524    }
1525
1526    LOOPER_END
1527}
1528
1529void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1530                                      const SkIRect& center, const SkRect& dst,
1531                                      const SkPaint* paint) {
1532    if (NULL == paint || paint->canComputeFastBounds()) {
1533        SkRect storage;
1534        const SkRect* bounds = &dst;
1535        if (paint) {
1536            bounds = &paint->computeFastBounds(dst, &storage);
1537        }
1538        if (this->quickReject(*bounds, paint2EdgeType(paint))) {
1539            return;
1540        }
1541    }
1542
1543    const int32_t w = bitmap.width();
1544    const int32_t h = bitmap.height();
1545
1546    SkIRect c = center;
1547    // pin center to the bounds of the bitmap
1548    c.fLeft = SkMax32(0, center.fLeft);
1549    c.fTop = SkMax32(0, center.fTop);
1550    c.fRight = SkPin32(center.fRight, c.fLeft, w);
1551    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1552
1553    const int32_t srcX[4] = { 0, c.fLeft, c.fRight, w };
1554    const int32_t srcY[4] = { 0, c.fTop, c.fBottom, h };
1555    SkScalar dstX[4] = {
1556        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1557        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1558    };
1559    SkScalar dstY[4] = {
1560        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1561        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1562    };
1563
1564    if (dstX[1] > dstX[2]) {
1565        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1566        dstX[2] = dstX[1];
1567    }
1568
1569    if (dstY[1] > dstY[2]) {
1570        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1571        dstY[2] = dstY[1];
1572    }
1573
1574    SkIRect s;
1575    SkRect  d;
1576    for (int y = 0; y < 3; y++) {
1577        s.fTop = srcY[y];
1578        s.fBottom = srcY[y+1];
1579        d.fTop = dstY[y];
1580        d.fBottom = dstY[y+1];
1581        for (int x = 0; x < 3; x++) {
1582            s.fLeft = srcX[x];
1583            s.fRight = srcX[x+1];
1584            d.fLeft = dstX[x];
1585            d.fRight = dstX[x+1];
1586            this->internalDrawBitmapRect(bitmap, &s, d, paint);
1587        }
1588    }
1589}
1590
1591void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1592                              const SkRect& dst, const SkPaint* paint) {
1593    SkDEBUGCODE(bitmap.validate();)
1594
1595    // Need a device entry-point, so gpu can use a mesh
1596    this->internalDrawBitmapNine(bitmap, center, dst, paint);
1597}
1598
1599void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1600                          const SkPaint* paint) {
1601    SkDEBUGCODE(bitmap.validate();)
1602
1603    if (reject_bitmap(bitmap)) {
1604        return;
1605    }
1606
1607    SkPaint tmp;
1608    if (NULL == paint) {
1609        paint = &tmp;
1610    }
1611
1612    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1613
1614    while (iter.next()) {
1615        iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
1616                                 looper.paint());
1617    }
1618    LOOPER_END
1619}
1620
1621class SkDeviceFilteredPaint {
1622public:
1623    SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
1624        SkDevice::TextFlags flags;
1625        if (device->filterTextFlags(paint, &flags)) {
1626            SkPaint* newPaint = fLazy.set(paint);
1627            newPaint->setFlags(flags.fFlags);
1628            newPaint->setHinting(flags.fHinting);
1629            fPaint = newPaint;
1630        } else {
1631            fPaint = &paint;
1632        }
1633    }
1634
1635    const SkPaint& paint() const { return *fPaint; }
1636
1637private:
1638    const SkPaint*  fPaint;
1639    SkLazyPaint     fLazy;
1640};
1641
1642void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
1643                        const SkRect& r, SkScalar textSize) {
1644    if (paint.getStyle() == SkPaint::kFill_Style) {
1645        draw.fDevice->drawRect(draw, r, paint);
1646    } else {
1647        SkPaint p(paint);
1648        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1649        draw.fDevice->drawRect(draw, r, p);
1650    }
1651}
1652
1653void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1654                                   const char text[], size_t byteLength,
1655                                   SkScalar x, SkScalar y) {
1656    SkASSERT(byteLength == 0 || text != NULL);
1657
1658    // nothing to draw
1659    if (text == NULL || byteLength == 0 ||
1660        draw.fClip->isEmpty() ||
1661        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1662        return;
1663    }
1664
1665    SkScalar    width = 0;
1666    SkPoint     start;
1667
1668    start.set(0, 0);    // to avoid warning
1669    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1670                            SkPaint::kStrikeThruText_Flag)) {
1671        width = paint.measureText(text, byteLength);
1672
1673        SkScalar offsetX = 0;
1674        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1675            offsetX = SkScalarHalf(width);
1676        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1677            offsetX = width;
1678        }
1679        start.set(x - offsetX, y);
1680    }
1681
1682    if (0 == width) {
1683        return;
1684    }
1685
1686    uint32_t flags = paint.getFlags();
1687
1688    if (flags & (SkPaint::kUnderlineText_Flag |
1689                 SkPaint::kStrikeThruText_Flag)) {
1690        SkScalar textSize = paint.getTextSize();
1691        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1692        SkRect   r;
1693
1694        r.fLeft = start.fX;
1695        r.fRight = start.fX + width;
1696
1697        if (flags & SkPaint::kUnderlineText_Flag) {
1698            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1699                                             start.fY);
1700            r.fTop = offset;
1701            r.fBottom = offset + height;
1702            DrawRect(draw, paint, r, textSize);
1703        }
1704        if (flags & SkPaint::kStrikeThruText_Flag) {
1705            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1706                                             start.fY);
1707            r.fTop = offset;
1708            r.fBottom = offset + height;
1709            DrawRect(draw, paint, r, textSize);
1710        }
1711    }
1712}
1713
1714void SkCanvas::drawText(const void* text, size_t byteLength,
1715                        SkScalar x, SkScalar y, const SkPaint& paint) {
1716    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1717
1718    while (iter.next()) {
1719        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1720        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
1721        DrawTextDecorations(iter, dfp.paint(),
1722                            static_cast<const char*>(text), byteLength, x, y);
1723    }
1724
1725    LOOPER_END
1726}
1727
1728void SkCanvas::drawPosText(const void* text, size_t byteLength,
1729                           const SkPoint pos[], const SkPaint& paint) {
1730    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1731
1732    while (iter.next()) {
1733        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1734        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1735                                  dfp.paint());
1736    }
1737
1738    LOOPER_END
1739}
1740
1741void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1742                            const SkScalar xpos[], SkScalar constY,
1743                            const SkPaint& paint) {
1744    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1745
1746    while (iter.next()) {
1747        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1748        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1749                                  dfp.paint());
1750    }
1751
1752    LOOPER_END
1753}
1754
1755void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1756                              const SkPath& path, const SkMatrix* matrix,
1757                              const SkPaint& paint) {
1758    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1759
1760    while (iter.next()) {
1761        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1762                                     matrix, looper.paint());
1763    }
1764
1765    LOOPER_END
1766}
1767
1768#ifdef SK_BUILD_FOR_ANDROID
1769void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1770                                 const SkPoint pos[], const SkPaint& paint,
1771                                 const SkPath& path, const SkMatrix* matrix) {
1772    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1773
1774    while (iter.next()) {
1775        iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1776                                        looper.paint(), path, matrix);
1777    }
1778
1779    LOOPER_END
1780}
1781#endif
1782
1783void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1784                            const SkPoint verts[], const SkPoint texs[],
1785                            const SkColor colors[], SkXfermode* xmode,
1786                            const uint16_t indices[], int indexCount,
1787                            const SkPaint& paint) {
1788    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1789
1790    while (iter.next()) {
1791        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1792                                   colors, xmode, indices, indexCount,
1793                                   looper.paint());
1794    }
1795
1796    LOOPER_END
1797}
1798
1799void SkCanvas::drawData(const void* data, size_t length) {
1800    // do nothing. Subclasses may do something with the data
1801}
1802
1803//////////////////////////////////////////////////////////////////////////////
1804// These methods are NOT virtual, and therefore must call back into virtual
1805// methods, rather than actually drawing themselves.
1806//////////////////////////////////////////////////////////////////////////////
1807
1808void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1809                        SkXfermode::Mode mode) {
1810    SkPaint paint;
1811
1812    paint.setARGB(a, r, g, b);
1813    if (SkXfermode::kSrcOver_Mode != mode) {
1814        paint.setXfermodeMode(mode);
1815    }
1816    this->drawPaint(paint);
1817}
1818
1819void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1820    SkPaint paint;
1821
1822    paint.setColor(c);
1823    if (SkXfermode::kSrcOver_Mode != mode) {
1824        paint.setXfermodeMode(mode);
1825    }
1826    this->drawPaint(paint);
1827}
1828
1829void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
1830    SkPoint pt;
1831
1832    pt.set(x, y);
1833    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1834}
1835
1836void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
1837    SkPoint pt;
1838    SkPaint paint;
1839
1840    pt.set(x, y);
1841    paint.setColor(color);
1842    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1843}
1844
1845void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
1846                        const SkPaint& paint) {
1847    SkPoint pts[2];
1848
1849    pts[0].set(x0, y0);
1850    pts[1].set(x1, y1);
1851    this->drawPoints(kLines_PointMode, 2, pts, paint);
1852}
1853
1854void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
1855                              SkScalar right, SkScalar bottom,
1856                              const SkPaint& paint) {
1857    SkRect  r;
1858
1859    r.set(left, top, right, bottom);
1860    this->drawRect(r, paint);
1861}
1862
1863void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
1864                          const SkPaint& paint) {
1865    if (radius < 0) {
1866        radius = 0;
1867    }
1868
1869    SkRect  r;
1870    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
1871
1872    if (paint.canComputeFastBounds()) {
1873        SkRect storage;
1874        if (this->quickReject(paint.computeFastBounds(r, &storage),
1875                              paint2EdgeType(&paint))) {
1876            return;
1877        }
1878    }
1879
1880    SkPath  path;
1881    path.addOval(r);
1882    this->drawPath(path, paint);
1883}
1884
1885void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
1886                             const SkPaint& paint) {
1887    if (rx > 0 && ry > 0) {
1888        if (paint.canComputeFastBounds()) {
1889            SkRect storage;
1890            if (this->quickReject(paint.computeFastBounds(r, &storage),
1891                                  paint2EdgeType(&paint))) {
1892                return;
1893            }
1894        }
1895
1896        SkPath  path;
1897        path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
1898        this->drawPath(path, paint);
1899    } else {
1900        this->drawRect(r, paint);
1901    }
1902}
1903
1904void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1905    if (paint.canComputeFastBounds()) {
1906        SkRect storage;
1907        if (this->quickReject(paint.computeFastBounds(oval, &storage),
1908                              paint2EdgeType(&paint))) {
1909            return;
1910        }
1911    }
1912
1913    SkPath  path;
1914    path.addOval(oval);
1915    this->drawPath(path, paint);
1916}
1917
1918void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
1919                       SkScalar sweepAngle, bool useCenter,
1920                       const SkPaint& paint) {
1921    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
1922        this->drawOval(oval, paint);
1923    } else {
1924        SkPath  path;
1925        if (useCenter) {
1926            path.moveTo(oval.centerX(), oval.centerY());
1927        }
1928        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
1929        if (useCenter) {
1930            path.close();
1931        }
1932        this->drawPath(path, paint);
1933    }
1934}
1935
1936void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
1937                                const SkPath& path, SkScalar hOffset,
1938                                SkScalar vOffset, const SkPaint& paint) {
1939    SkMatrix    matrix;
1940
1941    matrix.setTranslate(hOffset, vOffset);
1942    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
1943}
1944
1945///////////////////////////////////////////////////////////////////////////////
1946
1947void SkCanvas::drawPicture(SkPicture& picture) {
1948    int saveCount = save();
1949    picture.draw(this);
1950    restoreToCount(saveCount);
1951}
1952
1953///////////////////////////////////////////////////////////////////////////////
1954///////////////////////////////////////////////////////////////////////////////
1955
1956SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1957    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
1958
1959    SkASSERT(canvas);
1960
1961    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
1962    fDone = !fImpl->next();
1963}
1964
1965SkCanvas::LayerIter::~LayerIter() {
1966    fImpl->~SkDrawIter();
1967}
1968
1969void SkCanvas::LayerIter::next() {
1970    fDone = !fImpl->next();
1971}
1972
1973SkDevice* SkCanvas::LayerIter::device() const {
1974    return fImpl->getDevice();
1975}
1976
1977const SkMatrix& SkCanvas::LayerIter::matrix() const {
1978    return fImpl->getMatrix();
1979}
1980
1981const SkPaint& SkCanvas::LayerIter::paint() const {
1982    const SkPaint* paint = fImpl->getPaint();
1983    if (NULL == paint) {
1984        paint = &fDefaultPaint;
1985    }
1986    return *paint;
1987}
1988
1989const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
1990int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
1991int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
1992