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