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