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