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 SkColorFilter::MakeComposeFilter(std::move(imgCF), 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,bool isOpaque,const SkPaint * paint)1039 static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1040 const SkPaint* paint) {
1041 // need to force L32 for now if we have an image filter. Once filters support other colortypes
1042 // e.g. sRGB or F16, we can remove this check
1043 // SRGBTODO: Can we remove this check now?
1044 const bool hasImageFilter = paint && paint->getImageFilter();
1045
1046 SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1047 if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1048 // force to L32
1049 return SkImageInfo::MakeN32(w, h, alphaType);
1050 } else {
1051 // keep the same characteristics as the prev
1052 return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1053 }
1054 }
1055
internalSaveLayer(const SaveLayerRec & rec,SaveLayerStrategy strategy)1056 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
1057 const SkRect* bounds = rec.fBounds;
1058 const SkPaint* paint = rec.fPaint;
1059 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1060
1061 SkLazyPaint lazyP;
1062 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : nullptr;
1063 SkMatrix stashedMatrix = fMCRec->fMatrix;
1064 SkMatrix remainder;
1065 SkSize scale;
1066 /*
1067 * ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
1068 * but they do handle scaling. To accommodate this, we do the following:
1069 *
1070 * 1. Stash off the current CTM
1071 * 2. Decompose the CTM into SCALE and REMAINDER
1072 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
1073 * contains the REMAINDER
1074 * 4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
1075 * 5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
1076 * of the original imagefilter, and draw that (via drawSprite)
1077 * 6. Unwack the CTM to its original state (i.e. stashedMatrix)
1078 *
1079 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1080 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
1081 */
1082 if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
1083 stashedMatrix.decomposeScale(&scale, &remainder))
1084 {
1085 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1086 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
1087 SkPaint* p = lazyP.set(*paint);
1088 p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
1089 SkFilterQuality::kLow_SkFilterQuality,
1090 sk_ref_sp(imageFilter)));
1091 imageFilter = p->getImageFilter();
1092 paint = p;
1093 }
1094
1095 // do this before we create the layer. We don't call the public save() since
1096 // that would invoke a possibly overridden virtual
1097 this->internalSave();
1098
1099 SkIRect ir;
1100 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
1101 return;
1102 }
1103
1104 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1105 // the clipRectBounds() call above?
1106 if (kNoLayer_SaveLayerStrategy == strategy) {
1107 return;
1108 }
1109
1110 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
1111 SkPixelGeometry geo = fProps.pixelGeometry();
1112 if (paint) {
1113 // TODO: perhaps add a query to filters so we might preserve opaqueness...
1114 if (paint->getImageFilter() || paint->getColorFilter()) {
1115 isOpaque = false;
1116 geo = kUnknown_SkPixelGeometry;
1117 }
1118 }
1119
1120 SkBaseDevice* priorDevice = this->getTopDevice();
1121 if (nullptr == priorDevice) { // Do we still need this check???
1122 SkDebugf("Unable to find device for layer.");
1123 return;
1124 }
1125
1126 SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1127 paint);
1128
1129 sk_sp<SkBaseDevice> newDevice;
1130 {
1131 const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
1132 (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1133 const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1134 const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1135 preserveLCDText,
1136 fAllocator.get());
1137 newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
1138 if (!newDevice) {
1139 return;
1140 }
1141 }
1142 DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
1143
1144 // only have a "next" if this new layer doesn't affect the clip (rare)
1145 layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
1146 fMCRec->fLayer = layer;
1147 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
1148
1149 if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1150 DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1151 fMCRec->fMatrix);
1152 }
1153
1154 newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1155
1156 newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1157 if (layer->fNext) {
1158 // need to punch a hole in the previous device, so we don't draw there, given that
1159 // the new top-layer will allow drawing to happen "below" it.
1160 SkRegion hole(ir);
1161 do {
1162 layer = layer->fNext;
1163 layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1164 } while (layer->fNext);
1165 }
1166 }
1167
saveLayerAlpha(const SkRect * bounds,U8CPU alpha)1168 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1169 if (0xFF == alpha) {
1170 return this->saveLayer(bounds, nullptr);
1171 } else {
1172 SkPaint tmpPaint;
1173 tmpPaint.setAlpha(alpha);
1174 return this->saveLayer(bounds, &tmpPaint);
1175 }
1176 }
1177
internalRestore()1178 void SkCanvas::internalRestore() {
1179 SkASSERT(fMCStack.count() != 0);
1180
1181 // reserve our layer (if any)
1182 DeviceCM* layer = fMCRec->fLayer; // may be null
1183 // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1184 fMCRec->fLayer = nullptr;
1185
1186 // now do the normal restore()
1187 fMCRec->~MCRec(); // balanced in save()
1188 fMCStack.pop_back();
1189 fMCRec = (MCRec*)fMCStack.back();
1190
1191 if (fMCRec) {
1192 FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1193 }
1194
1195 /* Time to draw the layer's offscreen. We can't call the public drawSprite,
1196 since if we're being recorded, we don't want to record this (the
1197 recorder will have already recorded the restore).
1198 */
1199 if (layer) {
1200 if (fMCRec) {
1201 const SkIPoint& origin = layer->fDevice->getOrigin();
1202 this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
1203 layer->fPaint.get(),
1204 layer->fClipImage.get(), layer->fClipMatrix);
1205 // restore what we smashed in internalSaveLayer
1206 fMCRec->fMatrix = layer->fStashedMatrix;
1207 // reset this, since internalDrawDevice will have set it to true
1208 delete layer;
1209 } else {
1210 // we're at the root
1211 SkASSERT(layer == (void*)fDeviceCMStorage);
1212 layer->~DeviceCM();
1213 // no need to update fMCRec, 'cause we're killing the canvas
1214 }
1215 }
1216
1217 if (fMCRec) {
1218 fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1219 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1220 }
1221 }
1222
makeSurface(const SkImageInfo & info,const SkSurfaceProps * props)1223 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1224 if (nullptr == props) {
1225 props = &fProps;
1226 }
1227 return this->onNewSurface(info, *props);
1228 }
1229
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)1230 sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1231 SkBaseDevice* dev = this->getDevice();
1232 return dev ? dev->makeSurface(info, props) : nullptr;
1233 }
1234
imageInfo() const1235 SkImageInfo SkCanvas::imageInfo() const {
1236 return this->onImageInfo();
1237 }
1238
onImageInfo() const1239 SkImageInfo SkCanvas::onImageInfo() const {
1240 SkBaseDevice* dev = this->getDevice();
1241 if (dev) {
1242 return dev->imageInfo();
1243 } else {
1244 return SkImageInfo::MakeUnknown(0, 0);
1245 }
1246 }
1247
getProps(SkSurfaceProps * props) const1248 bool SkCanvas::getProps(SkSurfaceProps* props) const {
1249 return this->onGetProps(props);
1250 }
1251
onGetProps(SkSurfaceProps * props) const1252 bool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1253 SkBaseDevice* dev = this->getDevice();
1254 if (dev) {
1255 if (props) {
1256 *props = fProps;
1257 }
1258 return true;
1259 } else {
1260 return false;
1261 }
1262 }
1263
peekPixels(SkPixmap * pmap)1264 bool SkCanvas::peekPixels(SkPixmap* pmap) {
1265 return this->onPeekPixels(pmap);
1266 }
1267
onPeekPixels(SkPixmap * pmap)1268 bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1269 SkBaseDevice* dev = this->getDevice();
1270 return dev && dev->peekPixels(pmap);
1271 }
1272
accessTopLayerPixels(SkImageInfo * info,size_t * rowBytes,SkIPoint * origin)1273 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1274 SkPixmap pmap;
1275 if (!this->onAccessTopLayerPixels(&pmap)) {
1276 return nullptr;
1277 }
1278 if (info) {
1279 *info = pmap.info();
1280 }
1281 if (rowBytes) {
1282 *rowBytes = pmap.rowBytes();
1283 }
1284 if (origin) {
1285 *origin = this->getTopDevice()->getOrigin();
1286 }
1287 return pmap.writable_addr();
1288 }
1289
onAccessTopLayerPixels(SkPixmap * pmap)1290 bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
1291 SkBaseDevice* dev = this->getTopDevice();
1292 return dev && dev->accessPixels(pmap);
1293 }
1294
1295 /////////////////////////////////////////////////////////////////////////////
1296
internalDrawDevice(SkBaseDevice * srcDev,int x,int y,const SkPaint * paint,SkImage * clipImage,const SkMatrix & clipMatrix)1297 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
1298 SkImage* clipImage, const SkMatrix& clipMatrix) {
1299 SkPaint tmp;
1300 if (nullptr == paint) {
1301 paint = &tmp;
1302 }
1303
1304 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1305
1306 while (iter.next()) {
1307 SkBaseDevice* dstDev = iter.fDevice;
1308 paint = &looper.paint();
1309 SkImageFilter* filter = paint->getImageFilter();
1310 SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1311 if (filter || clipImage) {
1312 sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1313 if (specialImage) {
1314 dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
1315 clipImage, clipMatrix);
1316 }
1317 } else {
1318 dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
1319 }
1320 }
1321
1322 LOOPER_END
1323 }
1324
1325 /////////////////////////////////////////////////////////////////////////////
1326
translate(SkScalar dx,SkScalar dy)1327 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1328 if (dx || dy) {
1329 this->checkForDeferredSave();
1330 fMCRec->fMatrix.preTranslate(dx,dy);
1331
1332 // Translate shouldn't affect the is-scale-translateness of the matrix.
1333 SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1334
1335 FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1336
1337 this->didTranslate(dx,dy);
1338 }
1339 }
1340
scale(SkScalar sx,SkScalar sy)1341 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1342 SkMatrix m;
1343 m.setScale(sx, sy);
1344 this->concat(m);
1345 }
1346
rotate(SkScalar degrees)1347 void SkCanvas::rotate(SkScalar degrees) {
1348 SkMatrix m;
1349 m.setRotate(degrees);
1350 this->concat(m);
1351 }
1352
rotate(SkScalar degrees,SkScalar px,SkScalar py)1353 void SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
1354 SkMatrix m;
1355 m.setRotate(degrees, px, py);
1356 this->concat(m);
1357 }
1358
skew(SkScalar sx,SkScalar sy)1359 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1360 SkMatrix m;
1361 m.setSkew(sx, sy);
1362 this->concat(m);
1363 }
1364
concat(const SkMatrix & matrix)1365 void SkCanvas::concat(const SkMatrix& matrix) {
1366 if (matrix.isIdentity()) {
1367 return;
1368 }
1369
1370 this->checkForDeferredSave();
1371 fMCRec->fMatrix.preConcat(matrix);
1372 fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1373
1374 FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1375
1376 this->didConcat(matrix);
1377 }
1378
internalSetMatrix(const SkMatrix & matrix)1379 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1380 fMCRec->fMatrix = matrix;
1381 fIsScaleTranslate = matrix.isScaleTranslate();
1382
1383 FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1384 }
1385
setMatrix(const SkMatrix & matrix)1386 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1387 this->checkForDeferredSave();
1388 this->internalSetMatrix(matrix);
1389 this->didSetMatrix(matrix);
1390 }
1391
resetMatrix()1392 void SkCanvas::resetMatrix() {
1393 this->setMatrix(SkMatrix::I());
1394 }
1395
1396 //////////////////////////////////////////////////////////////////////////////
1397
clipRect(const SkRect & rect,SkClipOp op,bool doAA)1398 void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
1399 if (!rect.isFinite()) {
1400 return;
1401 }
1402 this->checkForDeferredSave();
1403 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1404 this->onClipRect(rect, op, edgeStyle);
1405 }
1406
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)1407 void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1408 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1409
1410 FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
1411
1412 AutoValidateClip avc(this);
1413 fMCRec->fRasterClip.opRect(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1414 isAA);
1415 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1416 }
1417
androidFramework_setDeviceClipRestriction(const SkIRect & rect)1418 void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
1419 fClipRestrictionRect = rect;
1420 if (fClipRestrictionRect.isEmpty()) {
1421 // we notify the device, but we *dont* resolve deferred saves (since we're just
1422 // removing the restriction if the rect is empty. how I hate this api.
1423 FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1424 } else {
1425 this->checkForDeferredSave();
1426 FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1427 AutoValidateClip avc(this);
1428 fMCRec->fRasterClip.opIRect(fClipRestrictionRect, SkRegion::kIntersect_Op);
1429 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1430 }
1431 }
1432
clipRRect(const SkRRect & rrect,SkClipOp op,bool doAA)1433 void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
1434 this->checkForDeferredSave();
1435 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1436 if (rrect.isRect()) {
1437 this->onClipRect(rrect.getBounds(), op, edgeStyle);
1438 } else {
1439 this->onClipRRect(rrect, op, edgeStyle);
1440 }
1441 }
1442
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)1443 void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1444 AutoValidateClip avc(this);
1445
1446 bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1447
1448 FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1449
1450 fMCRec->fRasterClip.opRRect(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1451 isAA);
1452 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1453 }
1454
clipPath(const SkPath & path,SkClipOp op,bool doAA)1455 void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
1456 this->checkForDeferredSave();
1457 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1458
1459 if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
1460 SkRect r;
1461 if (path.isRect(&r)) {
1462 this->onClipRect(r, op, edgeStyle);
1463 return;
1464 }
1465 SkRRect rrect;
1466 if (path.isOval(&r)) {
1467 rrect.setOval(r);
1468 this->onClipRRect(rrect, op, edgeStyle);
1469 return;
1470 }
1471 if (path.isRRect(&rrect)) {
1472 this->onClipRRect(rrect, op, edgeStyle);
1473 return;
1474 }
1475 }
1476
1477 this->onClipPath(path, op, edgeStyle);
1478 }
1479
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)1480 void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
1481 AutoValidateClip avc(this);
1482
1483 bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1484
1485 FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
1486
1487 const SkPath* rasterClipPath = &path;
1488 const SkMatrix* matrix = &fMCRec->fMatrix;
1489 fMCRec->fRasterClip.opPath(*rasterClipPath, *matrix, this->getTopLayerBounds(),
1490 (SkRegion::Op)op, isAA);
1491 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1492 }
1493
clipRegion(const SkRegion & rgn,SkClipOp op)1494 void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
1495 this->checkForDeferredSave();
1496 this->onClipRegion(rgn, op);
1497 }
1498
onClipRegion(const SkRegion & rgn,SkClipOp op)1499 void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
1500 FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
1501
1502 AutoValidateClip avc(this);
1503
1504 fMCRec->fRasterClip.opRegion(rgn, (SkRegion::Op)op);
1505 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1506 }
1507
1508 #ifdef SK_DEBUG
validateClip() const1509 void SkCanvas::validateClip() const {
1510 // construct clipRgn from the clipstack
1511 const SkBaseDevice* device = this->getDevice();
1512 if (!device) {
1513 SkASSERT(this->isClipEmpty());
1514 return;
1515 }
1516 }
1517 #endif
1518
androidFramework_isClipAA() const1519 bool SkCanvas::androidFramework_isClipAA() const {
1520 bool containsAA = false;
1521
1522 FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1523
1524 return containsAA;
1525 }
1526
1527 class RgnAccumulator {
1528 SkRegion* fRgn;
1529 public:
RgnAccumulator(SkRegion * total)1530 RgnAccumulator(SkRegion* total) : fRgn(total) {}
accumulate(SkBaseDevice * device,SkRegion * rgn)1531 void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1532 SkIPoint origin = device->getOrigin();
1533 if (origin.x() | origin.y()) {
1534 rgn->translate(origin.x(), origin.y());
1535 }
1536 fRgn->op(*rgn, SkRegion::kUnion_Op);
1537 }
1538 };
1539
temporary_internal_getRgnClip(SkRegion * rgn)1540 void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1541 RgnAccumulator accum(rgn);
1542 SkRegion tmp;
1543
1544 rgn->setEmpty();
1545 FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
1546 }
1547
1548 ///////////////////////////////////////////////////////////////////////////////
1549
isClipEmpty() const1550 bool SkCanvas::isClipEmpty() const {
1551 return fMCRec->fRasterClip.isEmpty();
1552
1553 // TODO: should we only use the conservative answer in a recording canvas?
1554 #if 0
1555 SkBaseDevice* dev = this->getTopDevice();
1556 // if no device we return true
1557 return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1558 #endif
1559 }
1560
isClipRect() const1561 bool SkCanvas::isClipRect() const {
1562 SkBaseDevice* dev = this->getTopDevice();
1563 // if no device we return false
1564 return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
1565 }
1566
is_nan_or_clipped(const Sk4f & devRect,const Sk4f & devClip)1567 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1568 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1569 __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1570 __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1571 __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1572 return 0xF != _mm_movemask_ps(mask);
1573 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1574 float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1575 float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1576 uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1577 return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1578 #else
1579 SkRect devRectAsRect;
1580 SkRect devClipAsRect;
1581 devRect.store(&devRectAsRect.fLeft);
1582 devClip.store(&devClipAsRect.fLeft);
1583 return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1584 #endif
1585 }
1586
1587 // It's important for this function to not be inlined. Otherwise the compiler will share code
1588 // between the fast path and the slow path, resulting in two slow paths.
quick_reject_slow_path(const SkRect & src,const SkRect & deviceClip,const SkMatrix & matrix)1589 static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1590 const SkMatrix& matrix) {
1591 SkRect deviceRect;
1592 matrix.mapRect(&deviceRect, src);
1593 return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1594 }
1595
quickReject(const SkRect & src) const1596 bool SkCanvas::quickReject(const SkRect& src) const {
1597 #ifdef SK_DEBUG
1598 // Verify that fDeviceClipBounds are set properly.
1599 SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1600 if (fMCRec->fRasterClip.isEmpty()) {
1601 SkASSERT(fDeviceClipBounds.isEmpty());
1602 } else {
1603 SkASSERT(tmp == fDeviceClipBounds);
1604 }
1605
1606 // Verify that fIsScaleTranslate is set properly.
1607 SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1608 #endif
1609
1610 if (!fIsScaleTranslate) {
1611 return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1612 }
1613
1614 // We inline the implementation of mapScaleTranslate() for the fast path.
1615 float sx = fMCRec->fMatrix.getScaleX();
1616 float sy = fMCRec->fMatrix.getScaleY();
1617 float tx = fMCRec->fMatrix.getTranslateX();
1618 float ty = fMCRec->fMatrix.getTranslateY();
1619 Sk4f scale(sx, sy, sx, sy);
1620 Sk4f trans(tx, ty, tx, ty);
1621
1622 // Apply matrix.
1623 Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1624
1625 // Make sure left < right, top < bottom.
1626 Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1627 Sk4f min = Sk4f::Min(ltrb, rblt);
1628 Sk4f max = Sk4f::Max(ltrb, rblt);
1629 // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1630 // ARM this sequence generates the fastest (a single instruction).
1631 Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1632
1633 // Check if the device rect is NaN or outside the clip.
1634 return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1635 }
1636
quickReject(const SkPath & path) const1637 bool SkCanvas::quickReject(const SkPath& path) const {
1638 return path.isEmpty() || this->quickReject(path.getBounds());
1639 }
1640
getLocalClipBounds() const1641 SkRect SkCanvas::getLocalClipBounds() const {
1642 SkIRect ibounds = this->getDeviceClipBounds();
1643 if (ibounds.isEmpty()) {
1644 return SkRect::MakeEmpty();
1645 }
1646
1647 SkMatrix inverse;
1648 // if we can't invert the CTM, we can't return local clip bounds
1649 if (!fMCRec->fMatrix.invert(&inverse)) {
1650 return SkRect::MakeEmpty();
1651 }
1652
1653 SkRect bounds;
1654 SkRect r;
1655 // adjust it outwards in case we are antialiasing
1656 const int inset = 1;
1657
1658 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1659 ibounds.fRight + inset, ibounds.fBottom + inset);
1660 inverse.mapRect(&bounds, r);
1661 return bounds;
1662 }
1663
getDeviceClipBounds() const1664 SkIRect SkCanvas::getDeviceClipBounds() const {
1665 return fMCRec->fRasterClip.getBounds();
1666 }
1667
getTotalMatrix() const1668 const SkMatrix& SkCanvas::getTotalMatrix() const {
1669 return fMCRec->fMatrix;
1670 }
1671
internal_private_accessTopLayerRenderTargetContext()1672 GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
1673 SkBaseDevice* dev = this->getTopDevice();
1674 return dev ? dev->accessRenderTargetContext() : nullptr;
1675 }
1676
getGrContext()1677 GrContext* SkCanvas::getGrContext() {
1678 SkBaseDevice* device = this->getTopDevice();
1679 return device ? device->context() : nullptr;
1680 }
1681
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1682 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1683 const SkPaint& paint) {
1684 TRACE_EVENT0("skia", TRACE_FUNC);
1685 if (outer.isEmpty()) {
1686 return;
1687 }
1688 if (inner.isEmpty()) {
1689 this->drawRRect(outer, paint);
1690 return;
1691 }
1692
1693 // We don't have this method (yet), but technically this is what we should
1694 // be able to return ...
1695 // if (!outer.contains(inner))) {
1696 //
1697 // For now at least check for containment of bounds
1698 if (!outer.getBounds().contains(inner.getBounds())) {
1699 return;
1700 }
1701
1702 this->onDrawDRRect(outer, inner, paint);
1703 }
1704
drawPaint(const SkPaint & paint)1705 void SkCanvas::drawPaint(const SkPaint& paint) {
1706 TRACE_EVENT0("skia", TRACE_FUNC);
1707 this->onDrawPaint(paint);
1708 }
1709
drawRect(const SkRect & r,const SkPaint & paint)1710 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1711 TRACE_EVENT0("skia", TRACE_FUNC);
1712 // To avoid redundant logic in our culling code and various backends, we always sort rects
1713 // before passing them along.
1714 this->onDrawRect(r.makeSorted(), paint);
1715 }
1716
drawRegion(const SkRegion & region,const SkPaint & paint)1717 void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1718 TRACE_EVENT0("skia", TRACE_FUNC);
1719 if (region.isEmpty()) {
1720 return;
1721 }
1722
1723 if (region.isRect()) {
1724 return this->drawIRect(region.getBounds(), paint);
1725 }
1726
1727 this->onDrawRegion(region, paint);
1728 }
1729
drawOval(const SkRect & r,const SkPaint & paint)1730 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1731 TRACE_EVENT0("skia", TRACE_FUNC);
1732 // To avoid redundant logic in our culling code and various backends, we always sort rects
1733 // before passing them along.
1734 this->onDrawOval(r.makeSorted(), paint);
1735 }
1736
drawRRect(const SkRRect & rrect,const SkPaint & paint)1737 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1738 TRACE_EVENT0("skia", TRACE_FUNC);
1739 this->onDrawRRect(rrect, paint);
1740 }
1741
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1742 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1743 TRACE_EVENT0("skia", TRACE_FUNC);
1744 this->onDrawPoints(mode, count, pts, paint);
1745 }
1746
drawVertices(const sk_sp<SkVertices> & vertices,SkBlendMode mode,const SkPaint & paint)1747 void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1748 const SkPaint& paint) {
1749 TRACE_EVENT0("skia", TRACE_FUNC);
1750 RETURN_ON_NULL(vertices);
1751 this->onDrawVerticesObject(vertices.get(), mode, paint);
1752 }
1753
drawVertices(const SkVertices * vertices,SkBlendMode mode,const SkPaint & paint)1754 void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1755 TRACE_EVENT0("skia", TRACE_FUNC);
1756 RETURN_ON_NULL(vertices);
1757 this->onDrawVerticesObject(vertices, mode, paint);
1758 }
1759
drawPath(const SkPath & path,const SkPaint & paint)1760 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1761 TRACE_EVENT0("skia", TRACE_FUNC);
1762 this->onDrawPath(path, paint);
1763 }
1764
drawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)1765 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1766 TRACE_EVENT0("skia", TRACE_FUNC);
1767 RETURN_ON_NULL(image);
1768 this->onDrawImage(image, x, y, paint);
1769 }
1770
1771 // Returns true if the rect can be "filled" : non-empty and finite
fillable(const SkRect & r)1772 static bool fillable(const SkRect& r) {
1773 SkScalar w = r.width();
1774 SkScalar h = r.height();
1775 return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0;
1776 }
1777
drawImageRect(const SkImage * image,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1778 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1779 const SkPaint* paint, SrcRectConstraint constraint) {
1780 TRACE_EVENT0("skia", TRACE_FUNC);
1781 RETURN_ON_NULL(image);
1782 if (!fillable(dst) || !fillable(src)) {
1783 return;
1784 }
1785 this->onDrawImageRect(image, &src, dst, paint, constraint);
1786 }
1787
drawImageRect(const SkImage * image,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1788 void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1789 const SkPaint* paint, SrcRectConstraint constraint) {
1790 RETURN_ON_NULL(image);
1791 this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1792 }
1793
drawImageRect(const SkImage * image,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1794 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1795 SrcRectConstraint constraint) {
1796 RETURN_ON_NULL(image);
1797 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1798 constraint);
1799 }
1800
drawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1801 void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1802 const SkPaint* paint) {
1803 TRACE_EVENT0("skia", TRACE_FUNC);
1804 RETURN_ON_NULL(image);
1805 if (dst.isEmpty()) {
1806 return;
1807 }
1808 if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1809 this->onDrawImageNine(image, center, dst, paint);
1810 } else {
1811 this->drawImageRect(image, dst, paint);
1812 }
1813 }
1814
drawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1815 void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1816 const SkPaint* paint) {
1817 TRACE_EVENT0("skia", TRACE_FUNC);
1818 RETURN_ON_NULL(image);
1819 if (dst.isEmpty()) {
1820 return;
1821 }
1822
1823 SkIRect bounds;
1824 Lattice latticePlusBounds = lattice;
1825 if (!latticePlusBounds.fBounds) {
1826 bounds = SkIRect::MakeWH(image->width(), image->height());
1827 latticePlusBounds.fBounds = &bounds;
1828 }
1829
1830 if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
1831 this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1832 } else {
1833 this->drawImageRect(image, dst, paint);
1834 }
1835 }
1836
drawBitmap(const SkBitmap & bitmap,SkScalar dx,SkScalar dy,const SkPaint * paint)1837 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1838 TRACE_EVENT0("skia", TRACE_FUNC);
1839 if (bitmap.drawsNothing()) {
1840 return;
1841 }
1842 this->onDrawBitmap(bitmap, dx, dy, paint);
1843 }
1844
drawBitmapRect(const SkBitmap & bitmap,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1845 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1846 const SkPaint* paint, SrcRectConstraint constraint) {
1847 TRACE_EVENT0("skia", TRACE_FUNC);
1848 if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1849 return;
1850 }
1851 this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1852 }
1853
drawBitmapRect(const SkBitmap & bitmap,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1854 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1855 const SkPaint* paint, SrcRectConstraint constraint) {
1856 this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1857 }
1858
drawBitmapRect(const SkBitmap & bitmap,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1859 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1860 SrcRectConstraint constraint) {
1861 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1862 constraint);
1863 }
1864
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1865 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1866 const SkPaint* paint) {
1867 TRACE_EVENT0("skia", TRACE_FUNC);
1868 if (bitmap.drawsNothing() || dst.isEmpty()) {
1869 return;
1870 }
1871 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1872 this->onDrawBitmapNine(bitmap, center, dst, paint);
1873 } else {
1874 this->drawBitmapRect(bitmap, dst, paint);
1875 }
1876 }
1877
drawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1878 void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1879 const SkPaint* paint) {
1880 TRACE_EVENT0("skia", TRACE_FUNC);
1881 if (bitmap.drawsNothing() || dst.isEmpty()) {
1882 return;
1883 }
1884
1885 SkIRect bounds;
1886 Lattice latticePlusBounds = lattice;
1887 if (!latticePlusBounds.fBounds) {
1888 bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1889 latticePlusBounds.fBounds = &bounds;
1890 }
1891
1892 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
1893 this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1894 } else {
1895 this->drawBitmapRect(bitmap, dst, paint);
1896 }
1897 }
1898
drawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode mode,const SkRect * cull,const SkPaint * paint)1899 void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1900 const SkColor colors[], int count, SkBlendMode mode,
1901 const SkRect* cull, const SkPaint* paint) {
1902 TRACE_EVENT0("skia", TRACE_FUNC);
1903 RETURN_ON_NULL(atlas);
1904 if (count <= 0) {
1905 return;
1906 }
1907 SkASSERT(atlas);
1908 SkASSERT(tex);
1909 this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1910 }
1911
drawAnnotation(const SkRect & rect,const char key[],SkData * value)1912 void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1913 TRACE_EVENT0("skia", TRACE_FUNC);
1914 if (key) {
1915 this->onDrawAnnotation(rect, key, value);
1916 }
1917 }
1918
legacy_drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1919 void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1920 const SkPaint* paint, SrcRectConstraint constraint) {
1921 if (src) {
1922 this->drawImageRect(image, *src, dst, paint, constraint);
1923 } else {
1924 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1925 dst, paint, constraint);
1926 }
1927 }
legacy_drawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1928 void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1929 const SkPaint* paint, SrcRectConstraint constraint) {
1930 if (src) {
1931 this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1932 } else {
1933 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1934 dst, paint, constraint);
1935 }
1936 }
1937
private_draw_shadow_rec(const SkPath & path,const SkDrawShadowRec & rec)1938 void SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
1939 TRACE_EVENT0("skia", TRACE_FUNC);
1940 this->onDrawShadowRec(path, rec);
1941 }
1942
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)1943 void SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
1944 SkPaint paint;
1945 const SkRect& pathBounds = path.getBounds();
1946
1947 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
1948 while (iter.next()) {
1949 iter.fDevice->drawShadow(path, rec);
1950 }
1951 LOOPER_END
1952 }
1953
1954 //////////////////////////////////////////////////////////////////////////////
1955 // These are the virtual drawing methods
1956 //////////////////////////////////////////////////////////////////////////////
1957
onDiscard()1958 void SkCanvas::onDiscard() {
1959 if (fSurfaceBase) {
1960 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1961 }
1962 }
1963
onDrawPaint(const SkPaint & paint)1964 void SkCanvas::onDrawPaint(const SkPaint& paint) {
1965 this->internalDrawPaint(paint);
1966 }
1967
internalDrawPaint(const SkPaint & paint)1968 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1969 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
1970
1971 while (iter.next()) {
1972 iter.fDevice->drawPaint(looper.paint());
1973 }
1974
1975 LOOPER_END
1976 }
1977
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1978 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
1979 const SkPaint& paint) {
1980 if ((long)count <= 0) {
1981 return;
1982 }
1983
1984 SkRect r;
1985 const SkRect* bounds = nullptr;
1986 if (paint.canComputeFastBounds()) {
1987 // special-case 2 points (common for drawing a single line)
1988 if (2 == count) {
1989 r.set(pts[0], pts[1]);
1990 } else {
1991 r.set(pts, SkToInt(count));
1992 }
1993 SkRect storage;
1994 if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
1995 return;
1996 }
1997 bounds = &r;
1998 }
1999
2000 SkASSERT(pts != nullptr);
2001
2002 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2003
2004 while (iter.next()) {
2005 iter.fDevice->drawPoints(mode, count, pts, looper.paint());
2006 }
2007
2008 LOOPER_END
2009 }
2010
needs_autodrawlooper(SkCanvas * canvas,const SkPaint & paint)2011 static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
2012 return ((intptr_t)paint.getImageFilter() |
2013 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
2014 (intptr_t)canvas->getDrawFilter() |
2015 #endif
2016 (intptr_t)paint.getLooper() ) != 0;
2017 }
2018
onDrawRect(const SkRect & r,const SkPaint & paint)2019 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2020 SkASSERT(r.isSorted());
2021 if (paint.canComputeFastBounds()) {
2022 SkRect storage;
2023 if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2024 return;
2025 }
2026 }
2027
2028 if (needs_autodrawlooper(this, paint)) {
2029 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
2030
2031 while (iter.next()) {
2032 iter.fDevice->drawRect(r, looper.paint());
2033 }
2034
2035 LOOPER_END
2036 } else {
2037 this->predrawNotify(&r, &paint, false);
2038 SkDrawIter iter(this);
2039 while (iter.next()) {
2040 iter.fDevice->drawRect(r, paint);
2041 }
2042 }
2043 }
2044
onDrawRegion(const SkRegion & region,const SkPaint & paint)2045 void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
2046 SkRect regionRect = SkRect::Make(region.getBounds());
2047 if (paint.canComputeFastBounds()) {
2048 SkRect storage;
2049 if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
2050 return;
2051 }
2052 }
2053
2054 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, ®ionRect)
2055
2056 while (iter.next()) {
2057 iter.fDevice->drawRegion(region, looper.paint());
2058 }
2059
2060 LOOPER_END
2061 }
2062
onDrawOval(const SkRect & oval,const SkPaint & paint)2063 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2064 SkASSERT(oval.isSorted());
2065 if (paint.canComputeFastBounds()) {
2066 SkRect storage;
2067 if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2068 return;
2069 }
2070 }
2071
2072 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2073
2074 while (iter.next()) {
2075 iter.fDevice->drawOval(oval, looper.paint());
2076 }
2077
2078 LOOPER_END
2079 }
2080
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2081 void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2082 SkScalar sweepAngle, bool useCenter,
2083 const SkPaint& paint) {
2084 SkASSERT(oval.isSorted());
2085 if (paint.canComputeFastBounds()) {
2086 SkRect storage;
2087 // Note we're using the entire oval as the bounds.
2088 if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2089 return;
2090 }
2091 }
2092
2093 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2094
2095 while (iter.next()) {
2096 iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2097 }
2098
2099 LOOPER_END
2100 }
2101
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)2102 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2103 if (paint.canComputeFastBounds()) {
2104 SkRect storage;
2105 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2106 return;
2107 }
2108 }
2109
2110 if (rrect.isRect()) {
2111 // call the non-virtual version
2112 this->SkCanvas::drawRect(rrect.getBounds(), paint);
2113 return;
2114 } else if (rrect.isOval()) {
2115 // call the non-virtual version
2116 this->SkCanvas::drawOval(rrect.getBounds(), paint);
2117 return;
2118 }
2119
2120 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2121
2122 while (iter.next()) {
2123 iter.fDevice->drawRRect(rrect, looper.paint());
2124 }
2125
2126 LOOPER_END
2127 }
2128
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)2129 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2130 if (paint.canComputeFastBounds()) {
2131 SkRect storage;
2132 if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2133 return;
2134 }
2135 }
2136
2137 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
2138
2139 while (iter.next()) {
2140 iter.fDevice->drawDRRect(outer, inner, looper.paint());
2141 }
2142
2143 LOOPER_END
2144 }
2145
onDrawPath(const SkPath & path,const SkPaint & paint)2146 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2147 if (!path.isFinite()) {
2148 return;
2149 }
2150
2151 const SkRect& pathBounds = path.getBounds();
2152 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2153 SkRect storage;
2154 if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2155 return;
2156 }
2157 }
2158
2159 if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
2160 if (path.isInverseFillType()) {
2161 this->internalDrawPaint(paint);
2162 return;
2163 }
2164 }
2165
2166 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
2167
2168 while (iter.next()) {
2169 iter.fDevice->drawPath(path, looper.paint());
2170 }
2171
2172 LOOPER_END
2173 }
2174
canDrawBitmapAsSprite(SkScalar x,SkScalar y,int w,int h,const SkPaint & paint)2175 bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2176 if (!paint.getImageFilter()) {
2177 return false;
2178 }
2179
2180 const SkMatrix& ctm = this->getTotalMatrix();
2181 if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2182 return false;
2183 }
2184
2185 // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2186 // Once we can filter and the filter will return a result larger than itself, we should be
2187 // able to remove this constraint.
2188 // skbug.com/4526
2189 //
2190 SkPoint pt;
2191 ctm.mapXY(x, y, &pt);
2192 SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2193 return ir.contains(fMCRec->fRasterClip.getBounds());
2194 }
2195
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)2196 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2197 SkRect bounds = SkRect::MakeXYWH(x, y,
2198 SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2199 if (nullptr == paint || paint->canComputeFastBounds()) {
2200 SkRect tmp = bounds;
2201 if (paint) {
2202 paint->computeFastBounds(tmp, &tmp);
2203 }
2204 if (this->quickReject(tmp)) {
2205 return;
2206 }
2207 }
2208
2209 SkLazyPaint lazy;
2210 if (nullptr == paint) {
2211 paint = lazy.init();
2212 }
2213
2214 sk_sp<SkSpecialImage> special;
2215 bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2216 *paint);
2217 if (drawAsSprite && paint->getImageFilter()) {
2218 special = this->getDevice()->makeSpecial(image);
2219 if (!special) {
2220 drawAsSprite = false;
2221 }
2222 }
2223
2224 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2225
2226 while (iter.next()) {
2227 const SkPaint& pnt = looper.paint();
2228 if (special) {
2229 SkPoint pt;
2230 iter.fDevice->ctm().mapXY(x, y, &pt);
2231 iter.fDevice->drawSpecial(special.get(),
2232 SkScalarRoundToInt(pt.fX),
2233 SkScalarRoundToInt(pt.fY), pnt,
2234 nullptr, SkMatrix::I());
2235 } else {
2236 iter.fDevice->drawImage(image, x, y, pnt);
2237 }
2238 }
2239
2240 LOOPER_END
2241 }
2242
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2243 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2244 const SkPaint* paint, SrcRectConstraint constraint) {
2245 if (nullptr == paint || paint->canComputeFastBounds()) {
2246 SkRect storage = dst;
2247 if (paint) {
2248 paint->computeFastBounds(dst, &storage);
2249 }
2250 if (this->quickReject(storage)) {
2251 return;
2252 }
2253 }
2254 SkLazyPaint lazy;
2255 if (nullptr == paint) {
2256 paint = lazy.init();
2257 }
2258
2259 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2260 image->isOpaque())
2261
2262 while (iter.next()) {
2263 iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2264 }
2265
2266 LOOPER_END
2267 }
2268
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)2269 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2270 SkDEBUGCODE(bitmap.validate();)
2271
2272 if (bitmap.drawsNothing()) {
2273 return;
2274 }
2275
2276 SkLazyPaint lazy;
2277 if (nullptr == paint) {
2278 paint = lazy.init();
2279 }
2280
2281 SkRect bounds;
2282 bitmap.getBounds(&bounds);
2283 bounds.offset(x, y);
2284 bool canFastBounds = paint->canComputeFastBounds();
2285 if (canFastBounds) {
2286 SkRect storage;
2287 if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
2288 return;
2289 }
2290 }
2291
2292 sk_sp<SkSpecialImage> special;
2293 bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2294 bitmap.height(), *paint);
2295 if (drawAsSprite && paint->getImageFilter()) {
2296 special = this->getDevice()->makeSpecial(bitmap);
2297 if (!special) {
2298 drawAsSprite = false;
2299 }
2300 }
2301
2302 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2303
2304 while (iter.next()) {
2305 const SkPaint& pnt = looper.paint();
2306 if (special) {
2307 SkPoint pt;
2308 iter.fDevice->ctm().mapXY(x, y, &pt);
2309 iter.fDevice->drawSpecial(special.get(),
2310 SkScalarRoundToInt(pt.fX),
2311 SkScalarRoundToInt(pt.fY), pnt,
2312 nullptr, SkMatrix::I());
2313 } else {
2314 iter.fDevice->drawBitmap(bitmap, x, y, looper.paint());
2315 }
2316 }
2317
2318 LOOPER_END
2319 }
2320
2321 // 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)2322 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2323 const SkRect& dst, const SkPaint* paint,
2324 SrcRectConstraint constraint) {
2325 if (bitmap.drawsNothing() || dst.isEmpty()) {
2326 return;
2327 }
2328
2329 if (nullptr == paint || paint->canComputeFastBounds()) {
2330 SkRect storage;
2331 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2332 return;
2333 }
2334 }
2335
2336 SkLazyPaint lazy;
2337 if (nullptr == paint) {
2338 paint = lazy.init();
2339 }
2340
2341 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2342 bitmap.isOpaque())
2343
2344 while (iter.next()) {
2345 iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2346 }
2347
2348 LOOPER_END
2349 }
2350
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2351 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2352 const SkPaint* paint, SrcRectConstraint constraint) {
2353 SkDEBUGCODE(bitmap.validate();)
2354 this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2355 }
2356
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2357 void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2358 const SkPaint* paint) {
2359 if (nullptr == paint || paint->canComputeFastBounds()) {
2360 SkRect storage;
2361 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2362 return;
2363 }
2364 }
2365
2366 SkLazyPaint lazy;
2367 if (nullptr == paint) {
2368 paint = lazy.init();
2369 }
2370
2371 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2372
2373 while (iter.next()) {
2374 iter.fDevice->drawImageNine(image, center, dst, looper.paint());
2375 }
2376
2377 LOOPER_END
2378 }
2379
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2380 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2381 const SkPaint* paint) {
2382 SkDEBUGCODE(bitmap.validate();)
2383
2384 if (nullptr == paint || paint->canComputeFastBounds()) {
2385 SkRect storage;
2386 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2387 return;
2388 }
2389 }
2390
2391 SkLazyPaint lazy;
2392 if (nullptr == paint) {
2393 paint = lazy.init();
2394 }
2395
2396 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2397
2398 while (iter.next()) {
2399 iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
2400 }
2401
2402 LOOPER_END
2403 }
2404
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2405 void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2406 const SkPaint* paint) {
2407 if (nullptr == paint || paint->canComputeFastBounds()) {
2408 SkRect storage;
2409 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2410 return;
2411 }
2412 }
2413
2414 SkLazyPaint lazy;
2415 if (nullptr == paint) {
2416 paint = lazy.init();
2417 }
2418
2419 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2420
2421 while (iter.next()) {
2422 iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2423 }
2424
2425 LOOPER_END
2426 }
2427
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2428 void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2429 const SkRect& dst, const SkPaint* paint) {
2430 if (nullptr == paint || paint->canComputeFastBounds()) {
2431 SkRect storage;
2432 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2433 return;
2434 }
2435 }
2436
2437 SkLazyPaint lazy;
2438 if (nullptr == paint) {
2439 paint = lazy.init();
2440 }
2441
2442 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2443
2444 while (iter.next()) {
2445 iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2446 }
2447
2448 LOOPER_END
2449 }
2450
2451 class SkDeviceFilteredPaint {
2452 public:
SkDeviceFilteredPaint(SkBaseDevice * device,const SkPaint & paint)2453 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2454 uint32_t filteredFlags = device->filterTextFlags(paint);
2455 if (filteredFlags != paint.getFlags()) {
2456 SkPaint* newPaint = fLazy.set(paint);
2457 newPaint->setFlags(filteredFlags);
2458 fPaint = newPaint;
2459 } else {
2460 fPaint = &paint;
2461 }
2462 }
2463
paint() const2464 const SkPaint& paint() const { return *fPaint; }
2465
2466 private:
2467 const SkPaint* fPaint;
2468 SkLazyPaint fLazy;
2469 };
2470
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2471 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2472 const SkPaint& paint) {
2473 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2474
2475 while (iter.next()) {
2476 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2477 iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
2478 }
2479
2480 LOOPER_END
2481 }
2482
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2483 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2484 const SkPaint& paint) {
2485 SkPoint textOffset = SkPoint::Make(0, 0);
2486
2487 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2488
2489 while (iter.next()) {
2490 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2491 iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2492 dfp.paint());
2493 }
2494
2495 LOOPER_END
2496 }
2497
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2498 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2499 SkScalar constY, const SkPaint& paint) {
2500
2501 SkPoint textOffset = SkPoint::Make(0, constY);
2502
2503 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2504
2505 while (iter.next()) {
2506 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2507 iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2508 dfp.paint());
2509 }
2510
2511 LOOPER_END
2512 }
2513
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2514 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2515 const SkMatrix* matrix, const SkPaint& paint) {
2516 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2517
2518 while (iter.next()) {
2519 iter.fDevice->drawTextOnPath(text, byteLength, path,
2520 matrix, looper.paint());
2521 }
2522
2523 LOOPER_END
2524 }
2525
onDrawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2526 void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2527 const SkRect* cullRect, const SkPaint& paint) {
2528 if (cullRect && this->quickReject(*cullRect)) {
2529 return;
2530 }
2531
2532 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2533
2534 while (iter.next()) {
2535 iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
2536 }
2537
2538 LOOPER_END
2539 }
2540
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2541 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2542 const SkPaint& paint) {
2543
2544 SkRect storage;
2545 const SkRect* bounds = nullptr;
2546 if (paint.canComputeFastBounds()) {
2547 storage = blob->bounds().makeOffset(x, y);
2548 SkRect tmp;
2549 if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2550 return;
2551 }
2552 bounds = &storage;
2553 }
2554
2555 // We cannot filter in the looper as we normally do, because the paint is
2556 // incomplete at this point (text-related attributes are embedded within blob run paints).
2557 SkDrawFilter* drawFilter = fMCRec->fFilter;
2558 fMCRec->fFilter = nullptr;
2559
2560 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2561
2562 while (iter.next()) {
2563 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2564 iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
2565 }
2566
2567 LOOPER_END
2568
2569 fMCRec->fFilter = drawFilter;
2570 }
2571
drawString(const SkString & string,SkScalar x,SkScalar y,const SkPaint & paint)2572 void SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) {
2573 this->drawText(string.c_str(), string.size(), x, y, paint);
2574 }
2575
2576 // 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)2577 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2578 const SkPaint& paint) {
2579 TRACE_EVENT0("skia", TRACE_FUNC);
2580 if (byteLength) {
2581 sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2582 this->onDrawText(text, byteLength, x, y, paint);
2583 }
2584 }
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2585 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2586 const SkPaint& paint) {
2587 TRACE_EVENT0("skia", TRACE_FUNC);
2588 if (byteLength) {
2589 sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2590 this->onDrawPosText(text, byteLength, pos, paint);
2591 }
2592 }
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2593 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2594 SkScalar constY, const SkPaint& paint) {
2595 TRACE_EVENT0("skia", TRACE_FUNC);
2596 if (byteLength) {
2597 sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2598 this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2599 }
2600 }
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2601 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2602 const SkMatrix* matrix, const SkPaint& paint) {
2603 TRACE_EVENT0("skia", TRACE_FUNC);
2604 if (byteLength) {
2605 sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2606 this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2607 }
2608 }
drawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2609 void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2610 const SkRect* cullRect, const SkPaint& paint) {
2611 TRACE_EVENT0("skia", TRACE_FUNC);
2612 if (byteLength) {
2613 sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2614 this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
2615 }
2616 }
drawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2617 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2618 const SkPaint& paint) {
2619 TRACE_EVENT0("skia", TRACE_FUNC);
2620 RETURN_ON_NULL(blob);
2621 RETURN_ON_FALSE(blob->bounds().makeOffset(x, y).isFinite());
2622 this->onDrawTextBlob(blob, x, y, paint);
2623 }
2624
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)2625 void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2626 const SkPaint& paint) {
2627 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2628
2629 while (iter.next()) {
2630 // In the common case of one iteration we could std::move vertices here.
2631 iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2632 }
2633
2634 LOOPER_END
2635 }
2636
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2637 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2638 const SkPoint texCoords[4], SkBlendMode bmode,
2639 const SkPaint& paint) {
2640 TRACE_EVENT0("skia", TRACE_FUNC);
2641 if (nullptr == cubics) {
2642 return;
2643 }
2644
2645 this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
2646 }
2647
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2648 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2649 const SkPoint texCoords[4], SkBlendMode bmode,
2650 const SkPaint& paint) {
2651 // Since a patch is always within the convex hull of the control points, we discard it when its
2652 // bounding rectangle is completely outside the current clip.
2653 SkRect bounds;
2654 bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2655 if (this->quickReject(bounds)) {
2656 return;
2657 }
2658
2659 const bool interpColorsLinearly = (this->imageInfo().colorSpace() != nullptr);
2660
2661 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2662
2663 while (iter.next()) {
2664 iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, interpColorsLinearly, paint);
2665 }
2666
2667 LOOPER_END
2668 }
2669
drawDrawable(SkDrawable * dr,SkScalar x,SkScalar y)2670 void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2671 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2672 TRACE_EVENT0("skia", TRACE_FUNC);
2673 #endif
2674 RETURN_ON_NULL(dr);
2675 if (x || y) {
2676 SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2677 this->onDrawDrawable(dr, &matrix);
2678 } else {
2679 this->onDrawDrawable(dr, nullptr);
2680 }
2681 }
2682
drawDrawable(SkDrawable * dr,const SkMatrix * matrix)2683 void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2684 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2685 TRACE_EVENT0("skia", TRACE_FUNC);
2686 #endif
2687 RETURN_ON_NULL(dr);
2688 if (matrix && matrix->isIdentity()) {
2689 matrix = nullptr;
2690 }
2691 this->onDrawDrawable(dr, matrix);
2692 }
2693
onDrawDrawable(SkDrawable * dr,const SkMatrix * matrix)2694 void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2695 // drawable bounds are no longer reliable (e.g. android displaylist)
2696 // so don't use them for quick-reject
2697 dr->draw(this, matrix);
2698 }
2699
onDrawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2700 void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2701 const SkColor colors[], int count, SkBlendMode bmode,
2702 const SkRect* cull, const SkPaint* paint) {
2703 if (cull && this->quickReject(*cull)) {
2704 return;
2705 }
2706
2707 SkPaint pnt;
2708 if (paint) {
2709 pnt = *paint;
2710 }
2711
2712 LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2713 while (iter.next()) {
2714 iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
2715 }
2716 LOOPER_END
2717 }
2718
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)2719 void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2720 SkASSERT(key);
2721
2722 SkPaint paint;
2723 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2724 while (iter.next()) {
2725 iter.fDevice->drawAnnotation(rect, key, value);
2726 }
2727 LOOPER_END
2728 }
2729
2730 //////////////////////////////////////////////////////////////////////////////
2731 // These methods are NOT virtual, and therefore must call back into virtual
2732 // methods, rather than actually drawing themselves.
2733 //////////////////////////////////////////////////////////////////////////////
2734
drawColor(SkColor c,SkBlendMode mode)2735 void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
2736 SkPaint paint;
2737 paint.setColor(c);
2738 paint.setBlendMode(mode);
2739 this->drawPaint(paint);
2740 }
2741
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2742 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2743 const SkPoint pt = { x, y };
2744 this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2745 }
2746
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2747 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
2748 SkPoint pts[2];
2749 pts[0].set(x0, y0);
2750 pts[1].set(x1, y1);
2751 this->drawPoints(kLines_PointMode, 2, pts, paint);
2752 }
2753
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2754 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
2755 if (radius < 0) {
2756 radius = 0;
2757 }
2758
2759 SkRect r;
2760 r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2761 this->drawOval(r, paint);
2762 }
2763
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2764 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2765 const SkPaint& paint) {
2766 if (rx > 0 && ry > 0) {
2767 SkRRect rrect;
2768 rrect.setRectXY(r, rx, ry);
2769 this->drawRRect(rrect, paint);
2770 } else {
2771 this->drawRect(r, paint);
2772 }
2773 }
2774
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2775 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2776 SkScalar sweepAngle, bool useCenter,
2777 const SkPaint& paint) {
2778 TRACE_EVENT0("skia", TRACE_FUNC);
2779 if (oval.isEmpty() || !sweepAngle) {
2780 return;
2781 }
2782 this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
2783 }
2784
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2785 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2786 const SkPath& path, SkScalar hOffset,
2787 SkScalar vOffset, const SkPaint& paint) {
2788 SkMatrix matrix;
2789
2790 matrix.setTranslate(hOffset, vOffset);
2791 this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2792 }
2793
2794 ///////////////////////////////////////////////////////////////////////////////
2795
2796 /**
2797 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2798 * against the playback cost of recursing into the subpicture to get at its actual ops.
2799 *
2800 * For now we pick a conservatively small value, though measurement (and other heuristics like
2801 * the type of ops contained) may justify changing this value.
2802 */
2803 #define kMaxPictureOpsToUnrollInsteadOfRef 1
2804
drawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2805 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2806 TRACE_EVENT0("skia", TRACE_FUNC);
2807 RETURN_ON_NULL(picture);
2808
2809 if (matrix && matrix->isIdentity()) {
2810 matrix = nullptr;
2811 }
2812 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2813 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2814 picture->playback(this);
2815 } else {
2816 this->onDrawPicture(picture, matrix, paint);
2817 }
2818 }
2819
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2820 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2821 const SkPaint* paint) {
2822 if (!paint || paint->canComputeFastBounds()) {
2823 SkRect bounds = picture->cullRect();
2824 if (paint) {
2825 paint->computeFastBounds(bounds, &bounds);
2826 }
2827 if (matrix) {
2828 matrix->mapRect(&bounds);
2829 }
2830 if (this->quickReject(bounds)) {
2831 return;
2832 }
2833 }
2834
2835 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2836 picture->playback(this);
2837 }
2838
2839 ///////////////////////////////////////////////////////////////////////////////
2840 ///////////////////////////////////////////////////////////////////////////////
2841
LayerIter(SkCanvas * canvas)2842 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
2843 static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
2844
2845 SkASSERT(canvas);
2846
2847 fImpl = new (fStorage) SkDrawIter(canvas);
2848 fDone = !fImpl->next();
2849 }
2850
~LayerIter()2851 SkCanvas::LayerIter::~LayerIter() {
2852 fImpl->~SkDrawIter();
2853 }
2854
next()2855 void SkCanvas::LayerIter::next() {
2856 fDone = !fImpl->next();
2857 }
2858
device() const2859 SkBaseDevice* SkCanvas::LayerIter::device() const {
2860 return fImpl->fDevice;
2861 }
2862
matrix() const2863 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2864 return fImpl->fDevice->ctm();
2865 }
2866
paint() const2867 const SkPaint& SkCanvas::LayerIter::paint() const {
2868 const SkPaint* paint = fImpl->getPaint();
2869 if (nullptr == paint) {
2870 paint = &fDefaultPaint;
2871 }
2872 return *paint;
2873 }
2874
clip(SkRegion * rgn) const2875 void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
2876 return fImpl->fDevice->onAsRgnClip(rgn);
2877 }
2878
x() const2879 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2880 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2881
2882 ///////////////////////////////////////////////////////////////////////////////
2883
supported_for_raster_canvas(const SkImageInfo & info)2884 static bool supported_for_raster_canvas(const SkImageInfo& info) {
2885 switch (info.alphaType()) {
2886 case kPremul_SkAlphaType:
2887 case kOpaque_SkAlphaType:
2888 break;
2889 default:
2890 return false;
2891 }
2892
2893 switch (info.colorType()) {
2894 case kAlpha_8_SkColorType:
2895 case kRGB_565_SkColorType:
2896 case kN32_SkColorType:
2897 case kRGBA_F16_SkColorType:
2898 break;
2899 default:
2900 return false;
2901 }
2902
2903 return true;
2904 }
2905
MakeRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkSurfaceProps * props)2906 std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
2907 size_t rowBytes, const SkSurfaceProps* props) {
2908 if (!supported_for_raster_canvas(info)) {
2909 return nullptr;
2910 }
2911
2912 SkBitmap bitmap;
2913 if (!bitmap.installPixels(info, pixels, rowBytes)) {
2914 return nullptr;
2915 }
2916
2917 return props ?
2918 skstd::make_unique<SkCanvas>(bitmap, *props) :
2919 skstd::make_unique<SkCanvas>(bitmap);
2920 }
2921
2922 ///////////////////////////////////////////////////////////////////////////////
2923
SkNoDrawCanvas(int width,int height)2924 SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
2925 : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
2926
SkNoDrawCanvas(const SkIRect & bounds)2927 SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
2928 : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
2929
getSaveLayerStrategy(const SaveLayerRec & rec)2930 SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
2931 (void)this->INHERITED::getSaveLayerStrategy(rec);
2932 return kNoLayer_SaveLayerStrategy;
2933 }
2934
2935 ///////////////////////////////////////////////////////////////////////////////
2936
2937 static_assert((int)SkRegion::kDifference_Op == (int)kDifference_SkClipOp, "");
2938 static_assert((int)SkRegion::kIntersect_Op == (int)kIntersect_SkClipOp, "");
2939 static_assert((int)SkRegion::kUnion_Op == (int)kUnion_SkClipOp, "");
2940 static_assert((int)SkRegion::kXOR_Op == (int)kXOR_SkClipOp, "");
2941 static_assert((int)SkRegion::kReverseDifference_Op == (int)kReverseDifference_SkClipOp, "");
2942 static_assert((int)SkRegion::kReplace_Op == (int)kReplace_SkClipOp, "");
2943
2944 ///////////////////////////////////////////////////////////////////////////////////////////////////
2945
accessTopRasterHandle() const2946 SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
2947 if (fAllocator && fMCRec->fTopLayer->fDevice) {
2948 const auto& dev = fMCRec->fTopLayer->fDevice;
2949 SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
2950 SkIPoint origin = dev->getOrigin();
2951 SkMatrix ctm = this->getTotalMatrix();
2952 ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
2953
2954 SkIRect clip = fMCRec->fRasterClip.getBounds();
2955 clip.offset(-origin.x(), -origin.y());
2956 if (!clip.intersect(0, 0, dev->width(), dev->height())) {
2957 clip.setEmpty();
2958 }
2959
2960 fAllocator->updateHandle(handle, ctm, clip);
2961 return handle;
2962 }
2963 return nullptr;
2964 }
2965
install(SkBitmap * bm,const SkImageInfo & info,const SkRasterHandleAllocator::Rec & rec)2966 static bool install(SkBitmap* bm, const SkImageInfo& info,
2967 const SkRasterHandleAllocator::Rec& rec) {
2968 return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
2969 }
2970
allocBitmap(const SkImageInfo & info,SkBitmap * bm)2971 SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
2972 SkBitmap* bm) {
2973 SkRasterHandleAllocator::Rec rec;
2974 if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
2975 return nullptr;
2976 }
2977 return rec.fHandle;
2978 }
2979
2980 std::unique_ptr<SkCanvas>
MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,const SkImageInfo & info,const Rec * rec)2981 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
2982 const SkImageInfo& info, const Rec* rec) {
2983 if (!alloc || !supported_for_raster_canvas(info)) {
2984 return nullptr;
2985 }
2986
2987 SkBitmap bm;
2988 Handle hndl;
2989
2990 if (rec) {
2991 hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
2992 } else {
2993 hndl = alloc->allocBitmap(info, &bm);
2994 }
2995 return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
2996 }
2997
2998 ///////////////////////////////////////////////////////////////////////////////////////////////////
2999
3000
3001