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