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