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