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