SkCanvas.cpp revision e87e383351e1547b21d96d02bcd0c3cbbe0837f1
1/*
2 * Copyright 2008 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkCanvas.h"
9#include "SkCanvasDrawable.h"
10#include "SkCanvasPriv.h"
11#include "SkBitmapDevice.h"
12#include "SkDeviceImageFilterProxy.h"
13#include "SkDraw.h"
14#include "SkDrawFilter.h"
15#include "SkDrawLooper.h"
16#include "SkImage.h"
17#include "SkMetaData.h"
18#include "SkPathOps.h"
19#include "SkPatchUtils.h"
20#include "SkPicture.h"
21#include "SkRasterClip.h"
22#include "SkReadPixelsRec.h"
23#include "SkRRect.h"
24#include "SkSmallAllocator.h"
25#include "SkSurface_Base.h"
26#include "SkTemplates.h"
27#include "SkTextBlob.h"
28#include "SkTextFormatParams.h"
29#include "SkTLazy.h"
30#include "SkTraceEvent.h"
31#include "SkUtils.h"
32
33#if SK_SUPPORT_GPU
34#include "GrRenderTarget.h"
35#endif
36
37static bool gIgnoreSaveLayerBounds;
38void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
39    gIgnoreSaveLayerBounds = ignore;
40}
41bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
42    return gIgnoreSaveLayerBounds;
43}
44
45static bool gTreatSpriteAsBitmap;
46void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
47    gTreatSpriteAsBitmap = spriteAsBitmap;
48}
49bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
50    return gTreatSpriteAsBitmap;
51}
52
53// experimental for faster tiled drawing...
54//#define SK_ENABLE_CLIP_QUICKREJECT
55
56//#define SK_TRACE_SAVERESTORE
57
58#ifdef SK_TRACE_SAVERESTORE
59    static int gLayerCounter;
60    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
61    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
62
63    static int gRecCounter;
64    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
65    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
66
67    static int gCanvasCounter;
68    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
69    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
70#else
71    #define inc_layer()
72    #define dec_layer()
73    #define inc_rec()
74    #define dec_rec()
75    #define inc_canvas()
76    #define dec_canvas()
77#endif
78
79typedef SkTLazy<SkPaint> SkLazyPaint;
80
81void SkCanvas::predrawNotify() {
82    if (fSurfaceBase) {
83        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
84    }
85}
86
87///////////////////////////////////////////////////////////////////////////////
88
89static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
90    const uint32_t propFlags = props.flags();
91    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
92        flags &= ~SkPaint::kDither_Flag;
93    }
94    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
95        flags &= ~SkPaint::kAntiAlias_Flag;
96    }
97    return flags;
98}
99
100///////////////////////////////////////////////////////////////////////////////
101
102/*  This is the record we keep for each SkBaseDevice that the user installs.
103    The clip/matrix/proc are fields that reflect the top of the save/restore
104    stack. Whenever the canvas changes, it marks a dirty flag, and then before
105    these are used (assuming we're not on a layer) we rebuild these cache
106    values: they reflect the top of the save stack, but translated and clipped
107    by the device's XY offset and bitmap-bounds.
108*/
109struct DeviceCM {
110    DeviceCM*           fNext;
111    SkBaseDevice*       fDevice;
112    SkRasterClip        fClip;
113    const SkMatrix*     fMatrix;
114    SkPaint*            fPaint; // may be null (in the future)
115
116    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas,
117             bool conservativeRasterClip)
118        : fNext(NULL)
119        , fClip(conservativeRasterClip)
120    {
121        if (NULL != device) {
122            device->ref();
123            device->onAttachToCanvas(canvas);
124        }
125        fDevice = device;
126        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
127    }
128
129    ~DeviceCM() {
130        if (fDevice) {
131            fDevice->onDetachFromCanvas();
132            fDevice->unref();
133        }
134        SkDELETE(fPaint);
135    }
136
137    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
138                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
139        int x = fDevice->getOrigin().x();
140        int y = fDevice->getOrigin().y();
141        int width = fDevice->width();
142        int height = fDevice->height();
143
144        if ((x | y) == 0) {
145            fMatrix = &totalMatrix;
146            fClip = totalClip;
147        } else {
148            fMatrixStorage = totalMatrix;
149            fMatrixStorage.postTranslate(SkIntToScalar(-x),
150                                         SkIntToScalar(-y));
151            fMatrix = &fMatrixStorage;
152
153            totalClip.translate(-x, -y, &fClip);
154        }
155
156        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
157
158        // intersect clip, but don't translate it (yet)
159
160        if (updateClip) {
161            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
162                           SkRegion::kDifference_Op);
163        }
164
165        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
166
167#ifdef SK_DEBUG
168        if (!fClip.isEmpty()) {
169            SkIRect deviceR;
170            deviceR.set(0, 0, width, height);
171            SkASSERT(deviceR.contains(fClip.getBounds()));
172        }
173#endif
174    }
175
176private:
177    SkMatrix    fMatrixStorage;
178};
179
180/*  This is the record we keep for each save/restore level in the stack.
181    Since a level optionally copies the matrix and/or stack, we have pointers
182    for these fields. If the value is copied for this level, the copy is
183    stored in the ...Storage field, and the pointer points to that. If the
184    value is not copied for this level, we ignore ...Storage, and just point
185    at the corresponding value in the previous level in the stack.
186*/
187class SkCanvas::MCRec {
188public:
189    SkDrawFilter*   fFilter;    // the current filter (or null)
190    DeviceCM*       fLayer;
191    /*  If there are any layers in the stack, this points to the top-most
192        one that is at or below this level in the stack (so we know what
193        bitmap/device to draw into from this level. This value is NOT
194        reference counted, since the real owner is either our fLayer field,
195        or a previous one in a lower level.)
196    */
197    DeviceCM*       fTopLayer;
198    SkRasterClip    fRasterClip;
199    SkMatrix        fMatrix;
200    int             fDeferredSaveCount;
201
202    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
203        fFilter     = NULL;
204        fLayer      = NULL;
205        fTopLayer   = NULL;
206        fMatrix.reset();
207        fDeferredSaveCount = 0;
208
209        // don't bother initializing fNext
210        inc_rec();
211    }
212    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
213        fFilter = SkSafeRef(prev.fFilter);
214        fLayer = NULL;
215        fTopLayer = prev.fTopLayer;
216        fDeferredSaveCount = 0;
217
218        // don't bother initializing fNext
219        inc_rec();
220    }
221    ~MCRec() {
222        SkSafeUnref(fFilter);
223        SkDELETE(fLayer);
224        dec_rec();
225    }
226};
227
228class SkDrawIter : public SkDraw {
229public:
230    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
231        canvas = canvas->canvasForDrawIter();
232        fCanvas = canvas;
233        canvas->updateDeviceCMCache();
234
235        fClipStack = &canvas->fClipStack;
236        fCurrLayer = canvas->fMCRec->fTopLayer;
237        fSkipEmptyClips = skipEmptyClips;
238    }
239
240    bool next() {
241        // skip over recs with empty clips
242        if (fSkipEmptyClips) {
243            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
244                fCurrLayer = fCurrLayer->fNext;
245            }
246        }
247
248        const DeviceCM* rec = fCurrLayer;
249        if (rec && rec->fDevice) {
250
251            fMatrix = rec->fMatrix;
252            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
253            fRC     = &rec->fClip;
254            fDevice = rec->fDevice;
255            fBitmap = &fDevice->accessBitmap(true);
256            fPaint  = rec->fPaint;
257            SkDEBUGCODE(this->validate();)
258
259            fCurrLayer = rec->fNext;
260            // fCurrLayer may be NULL now
261
262            return true;
263        }
264        return false;
265    }
266
267    SkBaseDevice* getDevice() const { return fDevice; }
268    int getX() const { return fDevice->getOrigin().x(); }
269    int getY() const { return fDevice->getOrigin().y(); }
270    const SkMatrix& getMatrix() const { return *fMatrix; }
271    const SkRegion& getClip() const { return *fClip; }
272    const SkPaint* getPaint() const { return fPaint; }
273
274private:
275    SkCanvas*       fCanvas;
276    const DeviceCM* fCurrLayer;
277    const SkPaint*  fPaint;     // May be null.
278    SkBool8         fSkipEmptyClips;
279
280    typedef SkDraw INHERITED;
281};
282
283/////////////////////////////////////////////////////////////////////////////
284
285class AutoDrawLooper {
286public:
287    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
288                   bool skipLayerForImageFilter = false,
289                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
290        fCanvas = canvas;
291        fFilter = canvas->getDrawFilter();
292        fPaint = &fOrigPaint;
293        fSaveCount = canvas->getSaveCount();
294        fDoClearImageFilter = false;
295        fDone = false;
296
297        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
298            SkPaint tmp;
299            tmp.setImageFilter(fOrigPaint.getImageFilter());
300            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
301                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
302            // we'll clear the imageFilter for the actual draws in next(), so
303            // it will only be applied during the restore().
304            fDoClearImageFilter = true;
305        }
306
307        if (SkDrawLooper* looper = paint.getLooper()) {
308            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
309                    looper->contextSize());
310            fLooperContext = looper->createContext(canvas, buffer);
311            fIsSimple = false;
312        } else {
313            fLooperContext = NULL;
314            // can we be marked as simple?
315            fIsSimple = !fFilter && !fDoClearImageFilter;
316        }
317
318        uint32_t oldFlags = paint.getFlags();
319        fNewPaintFlags = filter_paint_flags(props, oldFlags);
320        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
321            SkPaint* paint = fLazyPaint.set(fOrigPaint);
322            paint->setFlags(fNewPaintFlags);
323            fPaint = paint;
324            // if we're not simple, doNext() will take care of calling setFlags()
325        }
326    }
327
328    ~AutoDrawLooper() {
329        if (fDoClearImageFilter) {
330            fCanvas->internalRestore();
331        }
332        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
333    }
334
335    const SkPaint& paint() const {
336        SkASSERT(fPaint);
337        return *fPaint;
338    }
339
340    bool next(SkDrawFilter::Type drawType) {
341        if (fDone) {
342            return false;
343        } else if (fIsSimple) {
344            fDone = true;
345            return !fPaint->nothingToDraw();
346        } else {
347            return this->doNext(drawType);
348        }
349    }
350
351private:
352    SkLazyPaint     fLazyPaint;
353    SkCanvas*       fCanvas;
354    const SkPaint&  fOrigPaint;
355    SkDrawFilter*   fFilter;
356    const SkPaint*  fPaint;
357    int             fSaveCount;
358    uint32_t        fNewPaintFlags;
359    bool            fDoClearImageFilter;
360    bool            fDone;
361    bool            fIsSimple;
362    SkDrawLooper::Context* fLooperContext;
363    SkSmallAllocator<1, 32> fLooperContextAllocator;
364
365    bool doNext(SkDrawFilter::Type drawType);
366};
367
368bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
369    fPaint = NULL;
370    SkASSERT(!fIsSimple);
371    SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
372
373    SkPaint* paint = fLazyPaint.set(fOrigPaint);
374    paint->setFlags(fNewPaintFlags);
375
376    if (fDoClearImageFilter) {
377        paint->setImageFilter(NULL);
378    }
379
380    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
381        fDone = true;
382        return false;
383    }
384    if (fFilter) {
385        if (!fFilter->filter(paint, drawType)) {
386            fDone = true;
387            return false;
388        }
389        if (NULL == fLooperContext) {
390            // no looper means we only draw once
391            fDone = true;
392        }
393    }
394    fPaint = paint;
395
396    // if we only came in here for the imagefilter, mark us as done
397    if (!fLooperContext && !fFilter) {
398        fDone = true;
399    }
400
401    // call this after any possible paint modifiers
402    if (fPaint->nothingToDraw()) {
403        fPaint = NULL;
404        return false;
405    }
406    return true;
407}
408
409////////// macros to place around the internal draw calls //////////////////
410
411#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
412    this->predrawNotify();                                          \
413    AutoDrawLooper  looper(this, fProps, paint, true);              \
414    while (looper.next(type)) {                                     \
415        SkDrawIter          iter(this);
416
417#define LOOPER_BEGIN(paint, type, bounds)                           \
418    this->predrawNotify();                                          \
419    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
420    while (looper.next(type)) {                                     \
421        SkDrawIter          iter(this);
422
423#define LOOPER_END    }
424
425////////////////////////////////////////////////////////////////////////////
426
427SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
428    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
429    fCachedLocalClipBounds.setEmpty();
430    fCachedLocalClipBoundsDirty = true;
431    fAllowSoftClip = true;
432    fAllowSimplifyClip = false;
433    fDeviceCMDirty = true;
434    fSaveCount = 1;
435    fMetaData = NULL;
436
437    fMCRec = (MCRec*)fMCStack.push_back();
438    new (fMCRec) MCRec(fConservativeRasterClip);
439
440    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
441    fMCRec->fTopLayer = fMCRec->fLayer;
442
443    fSurfaceBase = NULL;
444
445    if (device) {
446        device->initForRootLayer(fProps.pixelGeometry());
447        if (device->forceConservativeRasterClip()) {
448            fConservativeRasterClip = true;
449        }
450        device->onAttachToCanvas(this);
451        fMCRec->fLayer->fDevice = SkRef(device);
452        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
453    }
454    return device;
455}
456
457SkCanvas::SkCanvas()
458    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
459    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
460{
461    inc_canvas();
462
463    this->init(NULL, kDefault_InitFlags);
464}
465
466static SkBitmap make_nopixels(int width, int height) {
467    SkBitmap bitmap;
468    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
469    return bitmap;
470}
471
472class SkNoPixelsBitmapDevice : public SkBitmapDevice {
473public:
474    SkNoPixelsBitmapDevice(const SkIRect& bounds)
475        : INHERITED(make_nopixels(bounds.width(), bounds.height()))
476    {
477        this->setOrigin(bounds.x(), bounds.y());
478    }
479
480private:
481
482    typedef SkBitmapDevice INHERITED;
483};
484
485SkCanvas::SkCanvas(int width, int height)
486    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
487    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
488{
489    inc_canvas();
490
491    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
492                          (SkIRect::MakeWH(width, height))), kDefault_InitFlags)->unref();
493}
494
495SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
496    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
497    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
498{
499    inc_canvas();
500
501    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds)), flags)->unref();
502}
503
504SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
505    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
506    , fProps(SkSurfacePropsCopyOrDefault(props))
507{
508    inc_canvas();
509
510    this->init(device, flags);
511}
512
513SkCanvas::SkCanvas(SkBaseDevice* device)
514    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
515    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
516{
517    inc_canvas();
518
519    this->init(device, kDefault_InitFlags);
520}
521
522SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
523    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
524    , fProps(props)
525{
526    inc_canvas();
527
528    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
529    this->init(device, kDefault_InitFlags);
530}
531
532SkCanvas::SkCanvas(const SkBitmap& bitmap)
533    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
534    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
535{
536    inc_canvas();
537
538    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
539    this->init(device, kDefault_InitFlags);
540}
541
542SkCanvas::~SkCanvas() {
543    // free up the contents of our deque
544    this->restoreToCount(1);    // restore everything but the last
545
546    this->internalRestore();    // restore the last, since we're going away
547
548    SkDELETE(fMetaData);
549
550    dec_canvas();
551}
552
553SkDrawFilter* SkCanvas::getDrawFilter() const {
554    return fMCRec->fFilter;
555}
556
557SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
558    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
559    return filter;
560}
561
562SkMetaData& SkCanvas::getMetaData() {
563    // metadata users are rare, so we lazily allocate it. If that changes we
564    // can decide to just make it a field in the device (rather than a ptr)
565    if (NULL == fMetaData) {
566        fMetaData = new SkMetaData;
567    }
568    return *fMetaData;
569}
570
571///////////////////////////////////////////////////////////////////////////////
572
573void SkCanvas::flush() {
574    SkBaseDevice* device = this->getDevice();
575    if (device) {
576        device->flush();
577    }
578}
579
580SkISize SkCanvas::getTopLayerSize() const {
581    SkBaseDevice* d = this->getTopDevice();
582    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
583}
584
585SkIPoint SkCanvas::getTopLayerOrigin() const {
586    SkBaseDevice* d = this->getTopDevice();
587    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
588}
589
590SkISize SkCanvas::getBaseLayerSize() const {
591    SkBaseDevice* d = this->getDevice();
592    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
593}
594
595SkBaseDevice* SkCanvas::getDevice() const {
596    // return root device
597    MCRec* rec = (MCRec*) fMCStack.front();
598    SkASSERT(rec && rec->fLayer);
599    return rec->fLayer->fDevice;
600}
601
602SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
603    if (updateMatrixClip) {
604        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
605    }
606    return fMCRec->fTopLayer->fDevice;
607}
608
609SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
610    // return root device
611    SkDeque::F2BIter iter(fMCStack);
612    MCRec*           rec = (MCRec*)iter.next();
613    SkASSERT(rec && rec->fLayer);
614    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
615
616    if (rootDevice == device) {
617        return device;
618    }
619
620    if (device) {
621        device->onAttachToCanvas(this);
622        device->initForRootLayer(fProps.pixelGeometry());
623    }
624    if (rootDevice) {
625        rootDevice->onDetachFromCanvas();
626    }
627
628    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
629    rootDevice = device;
630
631    fDeviceCMDirty = true;
632
633    /*  Now we update our initial region to have the bounds of the new device,
634        and then intersect all of the clips in our stack with these bounds,
635        to ensure that we can't draw outside of the device's bounds (and trash
636                                                                     memory).
637
638    NOTE: this is only a partial-fix, since if the new device is larger than
639        the previous one, we don't know how to "enlarge" the clips in our stack,
640        so drawing may be artificially restricted. Without keeping a history of
641        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
642        reconstruct the correct clips, so this approximation will have to do.
643        The caller really needs to restore() back to the base if they want to
644        accurately take advantage of the new device bounds.
645    */
646
647    SkIRect bounds;
648    if (device) {
649        bounds.set(0, 0, device->width(), device->height());
650    } else {
651        bounds.setEmpty();
652    }
653    // now jam our 1st clip to be bounds, and intersect the rest with that
654    rec->fRasterClip.setRect(bounds);
655    while ((rec = (MCRec*)iter.next()) != NULL) {
656        (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op);
657    }
658
659    return device;
660}
661
662bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
663    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
664        return false;
665    }
666
667    bool weAllocated = false;
668    if (NULL == bitmap->pixelRef()) {
669        if (!bitmap->tryAllocPixels()) {
670            return false;
671        }
672        weAllocated = true;
673    }
674
675    SkBitmap bm(*bitmap);
676    bm.lockPixels();
677    if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
678        return true;
679    }
680
681    if (weAllocated) {
682        bitmap->setPixelRef(NULL);
683    }
684    return false;
685}
686
687bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
688    SkIRect r = srcRect;
689    const SkISize size = this->getBaseLayerSize();
690    if (!r.intersect(0, 0, size.width(), size.height())) {
691        bitmap->reset();
692        return false;
693    }
694
695    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
696        // bitmap will already be reset.
697        return false;
698    }
699    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
700        bitmap->reset();
701        return false;
702    }
703    return true;
704}
705
706bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
707    SkBaseDevice* device = this->getDevice();
708    if (!device) {
709        return false;
710    }
711    const SkISize size = this->getBaseLayerSize();
712
713    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
714    if (!rec.trim(size.width(), size.height())) {
715        return false;
716    }
717
718    // The device can assert that the requested area is always contained in its bounds
719    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
720}
721
722bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
723    if (bitmap.getTexture()) {
724        return false;
725    }
726    SkBitmap bm(bitmap);
727    bm.lockPixels();
728    if (bm.getPixels()) {
729        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
730    }
731    return false;
732}
733
734bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
735                           int x, int y) {
736    switch (origInfo.colorType()) {
737        case kUnknown_SkColorType:
738        case kIndex_8_SkColorType:
739            return false;
740        default:
741            break;
742    }
743    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
744        return false;
745    }
746
747    const SkISize size = this->getBaseLayerSize();
748    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
749    if (!target.intersect(0, 0, size.width(), size.height())) {
750        return false;
751    }
752
753    SkBaseDevice* device = this->getDevice();
754    if (!device) {
755        return false;
756    }
757
758    // the intersect may have shrunk info's logical size
759    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
760
761    // if x or y are negative, then we have to adjust pixels
762    if (x > 0) {
763        x = 0;
764    }
765    if (y > 0) {
766        y = 0;
767    }
768    // here x,y are either 0 or negative
769    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
770
771    // Tell our owning surface to bump its generation ID
772    this->predrawNotify();
773
774    // The device can assert that the requested area is always contained in its bounds
775    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
776}
777
778SkCanvas* SkCanvas::canvasForDrawIter() {
779    return this;
780}
781
782//////////////////////////////////////////////////////////////////////////////
783
784void SkCanvas::updateDeviceCMCache() {
785    if (fDeviceCMDirty) {
786        const SkMatrix& totalMatrix = this->getTotalMatrix();
787        const SkRasterClip& totalClip = fMCRec->fRasterClip;
788        DeviceCM*       layer = fMCRec->fTopLayer;
789
790        if (NULL == layer->fNext) {   // only one layer
791            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
792        } else {
793            SkRasterClip clip(totalClip);
794            do {
795                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
796            } while ((layer = layer->fNext) != NULL);
797        }
798        fDeviceCMDirty = false;
799    }
800}
801
802///////////////////////////////////////////////////////////////////////////////
803
804void SkCanvas::checkForDeferredSave() {
805    if (fMCRec->fDeferredSaveCount > 0) {
806        fMCRec->fDeferredSaveCount -= 1;
807        this->doSave();
808    }
809}
810
811int SkCanvas::getSaveCount() const {
812#ifdef SK_DEBUG
813    int count = 0;
814    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
815    for (;;) {
816        const MCRec* rec = (const MCRec*)iter.next();
817        if (!rec) {
818            break;
819        }
820        count += 1 + rec->fDeferredSaveCount;
821    }
822    SkASSERT(count == fSaveCount);
823#endif
824    return fSaveCount;
825}
826
827int SkCanvas::save() {
828    fSaveCount += 1;
829    fMCRec->fDeferredSaveCount += 1;
830    return this->getSaveCount() - 1;  // return our prev value
831}
832
833void SkCanvas::doSave() {
834    this->willSave();
835    this->internalSave();
836}
837
838void SkCanvas::restore() {
839    if (fMCRec->fDeferredSaveCount > 0) {
840        SkASSERT(fSaveCount > 1);
841        fSaveCount -= 1;
842        fMCRec->fDeferredSaveCount -= 1;
843    } else {
844        // check for underflow
845        if (fMCStack.count() > 1) {
846            this->willRestore();
847            SkASSERT(fSaveCount > 1);
848            fSaveCount -= 1;
849            this->internalRestore();
850            this->didRestore();
851        }
852    }
853}
854
855void SkCanvas::restoreToCount(int count) {
856    // sanity check
857    if (count < 1) {
858        count = 1;
859    }
860
861    int n = this->getSaveCount() - count;
862    for (int i = 0; i < n; ++i) {
863        this->restore();
864    }
865}
866
867void SkCanvas::internalSave() {
868    MCRec* newTop = (MCRec*)fMCStack.push_back();
869    new (newTop) MCRec(*fMCRec);    // balanced in restore()
870    fMCRec = newTop;
871
872    fClipStack.save();
873}
874
875static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
876#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
877    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
878#else
879    return true;
880#endif
881}
882
883bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
884                               SkIRect* intersection, const SkImageFilter* imageFilter) {
885    SkIRect clipBounds;
886    SkRegion::Op op = SkRegion::kIntersect_Op;
887    if (!this->getClipDeviceBounds(&clipBounds)) {
888        return false;
889    }
890
891    if (imageFilter) {
892        imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
893        // Filters may grow the bounds beyond the device bounds.
894        op = SkRegion::kReplace_Op;
895    }
896    SkIRect ir;
897    if (bounds) {
898        SkRect r;
899
900        this->getTotalMatrix().mapRect(&r, *bounds);
901        r.roundOut(&ir);
902        // early exit if the layer's bounds are clipped out
903        if (!ir.intersect(clipBounds)) {
904            if (bounds_affects_clip(flags)) {
905                fMCRec->fRasterClip.setEmpty();
906            }
907            return false;
908        }
909    } else {    // no user bounds, so just use the clip
910        ir = clipBounds;
911    }
912
913    if (bounds_affects_clip(flags)) {
914        fClipStack.clipDevRect(ir, op);
915        // early exit if the clip is now empty
916        if (!fMCRec->fRasterClip.op(ir, op)) {
917            return false;
918        }
919    }
920
921    if (intersection) {
922        *intersection = ir;
923    }
924    return true;
925}
926
927int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
928    if (gIgnoreSaveLayerBounds) {
929        bounds = NULL;
930    }
931    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
932    fSaveCount += 1;
933    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
934    return this->getSaveCount() - 1;
935}
936
937int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
938    if (gIgnoreSaveLayerBounds) {
939        bounds = NULL;
940    }
941    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
942    fSaveCount += 1;
943    this->internalSaveLayer(bounds, paint, flags, false, strategy);
944    return this->getSaveCount() - 1;
945}
946
947void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
948                                bool justForImageFilter, SaveLayerStrategy strategy) {
949#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
950    flags |= kClipToLayer_SaveFlag;
951#endif
952
953    // do this before we create the layer. We don't call the public save() since
954    // that would invoke a possibly overridden virtual
955    this->internalSave();
956
957    fDeviceCMDirty = true;
958
959    SkIRect ir;
960    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
961        return;
962    }
963
964    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
965    // the clipRectBounds() call above?
966    if (kNoLayer_SaveLayerStrategy == strategy) {
967        return;
968    }
969
970    // Kill the imagefilter if our device doesn't allow it
971    SkLazyPaint lazyP;
972    if (paint && paint->getImageFilter()) {
973        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
974            if (justForImageFilter) {
975                // early exit if the layer was just for the imageFilter
976                return;
977            }
978            SkPaint* p = lazyP.set(*paint);
979            p->setImageFilter(NULL);
980            paint = p;
981        }
982    }
983
984    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
985    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
986                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
987
988    SkBaseDevice* device = this->getTopDevice();
989    if (NULL == device) {
990        SkDebugf("Unable to find device for layer.");
991        return;
992    }
993
994    SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage;
995    if (paint && paint->getImageFilter()) {
996        usage = SkBaseDevice::kImageFilter_Usage;
997    }
998    device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage,
999                                                                       fProps.pixelGeometry()));
1000    if (NULL == device) {
1001        SkDebugf("Unable to create device for layer.");
1002        return;
1003    }
1004
1005    device->setOrigin(ir.fLeft, ir.fTop);
1006    DeviceCM* layer = SkNEW_ARGS(DeviceCM,
1007                                 (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
1008    device->unref();
1009
1010    layer->fNext = fMCRec->fTopLayer;
1011    fMCRec->fLayer = layer;
1012    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1013}
1014
1015int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1016    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1017}
1018
1019int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
1020                             SaveFlags flags) {
1021    if (0xFF == alpha) {
1022        return this->saveLayer(bounds, NULL, flags);
1023    } else {
1024        SkPaint tmpPaint;
1025        tmpPaint.setAlpha(alpha);
1026        return this->saveLayer(bounds, &tmpPaint, flags);
1027    }
1028}
1029
1030void SkCanvas::internalRestore() {
1031    SkASSERT(fMCStack.count() != 0);
1032
1033    fDeviceCMDirty = true;
1034    fCachedLocalClipBoundsDirty = true;
1035
1036    fClipStack.restore();
1037
1038    // reserve our layer (if any)
1039    DeviceCM* layer = fMCRec->fLayer;   // may be null
1040    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1041    fMCRec->fLayer = NULL;
1042
1043    // now do the normal restore()
1044    fMCRec->~MCRec();       // balanced in save()
1045    fMCStack.pop_back();
1046    fMCRec = (MCRec*)fMCStack.back();
1047
1048    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1049        since if we're being recorded, we don't want to record this (the
1050        recorder will have already recorded the restore).
1051    */
1052    if (layer) {
1053        if (layer->fNext) {
1054            const SkIPoint& origin = layer->fDevice->getOrigin();
1055            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1056                                     layer->fPaint);
1057            // reset this, since internalDrawDevice will have set it to true
1058            fDeviceCMDirty = true;
1059        }
1060        SkDELETE(layer);
1061    }
1062}
1063
1064SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1065    if (NULL == props) {
1066        props = &fProps;
1067    }
1068    return this->onNewSurface(info, *props);
1069}
1070
1071SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1072    SkBaseDevice* dev = this->getDevice();
1073    return dev ? dev->newSurface(info, props) : NULL;
1074}
1075
1076SkImageInfo SkCanvas::imageInfo() const {
1077    SkBaseDevice* dev = this->getDevice();
1078    if (dev) {
1079        return dev->imageInfo();
1080    } else {
1081        return SkImageInfo::MakeUnknown(0, 0);
1082    }
1083}
1084
1085const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1086    return this->onPeekPixels(info, rowBytes);
1087}
1088
1089const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1090    SkBaseDevice* dev = this->getDevice();
1091    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1092}
1093
1094void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1095    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
1096    if (pixels && origin) {
1097        *origin = this->getTopDevice(false)->getOrigin();
1098    }
1099    return pixels;
1100}
1101
1102void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
1103    SkBaseDevice* dev = this->getTopDevice();
1104    return dev ? dev->accessPixels(info, rowBytes) : NULL;
1105}
1106
1107SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1108    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1109    if (NULL == fAddr) {
1110        fInfo = canvas->imageInfo();
1111        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1112            return; // failure, fAddr is NULL
1113        }
1114        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1115            return; // failure, fAddr is NULL
1116        }
1117        fAddr = fBitmap.getPixels();
1118        fRowBytes = fBitmap.rowBytes();
1119    }
1120    SkASSERT(fAddr);    // success
1121}
1122
1123bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1124    if (fAddr) {
1125        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1126    } else {
1127        bitmap->reset();
1128        return false;
1129    }
1130}
1131
1132/////////////////////////////////////////////////////////////////////////////
1133void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1134                                const SkMatrix& matrix, const SkPaint* paint) {
1135    if (bitmap.drawsNothing()) {
1136        return;
1137    }
1138
1139    SkLazyPaint lazy;
1140    if (NULL == paint) {
1141        paint = lazy.init();
1142    }
1143
1144    SkDEBUGCODE(bitmap.validate();)
1145
1146    SkRect storage;
1147    const SkRect* bounds = NULL;
1148    if (paint && paint->canComputeFastBounds()) {
1149        bitmap.getBounds(&storage);
1150        matrix.mapRect(&storage);
1151        bounds = &paint->computeFastBounds(storage, &storage);
1152    }
1153
1154    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1155
1156    while (iter.next()) {
1157        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1158    }
1159
1160    LOOPER_END
1161}
1162
1163void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1164                                  const SkPaint* paint) {
1165    SkPaint tmp;
1166    if (NULL == paint) {
1167        paint = &tmp;
1168    }
1169
1170    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1171    while (iter.next()) {
1172        SkBaseDevice* dstDev = iter.fDevice;
1173        paint = &looper.paint();
1174        SkImageFilter* filter = paint->getImageFilter();
1175        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1176        if (filter && !dstDev->canHandleImageFilter(filter)) {
1177            SkDeviceImageFilterProxy proxy(dstDev, fProps);
1178            SkBitmap dst;
1179            SkIPoint offset = SkIPoint::Make(0, 0);
1180            const SkBitmap& src = srcDev->accessBitmap(false);
1181            SkMatrix matrix = *iter.fMatrix;
1182            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1183            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1184            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1185            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1186            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1187                SkPaint tmpUnfiltered(*paint);
1188                tmpUnfiltered.setImageFilter(NULL);
1189                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1190                                   tmpUnfiltered);
1191            }
1192        } else {
1193            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1194        }
1195    }
1196    LOOPER_END
1197}
1198
1199void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1200                          const SkPaint* paint) {
1201    if (gTreatSpriteAsBitmap) {
1202        this->save();
1203        this->resetMatrix();
1204        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
1205        this->restore();
1206        return;
1207    }
1208
1209    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
1210    if (bitmap.drawsNothing()) {
1211        return;
1212    }
1213    SkDEBUGCODE(bitmap.validate();)
1214
1215    SkPaint tmp;
1216    if (NULL == paint) {
1217        paint = &tmp;
1218    }
1219
1220    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1221
1222    while (iter.next()) {
1223        paint = &looper.paint();
1224        SkImageFilter* filter = paint->getImageFilter();
1225        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1226        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1227            SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
1228            SkBitmap dst;
1229            SkIPoint offset = SkIPoint::Make(0, 0);
1230            SkMatrix matrix = *iter.fMatrix;
1231            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1232            const SkIRect clipBounds = bitmap.bounds();
1233            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
1234            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1235            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1236                SkPaint tmpUnfiltered(*paint);
1237                tmpUnfiltered.setImageFilter(NULL);
1238                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1239                                         tmpUnfiltered);
1240            }
1241        } else {
1242            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1243        }
1244    }
1245    LOOPER_END
1246}
1247
1248/////////////////////////////////////////////////////////////////////////////
1249void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1250    SkMatrix m;
1251    m.setTranslate(dx, dy);
1252    this->concat(m);
1253}
1254
1255void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1256    SkMatrix m;
1257    m.setScale(sx, sy);
1258    this->concat(m);
1259}
1260
1261void SkCanvas::rotate(SkScalar degrees) {
1262    SkMatrix m;
1263    m.setRotate(degrees);
1264    this->concat(m);
1265}
1266
1267void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1268    SkMatrix m;
1269    m.setSkew(sx, sy);
1270    this->concat(m);
1271}
1272
1273void SkCanvas::concat(const SkMatrix& matrix) {
1274    if (matrix.isIdentity()) {
1275        return;
1276    }
1277
1278    this->checkForDeferredSave();
1279    fDeviceCMDirty = true;
1280    fCachedLocalClipBoundsDirty = true;
1281    fMCRec->fMatrix.preConcat(matrix);
1282
1283    this->didConcat(matrix);
1284}
1285
1286void SkCanvas::setMatrix(const SkMatrix& matrix) {
1287    this->checkForDeferredSave();
1288    fDeviceCMDirty = true;
1289    fCachedLocalClipBoundsDirty = true;
1290    fMCRec->fMatrix = matrix;
1291    this->didSetMatrix(matrix);
1292}
1293
1294void SkCanvas::resetMatrix() {
1295    SkMatrix matrix;
1296
1297    matrix.reset();
1298    this->setMatrix(matrix);
1299}
1300
1301//////////////////////////////////////////////////////////////////////////////
1302
1303void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1304    this->checkForDeferredSave();
1305    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1306    this->onClipRect(rect, op, edgeStyle);
1307}
1308
1309void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1310#ifdef SK_ENABLE_CLIP_QUICKREJECT
1311    if (SkRegion::kIntersect_Op == op) {
1312        if (fMCRec->fRasterClip.isEmpty()) {
1313            return false;
1314        }
1315
1316        if (this->quickReject(rect)) {
1317            fDeviceCMDirty = true;
1318            fCachedLocalClipBoundsDirty = true;
1319
1320            fClipStack.clipEmpty();
1321            return fMCRec->fRasterClip.setEmpty();
1322        }
1323    }
1324#endif
1325
1326    AutoValidateClip avc(this);
1327
1328    fDeviceCMDirty = true;
1329    fCachedLocalClipBoundsDirty = true;
1330    if (!fAllowSoftClip) {
1331        edgeStyle = kHard_ClipEdgeStyle;
1332    }
1333
1334    if (fMCRec->fMatrix.rectStaysRect()) {
1335        // for these simpler matrices, we can stay a rect even after applying
1336        // the matrix. This means we don't have to a) make a path, and b) tell
1337        // the region code to scan-convert the path, only to discover that it
1338        // is really just a rect.
1339        SkRect      r;
1340
1341        fMCRec->fMatrix.mapRect(&r, rect);
1342        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1343        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
1344    } else {
1345        // since we're rotated or some such thing, we convert the rect to a path
1346        // and clip against that, since it can handle any matrix. However, to
1347        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1348        // we explicitly call "our" version of clipPath.
1349        SkPath  path;
1350
1351        path.addRect(rect);
1352        this->SkCanvas::onClipPath(path, op, edgeStyle);
1353    }
1354}
1355
1356static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
1357                            SkRegion::Op op, bool doAA) {
1358    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1359}
1360
1361void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1362    this->checkForDeferredSave();
1363    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1364    if (rrect.isRect()) {
1365        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1366    } else {
1367        this->onClipRRect(rrect, op, edgeStyle);
1368    }
1369}
1370
1371void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1372    SkRRect transformedRRect;
1373    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1374        AutoValidateClip avc(this);
1375
1376        fDeviceCMDirty = true;
1377        fCachedLocalClipBoundsDirty = true;
1378        if (!fAllowSoftClip) {
1379            edgeStyle = kHard_ClipEdgeStyle;
1380        }
1381
1382        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1383
1384        SkPath devPath;
1385        devPath.addRRect(transformedRRect);
1386
1387        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1388        return;
1389    }
1390
1391    SkPath path;
1392    path.addRRect(rrect);
1393    // call the non-virtual version
1394    this->SkCanvas::onClipPath(path, op, edgeStyle);
1395}
1396
1397void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1398    this->checkForDeferredSave();
1399    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1400    SkRect r;
1401    if (!path.isInverseFillType() && path.isRect(&r)) {
1402        this->onClipRect(r, op, edgeStyle);
1403    } else {
1404        this->onClipPath(path, op, edgeStyle);
1405    }
1406}
1407
1408void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1409#ifdef SK_ENABLE_CLIP_QUICKREJECT
1410    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1411        if (fMCRec->fRasterClip.isEmpty()) {
1412            return false;
1413        }
1414
1415        if (this->quickReject(path.getBounds())) {
1416            fDeviceCMDirty = true;
1417            fCachedLocalClipBoundsDirty = true;
1418
1419            fClipStack.clipEmpty();
1420            return fMCRec->fRasterClip.setEmpty();
1421        }
1422    }
1423#endif
1424
1425    AutoValidateClip avc(this);
1426
1427    fDeviceCMDirty = true;
1428    fCachedLocalClipBoundsDirty = true;
1429    if (!fAllowSoftClip) {
1430        edgeStyle = kHard_ClipEdgeStyle;
1431    }
1432
1433    SkPath devPath;
1434    path.transform(fMCRec->fMatrix, &devPath);
1435
1436    // Check if the transfomation, or the original path itself
1437    // made us empty. Note this can also happen if we contained NaN
1438    // values. computing the bounds detects this, and will set our
1439    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1440    if (devPath.getBounds().isEmpty()) {
1441        // resetting the path will remove any NaN or other wanky values
1442        // that might upset our scan converter.
1443        devPath.reset();
1444    }
1445
1446    // if we called path.swap() we could avoid a deep copy of this path
1447    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1448
1449    if (fAllowSimplifyClip) {
1450        devPath.reset();
1451        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1452        const SkClipStack* clipStack = getClipStack();
1453        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
1454        const SkClipStack::Element* element;
1455        while ((element = iter.next())) {
1456            SkClipStack::Element::Type type = element->getType();
1457            SkPath operand;
1458            if (type != SkClipStack::Element::kEmpty_Type) {
1459                element->asPath(&operand);
1460            }
1461            SkRegion::Op elementOp = element->getOp();
1462            if (elementOp == SkRegion::kReplace_Op) {
1463                devPath = operand;
1464            } else {
1465                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1466            }
1467            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1468            // perhaps we need an API change to avoid this sort of mixed-signals about
1469            // clipping.
1470            if (element->isAA()) {
1471                edgeStyle = kSoft_ClipEdgeStyle;
1472            }
1473        }
1474        op = SkRegion::kReplace_Op;
1475    }
1476
1477    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1478}
1479
1480void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1481    this->checkForDeferredSave();
1482    this->onClipRegion(rgn, op);
1483}
1484
1485void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1486    AutoValidateClip avc(this);
1487
1488    fDeviceCMDirty = true;
1489    fCachedLocalClipBoundsDirty = true;
1490
1491    // todo: signal fClipStack that we have a region, and therefore (I guess)
1492    // we have to ignore it, and use the region directly?
1493    fClipStack.clipDevRect(rgn.getBounds(), op);
1494
1495    fMCRec->fRasterClip.op(rgn, op);
1496}
1497
1498#ifdef SK_DEBUG
1499void SkCanvas::validateClip() const {
1500    // construct clipRgn from the clipstack
1501    const SkBaseDevice* device = this->getDevice();
1502    if (!device) {
1503        SkASSERT(this->isClipEmpty());
1504        return;
1505    }
1506
1507    SkIRect ir;
1508    ir.set(0, 0, device->width(), device->height());
1509    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1510
1511    SkClipStack::B2TIter                iter(fClipStack);
1512    const SkClipStack::Element* element;
1513    while ((element = iter.next()) != NULL) {
1514        switch (element->getType()) {
1515            case SkClipStack::Element::kRect_Type:
1516                element->getRect().round(&ir);
1517                tmpClip.op(ir, element->getOp());
1518                break;
1519            case SkClipStack::Element::kEmpty_Type:
1520                tmpClip.setEmpty();
1521                break;
1522            default: {
1523                SkPath path;
1524                element->asPath(&path);
1525                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
1526                break;
1527            }
1528        }
1529    }
1530}
1531#endif
1532
1533void SkCanvas::replayClips(ClipVisitor* visitor) const {
1534    SkClipStack::B2TIter                iter(fClipStack);
1535    const SkClipStack::Element*         element;
1536
1537    while ((element = iter.next()) != NULL) {
1538        element->replay(visitor);
1539    }
1540}
1541
1542///////////////////////////////////////////////////////////////////////////////
1543
1544bool SkCanvas::isClipEmpty() const {
1545    return fMCRec->fRasterClip.isEmpty();
1546}
1547
1548bool SkCanvas::isClipRect() const {
1549    return fMCRec->fRasterClip.isRect();
1550}
1551
1552bool SkCanvas::quickReject(const SkRect& rect) const {
1553    if (!rect.isFinite())
1554        return true;
1555
1556    if (fMCRec->fRasterClip.isEmpty()) {
1557        return true;
1558    }
1559
1560    if (fMCRec->fMatrix.hasPerspective()) {
1561        SkRect dst;
1562        fMCRec->fMatrix.mapRect(&dst, rect);
1563        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1564    } else {
1565        const SkRect& clipR = this->getLocalClipBounds();
1566
1567        // for speed, do the most likely reject compares first
1568        // TODO: should we use | instead, or compare all 4 at once?
1569        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1570            return true;
1571        }
1572        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1573            return true;
1574        }
1575        return false;
1576    }
1577}
1578
1579bool SkCanvas::quickReject(const SkPath& path) const {
1580    return path.isEmpty() || this->quickReject(path.getBounds());
1581}
1582
1583bool SkCanvas::getClipBounds(SkRect* bounds) const {
1584    SkIRect ibounds;
1585    if (!this->getClipDeviceBounds(&ibounds)) {
1586        return false;
1587    }
1588
1589    SkMatrix inverse;
1590    // if we can't invert the CTM, we can't return local clip bounds
1591    if (!fMCRec->fMatrix.invert(&inverse)) {
1592        if (bounds) {
1593            bounds->setEmpty();
1594        }
1595        return false;
1596    }
1597
1598    if (bounds) {
1599        SkRect r;
1600        // adjust it outwards in case we are antialiasing
1601        const int inset = 1;
1602
1603        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1604               ibounds.fRight + inset, ibounds.fBottom + inset);
1605        inverse.mapRect(bounds, r);
1606    }
1607    return true;
1608}
1609
1610bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1611    const SkRasterClip& clip = fMCRec->fRasterClip;
1612    if (clip.isEmpty()) {
1613        if (bounds) {
1614            bounds->setEmpty();
1615        }
1616        return false;
1617    }
1618
1619    if (bounds) {
1620        *bounds = clip.getBounds();
1621    }
1622    return true;
1623}
1624
1625const SkMatrix& SkCanvas::getTotalMatrix() const {
1626    return fMCRec->fMatrix;
1627}
1628
1629const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1630    return fMCRec->fRasterClip.forceGetBW();
1631}
1632
1633GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1634    SkBaseDevice* dev = this->getTopDevice();
1635    return dev ? dev->accessRenderTarget() : NULL;
1636}
1637
1638GrContext* SkCanvas::getGrContext() {
1639#if SK_SUPPORT_GPU
1640    SkBaseDevice* device = this->getTopDevice();
1641    if (device) {
1642        GrRenderTarget* renderTarget = device->accessRenderTarget();
1643        if (renderTarget) {
1644            return renderTarget->getContext();
1645        }
1646    }
1647#endif
1648
1649    return NULL;
1650
1651}
1652
1653void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1654                          const SkPaint& paint) {
1655    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1656    if (outer.isEmpty()) {
1657        return;
1658    }
1659    if (inner.isEmpty()) {
1660        this->drawRRect(outer, paint);
1661        return;
1662    }
1663
1664    // We don't have this method (yet), but technically this is what we should
1665    // be able to assert...
1666    // SkASSERT(outer.contains(inner));
1667    //
1668    // For now at least check for containment of bounds
1669    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1670
1671    this->onDrawDRRect(outer, inner, paint);
1672}
1673
1674//////////////////////////////////////////////////////////////////////////////
1675//  These are the virtual drawing methods
1676//////////////////////////////////////////////////////////////////////////////
1677
1678void SkCanvas::onDiscard() {
1679    if (fSurfaceBase) {
1680        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1681    }
1682}
1683
1684void SkCanvas::drawPaint(const SkPaint& paint) {
1685    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1686    this->internalDrawPaint(paint);
1687}
1688
1689void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1690    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1691
1692    while (iter.next()) {
1693        iter.fDevice->drawPaint(iter, looper.paint());
1694    }
1695
1696    LOOPER_END
1697}
1698
1699void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1700                          const SkPaint& paint) {
1701    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
1702    if ((long)count <= 0) {
1703        return;
1704    }
1705
1706    SkRect r, storage;
1707    const SkRect* bounds = NULL;
1708    if (paint.canComputeFastBounds()) {
1709        // special-case 2 points (common for drawing a single line)
1710        if (2 == count) {
1711            r.set(pts[0], pts[1]);
1712        } else {
1713            r.set(pts, SkToInt(count));
1714        }
1715        bounds = &paint.computeFastStrokeBounds(r, &storage);
1716        if (this->quickReject(*bounds)) {
1717            return;
1718        }
1719    }
1720
1721    SkASSERT(pts != NULL);
1722
1723    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1724
1725    while (iter.next()) {
1726        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1727    }
1728
1729    LOOPER_END
1730}
1731
1732void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1733    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
1734    SkRect storage;
1735    const SkRect* bounds = NULL;
1736    if (paint.canComputeFastBounds()) {
1737        bounds = &paint.computeFastBounds(r, &storage);
1738        if (this->quickReject(*bounds)) {
1739            return;
1740        }
1741    }
1742
1743    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1744
1745    while (iter.next()) {
1746        iter.fDevice->drawRect(iter, r, looper.paint());
1747    }
1748
1749    LOOPER_END
1750}
1751
1752void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1753    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
1754    SkRect storage;
1755    const SkRect* bounds = NULL;
1756    if (paint.canComputeFastBounds()) {
1757        bounds = &paint.computeFastBounds(oval, &storage);
1758        if (this->quickReject(*bounds)) {
1759            return;
1760        }
1761    }
1762
1763    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1764
1765    while (iter.next()) {
1766        iter.fDevice->drawOval(iter, oval, looper.paint());
1767    }
1768
1769    LOOPER_END
1770}
1771
1772void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1773    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
1774    SkRect storage;
1775    const SkRect* bounds = NULL;
1776    if (paint.canComputeFastBounds()) {
1777        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1778        if (this->quickReject(*bounds)) {
1779            return;
1780        }
1781    }
1782
1783    if (rrect.isRect()) {
1784        // call the non-virtual version
1785        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1786        return;
1787    } else if (rrect.isOval()) {
1788        // call the non-virtual version
1789        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1790        return;
1791    }
1792
1793    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1794
1795    while (iter.next()) {
1796        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1797    }
1798
1799    LOOPER_END
1800}
1801
1802void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1803                            const SkPaint& paint) {
1804    SkRect storage;
1805    const SkRect* bounds = NULL;
1806    if (paint.canComputeFastBounds()) {
1807        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1808        if (this->quickReject(*bounds)) {
1809            return;
1810        }
1811    }
1812
1813    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1814
1815    while (iter.next()) {
1816        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1817    }
1818
1819    LOOPER_END
1820}
1821
1822void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1823    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
1824    if (!path.isFinite()) {
1825        return;
1826    }
1827
1828    SkRect storage;
1829    const SkRect* bounds = NULL;
1830    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1831        const SkRect& pathBounds = path.getBounds();
1832        bounds = &paint.computeFastBounds(pathBounds, &storage);
1833        if (this->quickReject(*bounds)) {
1834            return;
1835        }
1836    }
1837
1838    const SkRect& r = path.getBounds();
1839    if (r.width() <= 0 && r.height() <= 0) {
1840        if (path.isInverseFillType()) {
1841            this->internalDrawPaint(paint);
1842        }
1843        return;
1844    }
1845
1846    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1847
1848    while (iter.next()) {
1849        iter.fDevice->drawPath(iter, path, looper.paint());
1850    }
1851
1852    LOOPER_END
1853}
1854
1855void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top,
1856                       const SkPaint* paint) {
1857    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
1858    image->draw(this, left, top, paint);
1859}
1860
1861void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src,
1862                           const SkRect& dst,
1863                           const SkPaint* paint) {
1864    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
1865    image->drawRect(this, src, dst, paint);
1866}
1867
1868void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1869                          const SkPaint* paint) {
1870    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
1871    SkDEBUGCODE(bitmap.validate();)
1872
1873    if (NULL == paint || paint->canComputeFastBounds()) {
1874        SkRect bounds = {
1875            x, y,
1876            x + SkIntToScalar(bitmap.width()),
1877            y + SkIntToScalar(bitmap.height())
1878        };
1879        if (paint) {
1880            (void)paint->computeFastBounds(bounds, &bounds);
1881        }
1882        if (this->quickReject(bounds)) {
1883            return;
1884        }
1885    }
1886
1887    SkMatrix matrix;
1888    matrix.setTranslate(x, y);
1889    this->internalDrawBitmap(bitmap, matrix, paint);
1890}
1891
1892// this one is non-virtual, so it can be called safely by other canvas apis
1893void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1894                                      const SkRect& dst, const SkPaint* paint,
1895                                      DrawBitmapRectFlags flags) {
1896    if (bitmap.drawsNothing() || dst.isEmpty()) {
1897        return;
1898    }
1899
1900    SkRect storage;
1901    const SkRect* bounds = &dst;
1902    if (NULL == paint || paint->canComputeFastBounds()) {
1903        if (paint) {
1904            bounds = &paint->computeFastBounds(dst, &storage);
1905        }
1906        if (this->quickReject(*bounds)) {
1907            return;
1908        }
1909    }
1910
1911    SkLazyPaint lazy;
1912    if (NULL == paint) {
1913        paint = lazy.init();
1914    }
1915
1916    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1917
1918    while (iter.next()) {
1919        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1920    }
1921
1922    LOOPER_END
1923}
1924
1925void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1926                                    const SkRect& dst, const SkPaint* paint,
1927                                    DrawBitmapRectFlags flags) {
1928    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
1929    SkDEBUGCODE(bitmap.validate();)
1930    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
1931}
1932
1933void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1934                                      const SkIRect& center, const SkRect& dst,
1935                                      const SkPaint* paint) {
1936    if (bitmap.drawsNothing()) {
1937        return;
1938    }
1939    if (NULL == paint || paint->canComputeFastBounds()) {
1940        SkRect storage;
1941        const SkRect* bounds = &dst;
1942        if (paint) {
1943            bounds = &paint->computeFastBounds(dst, &storage);
1944        }
1945        if (this->quickReject(*bounds)) {
1946            return;
1947        }
1948    }
1949
1950    const int32_t w = bitmap.width();
1951    const int32_t h = bitmap.height();
1952
1953    SkIRect c = center;
1954    // pin center to the bounds of the bitmap
1955    c.fLeft = SkMax32(0, center.fLeft);
1956    c.fTop = SkMax32(0, center.fTop);
1957    c.fRight = SkPin32(center.fRight, c.fLeft, w);
1958    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1959
1960    const SkScalar srcX[4] = {
1961        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
1962    };
1963    const SkScalar srcY[4] = {
1964        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
1965    };
1966    SkScalar dstX[4] = {
1967        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1968        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1969    };
1970    SkScalar dstY[4] = {
1971        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1972        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1973    };
1974
1975    if (dstX[1] > dstX[2]) {
1976        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1977        dstX[2] = dstX[1];
1978    }
1979
1980    if (dstY[1] > dstY[2]) {
1981        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1982        dstY[2] = dstY[1];
1983    }
1984
1985    for (int y = 0; y < 3; y++) {
1986        SkRect s, d;
1987
1988        s.fTop = srcY[y];
1989        s.fBottom = srcY[y+1];
1990        d.fTop = dstY[y];
1991        d.fBottom = dstY[y+1];
1992        for (int x = 0; x < 3; x++) {
1993            s.fLeft = srcX[x];
1994            s.fRight = srcX[x+1];
1995            d.fLeft = dstX[x];
1996            d.fRight = dstX[x+1];
1997            this->internalDrawBitmapRect(bitmap, &s, d, paint,
1998                                         kNone_DrawBitmapRectFlag);
1999        }
2000    }
2001}
2002
2003void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
2004                              const SkRect& dst, const SkPaint* paint) {
2005    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2006    SkDEBUGCODE(bitmap.validate();)
2007
2008    // Need a device entry-point, so gpu can use a mesh
2009    this->internalDrawBitmapNine(bitmap, center, dst, paint);
2010}
2011
2012class SkDeviceFilteredPaint {
2013public:
2014    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2015        uint32_t filteredFlags = device->filterTextFlags(paint);
2016        if (filteredFlags != paint.getFlags()) {
2017            SkPaint* newPaint = fLazy.set(paint);
2018            newPaint->setFlags(filteredFlags);
2019            fPaint = newPaint;
2020        } else {
2021            fPaint = &paint;
2022        }
2023    }
2024
2025    const SkPaint& paint() const { return *fPaint; }
2026
2027private:
2028    const SkPaint*  fPaint;
2029    SkLazyPaint     fLazy;
2030};
2031
2032void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2033                        const SkRect& r, SkScalar textSize) {
2034    if (paint.getStyle() == SkPaint::kFill_Style) {
2035        draw.fDevice->drawRect(draw, r, paint);
2036    } else {
2037        SkPaint p(paint);
2038        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2039        draw.fDevice->drawRect(draw, r, p);
2040    }
2041}
2042
2043void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2044                                   const char text[], size_t byteLength,
2045                                   SkScalar x, SkScalar y) {
2046    SkASSERT(byteLength == 0 || text != NULL);
2047
2048    // nothing to draw
2049    if (text == NULL || byteLength == 0 ||
2050        draw.fClip->isEmpty() ||
2051        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2052        return;
2053    }
2054
2055    SkScalar    width = 0;
2056    SkPoint     start;
2057
2058    start.set(0, 0);    // to avoid warning
2059    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2060                            SkPaint::kStrikeThruText_Flag)) {
2061        width = paint.measureText(text, byteLength);
2062
2063        SkScalar offsetX = 0;
2064        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2065            offsetX = SkScalarHalf(width);
2066        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2067            offsetX = width;
2068        }
2069        start.set(x - offsetX, y);
2070    }
2071
2072    if (0 == width) {
2073        return;
2074    }
2075
2076    uint32_t flags = paint.getFlags();
2077
2078    if (flags & (SkPaint::kUnderlineText_Flag |
2079                 SkPaint::kStrikeThruText_Flag)) {
2080        SkScalar textSize = paint.getTextSize();
2081        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2082        SkRect   r;
2083
2084        r.fLeft = start.fX;
2085        r.fRight = start.fX + width;
2086
2087        if (flags & SkPaint::kUnderlineText_Flag) {
2088            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2089                                             start.fY);
2090            r.fTop = offset;
2091            r.fBottom = offset + height;
2092            DrawRect(draw, paint, r, textSize);
2093        }
2094        if (flags & SkPaint::kStrikeThruText_Flag) {
2095            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2096                                             start.fY);
2097            r.fTop = offset;
2098            r.fBottom = offset + height;
2099            DrawRect(draw, paint, r, textSize);
2100        }
2101    }
2102}
2103
2104void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2105                          const SkPaint& paint) {
2106    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2107
2108    while (iter.next()) {
2109        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2110        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2111        DrawTextDecorations(iter, dfp.paint(),
2112                            static_cast<const char*>(text), byteLength, x, y);
2113    }
2114
2115    LOOPER_END
2116}
2117
2118void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2119                             const SkPaint& paint) {
2120    SkPoint textOffset = SkPoint::Make(0, 0);
2121
2122    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2123
2124    while (iter.next()) {
2125        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2126        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2127                                  dfp.paint());
2128    }
2129
2130    LOOPER_END
2131}
2132
2133void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2134                              SkScalar constY, const SkPaint& paint) {
2135
2136    SkPoint textOffset = SkPoint::Make(0, constY);
2137
2138    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2139
2140    while (iter.next()) {
2141        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2142        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2143                                  dfp.paint());
2144    }
2145
2146    LOOPER_END
2147}
2148
2149void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2150                                const SkMatrix* matrix, const SkPaint& paint) {
2151    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2152
2153    while (iter.next()) {
2154        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2155                                     matrix, looper.paint());
2156    }
2157
2158    LOOPER_END
2159}
2160
2161void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2162                              const SkPaint& paint) {
2163
2164    if (paint.canComputeFastBounds()) {
2165        SkRect storage;
2166
2167        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
2168            return;
2169        }
2170    }
2171
2172    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2173
2174    while (iter.next()) {
2175        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2176        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
2177    }
2178
2179    LOOPER_END
2180}
2181
2182// These will become non-virtual, so they always call the (virtual) onDraw... method
2183void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2184                        const SkPaint& paint) {
2185    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2186    this->onDrawText(text, byteLength, x, y, paint);
2187}
2188void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2189                           const SkPaint& paint) {
2190    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2191    this->onDrawPosText(text, byteLength, pos, paint);
2192}
2193void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2194                            SkScalar constY, const SkPaint& paint) {
2195    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2196    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2197}
2198void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2199                              const SkMatrix* matrix, const SkPaint& paint) {
2200    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2201    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2202}
2203void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2204                            const SkPaint& paint) {
2205    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2206    if (blob) {
2207        this->onDrawTextBlob(blob, x, y, paint);
2208    }
2209}
2210
2211void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
2212                            const SkPoint verts[], const SkPoint texs[],
2213                            const SkColor colors[], SkXfermode* xmode,
2214                            const uint16_t indices[], int indexCount,
2215                            const SkPaint& paint) {
2216    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2217    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2218
2219    while (iter.next()) {
2220        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2221                                   colors, xmode, indices, indexCount,
2222                                   looper.paint());
2223    }
2224
2225    LOOPER_END
2226}
2227
2228void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2229                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2230    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2231    if (NULL == cubics) {
2232        return;
2233    }
2234
2235    // Since a patch is always within the convex hull of the control points, we discard it when its
2236    // bounding rectangle is completely outside the current clip.
2237    SkRect bounds;
2238    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2239    if (this->quickReject(bounds)) {
2240        return;
2241    }
2242
2243    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2244}
2245
2246void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2247                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2248
2249    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2250
2251    while (iter.next()) {
2252        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2253    }
2254
2255    LOOPER_END
2256}
2257
2258void SkCanvas::EXPERIMENTAL_drawDrawable(SkCanvasDrawable* dr) {
2259    if (dr && !this->quickReject(dr->getBounds())) {
2260        this->onDrawDrawable(dr);
2261    }
2262}
2263
2264void SkCanvas::onDrawDrawable(SkCanvasDrawable* dr) {
2265    dr->draw(this);
2266}
2267
2268//////////////////////////////////////////////////////////////////////////////
2269// These methods are NOT virtual, and therefore must call back into virtual
2270// methods, rather than actually drawing themselves.
2271//////////////////////////////////////////////////////////////////////////////
2272
2273void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2274                        SkXfermode::Mode mode) {
2275    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2276    SkPaint paint;
2277
2278    paint.setARGB(a, r, g, b);
2279    if (SkXfermode::kSrcOver_Mode != mode) {
2280        paint.setXfermodeMode(mode);
2281    }
2282    this->drawPaint(paint);
2283}
2284
2285void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2286    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2287    SkPaint paint;
2288
2289    paint.setColor(c);
2290    if (SkXfermode::kSrcOver_Mode != mode) {
2291        paint.setXfermodeMode(mode);
2292    }
2293    this->drawPaint(paint);
2294}
2295
2296void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2297    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2298    SkPoint pt;
2299
2300    pt.set(x, y);
2301    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2302}
2303
2304void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2305    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2306    SkPoint pt;
2307    SkPaint paint;
2308
2309    pt.set(x, y);
2310    paint.setColor(color);
2311    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2312}
2313
2314void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2315                        const SkPaint& paint) {
2316    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2317    SkPoint pts[2];
2318
2319    pts[0].set(x0, y0);
2320    pts[1].set(x1, y1);
2321    this->drawPoints(kLines_PointMode, 2, pts, paint);
2322}
2323
2324void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2325                              SkScalar right, SkScalar bottom,
2326                              const SkPaint& paint) {
2327    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2328    SkRect  r;
2329
2330    r.set(left, top, right, bottom);
2331    this->drawRect(r, paint);
2332}
2333
2334void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2335                          const SkPaint& paint) {
2336    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2337    if (radius < 0) {
2338        radius = 0;
2339    }
2340
2341    SkRect  r;
2342    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2343    this->drawOval(r, paint);
2344}
2345
2346void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2347                             const SkPaint& paint) {
2348    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2349    if (rx > 0 && ry > 0) {
2350        if (paint.canComputeFastBounds()) {
2351            SkRect storage;
2352            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2353                return;
2354            }
2355        }
2356        SkRRect rrect;
2357        rrect.setRectXY(r, rx, ry);
2358        this->drawRRect(rrect, paint);
2359    } else {
2360        this->drawRect(r, paint);
2361    }
2362}
2363
2364void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2365                       SkScalar sweepAngle, bool useCenter,
2366                       const SkPaint& paint) {
2367    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2368    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2369        this->drawOval(oval, paint);
2370    } else {
2371        SkPath  path;
2372        if (useCenter) {
2373            path.moveTo(oval.centerX(), oval.centerY());
2374        }
2375        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2376        if (useCenter) {
2377            path.close();
2378        }
2379        this->drawPath(path, paint);
2380    }
2381}
2382
2383void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2384                                const SkPath& path, SkScalar hOffset,
2385                                SkScalar vOffset, const SkPaint& paint) {
2386    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2387    SkMatrix    matrix;
2388
2389    matrix.setTranslate(hOffset, vOffset);
2390    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2391}
2392
2393///////////////////////////////////////////////////////////////////////////////
2394void SkCanvas::drawPicture(const SkPicture* picture) {
2395    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2396    if (picture) {
2397        this->onDrawPicture(picture, NULL, NULL);
2398    }
2399}
2400
2401void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2402    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)");
2403    if (picture) {
2404        if (matrix && matrix->isIdentity()) {
2405            matrix = NULL;
2406        }
2407        this->onDrawPicture(picture, matrix, paint);
2408    }
2409}
2410
2411void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2412                             const SkPaint* paint) {
2413    SkBaseDevice* device = this->getTopDevice();
2414    if (device) {
2415        // Canvas has to first give the device the opportunity to render
2416        // the picture itself.
2417        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2418            return; // the device has rendered the entire picture
2419        }
2420    }
2421
2422    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2423
2424    picture->playback(this);
2425}
2426
2427///////////////////////////////////////////////////////////////////////////////
2428///////////////////////////////////////////////////////////////////////////////
2429
2430SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2431    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2432
2433    SkASSERT(canvas);
2434
2435    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2436    fDone = !fImpl->next();
2437}
2438
2439SkCanvas::LayerIter::~LayerIter() {
2440    fImpl->~SkDrawIter();
2441}
2442
2443void SkCanvas::LayerIter::next() {
2444    fDone = !fImpl->next();
2445}
2446
2447SkBaseDevice* SkCanvas::LayerIter::device() const {
2448    return fImpl->getDevice();
2449}
2450
2451const SkMatrix& SkCanvas::LayerIter::matrix() const {
2452    return fImpl->getMatrix();
2453}
2454
2455const SkPaint& SkCanvas::LayerIter::paint() const {
2456    const SkPaint* paint = fImpl->getPaint();
2457    if (NULL == paint) {
2458        paint = &fDefaultPaint;
2459    }
2460    return *paint;
2461}
2462
2463const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2464int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2465int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2466
2467///////////////////////////////////////////////////////////////////////////////
2468
2469SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2470
2471///////////////////////////////////////////////////////////////////////////////
2472
2473static bool supported_for_raster_canvas(const SkImageInfo& info) {
2474    switch (info.alphaType()) {
2475        case kPremul_SkAlphaType:
2476        case kOpaque_SkAlphaType:
2477            break;
2478        default:
2479            return false;
2480    }
2481
2482    switch (info.colorType()) {
2483        case kAlpha_8_SkColorType:
2484        case kRGB_565_SkColorType:
2485        case kN32_SkColorType:
2486            break;
2487        default:
2488            return false;
2489    }
2490
2491    return true;
2492}
2493
2494SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2495    if (!supported_for_raster_canvas(info)) {
2496        return NULL;
2497    }
2498
2499    SkBitmap bitmap;
2500    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2501        return NULL;
2502    }
2503    return SkNEW_ARGS(SkCanvas, (bitmap));
2504}
2505
2506///////////////////////////////////////////////////////////////////////////////
2507
2508SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2509                                                 const SkPaint* paint, const SkRect& bounds)
2510    : fCanvas(canvas)
2511    , fSaveCount(canvas->getSaveCount())
2512{
2513    if (paint) {
2514        SkRect newBounds = bounds;
2515        if (matrix) {
2516            matrix->mapRect(&newBounds);
2517        }
2518        canvas->saveLayer(&newBounds, paint);
2519    } else if (matrix) {
2520        canvas->save();
2521    }
2522
2523    if (matrix) {
2524        canvas->concat(*matrix);
2525    }
2526}
2527
2528SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2529    fCanvas->restoreToCount(fSaveCount);
2530}
2531