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