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