Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkRecordDraw.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 Google Inc.
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
9
15#include "include/core/SkMesh.h"
18#include "include/core/SkRect.h"
34#include "src/core/SkRecord.h"
35#include "src/core/SkRecords.h"
38
39#include <algorithm>
40#include <optional>
41#include <vector>
42
43class SkImageFilter;
44
45void SkRecordDraw(const SkRecord& record,
46 SkCanvas* canvas,
47 SkPicture const* const drawablePicts[],
48 SkDrawable* const drawables[],
49 int drawableCount,
50 const SkBBoxHierarchy* bbh,
52 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
53
54 if (bbh) {
55 // Draw only ops that affect pixels in the canvas's current clip.
56 // The SkRecord and BBH were recorded in identity space. This canvas
57 // is not necessarily in that same space. getLocalClipBounds() returns us
58 // this canvas' clip bounds transformed back into identity space, which
59 // lets us query the BBH.
60 SkRect query = canvas->getLocalClipBounds();
61
62 std::vector<int> ops;
63 bbh->search(query, &ops);
64
65 SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
66 for (int i = 0; i < (int)ops.size(); i++) {
67 if (callback && callback->abort()) {
68 return;
69 }
70 // This visit call uses the SkRecords::Draw::operator() to call
71 // methods on the |canvas|, wrapped by methods defined with the
72 // DRAW() macro.
73 record.visit(ops[i], draw);
74 }
75 } else {
76 // Draw all ops.
77 SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
78 for (int i = 0; i < record.count(); i++) {
79 if (callback && callback->abort()) {
80 return;
81 }
82 // This visit call uses the SkRecords::Draw::operator() to call
83 // methods on the |canvas|, wrapped by methods defined with the
84 // DRAW() macro.
85 record.visit(i, draw);
86 }
87 }
88}
89
90namespace SkRecords {
91
92// NoOps draw nothing.
93template <> void Draw::draw(const NoOp&) {}
94
95#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
96DRAW(Restore, restore())
97DRAW(Save, save())
98DRAW(SaveLayer,
99 saveLayer(SkCanvasPriv::ScaledBackdropLayer(
100 r.bounds,
101 r.paint,
102 r.backdrop.get(),
105 SkCanvas::FilterSpan{const_cast<sk_sp<SkImageFilter>*>(r.filters.data()),
106 r.filters.size()})))
107
108template <> void Draw::draw(const SaveBehind& r) {
109 SkCanvasPriv::SaveBehind(fCanvas, r.subset);
110}
111
112template <> void Draw::draw(const DrawBehind& r) {
113 SkCanvasPriv::DrawBehind(fCanvas, r.paint);
114}
115
116DRAW(SetMatrix, setMatrix(fInitialCTM.asM33() * r.matrix))
117DRAW(SetM44, setMatrix(fInitialCTM * r.matrix))
118DRAW(Concat44, concat(r.matrix))
119DRAW(Concat, concat(r.matrix))
120DRAW(Translate, translate(r.dx, r.dy))
121DRAW(Scale, scale(r.sx, r.sy))
122
123DRAW(ClipPath, clipPath(r.path, r.opAA.op(), r.opAA.aa()))
124DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op(), r.opAA.aa()))
125DRAW(ClipRect, clipRect(r.rect, r.opAA.op(), r.opAA.aa()))
126DRAW(ClipRegion, clipRegion(r.region, r.op))
127DRAW(ClipShader, clipShader(r.shader, r.op))
128
129template <> void Draw::draw(const ResetClip& r) {
131}
132
133DRAW(DrawArc, drawArc(r.oval, r.startAngle, r.sweepAngle, r.useCenter, r.paint))
134DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint))
135DRAW(DrawImage, drawImage(r.image.get(), r.left, r.top, r.sampling, r.paint))
136
137template <> void Draw::draw(const DrawImageLattice& r) {
138 SkCanvas::Lattice lattice;
139 lattice.fXCount = r.xCount;
140 lattice.fXDivs = r.xDivs;
141 lattice.fYCount = r.yCount;
142 lattice.fYDivs = r.yDivs;
143 lattice.fRectTypes = (0 == r.flagCount) ? nullptr : r.flags;
144 lattice.fColors = (0 == r.flagCount) ? nullptr : r.colors;
145 lattice.fBounds = &r.src;
146 fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.filter, r.paint);
147}
148
149DRAW(DrawImageRect, drawImageRect(r.image.get(), r.src, r.dst, r.sampling, r.paint, r.constraint))
150DRAW(DrawOval, drawOval(r.oval, r.paint))
151DRAW(DrawPaint, drawPaint(r.paint))
152DRAW(DrawPath, drawPath(r.path, r.paint))
153DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.bmode, r.paint))
154DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint))
155DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint))
156DRAW(DrawRRect, drawRRect(r.rrect, r.paint))
157DRAW(DrawRect, drawRect(r.rect, r.paint))
158DRAW(DrawRegion, drawRegion(r.region, r.paint))
159DRAW(DrawTextBlob, drawTextBlob(r.blob.get(), r.x, r.y, r.paint))
160DRAW(DrawSlug, drawSlug(r.slug.get(), r.paint))
161DRAW(DrawAtlas, drawAtlas(r.atlas.get(), r.xforms, r.texs, r.colors, r.count, r.mode, r.sampling,
162 r.cull, r.paint))
163DRAW(DrawVertices, drawVertices(r.vertices, r.bmode, r.paint))
164DRAW(DrawMesh, drawMesh(r.mesh, r.blender, r.paint))
165DRAW(DrawShadowRec, private_draw_shadow_rec(r.path, r.rec))
166DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get()))
167
169 r.rect, r.clip, r.aa, r.color, r.mode))
171 r.set.get(), r.count, r.dstClips, r.preViewMatrices, r.sampling, r.paint, r.constraint))
172
173#undef DRAW
174
175template <> void Draw::draw(const DrawDrawable& r) {
176 SkASSERT(r.index >= 0);
177 SkASSERT(r.index < fDrawableCount);
178 if (fDrawables) {
179 SkASSERT(nullptr == fDrawablePicts);
180 fCanvas->drawDrawable(fDrawables[r.index], r.matrix);
181 } else {
182 fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, nullptr);
183 }
184}
185
186// This is an SkRecord visitor that fills an SkBBoxHierarchy.
187//
188// The interesting part here is how to calculate bounds for ops which don't
189// have intrinsic bounds. What is the bounds of a Save or a Translate?
190//
191// We answer this by thinking about a particular definition of bounds: if I
192// don't execute this op, pixels in this rectangle might draw incorrectly. So
193// the bounds of a Save, a Translate, a Restore, etc. are the union of the
194// bounds of Draw* ops that they might have an effect on. For any given
195// Save/Restore block, the bounds of the Save, the Restore, and any other
196// non-drawing ("control") ops inside are exactly the union of the bounds of
197// the drawing ops inside that block.
198//
199// To implement this, we keep a stack of active Save blocks. As we consume ops
200// inside the Save/Restore block, drawing ops are unioned with the bounds of
201// the block, and control ops are stashed away for later. When we finish the
202// block with a Restore, our bounds are complete, and we go back and fill them
203// in for all the control ops we stashed away.
205public:
206 FillBounds(const SkRect& cullRect, const SkRecord& record,
208 : fCullRect(cullRect)
209 , fBounds(bounds)
210 , fMeta(meta) {
211 fCTM = SkMatrix::I();
212
213 // We push an extra save block to track the bounds of any top-level control operations.
214 fSaveStack.push_back({ 0, Bounds::MakeEmpty(), nullptr, fCTM });
215 }
216
218 // If we have any lingering unpaired Saves, simulate restores to make
219 // sure all ops in those Save blocks have their bounds calculated.
220 while (!fSaveStack.empty()) {
221 this->popSaveBlock();
222 }
223
224 // Any control ops not part of any Save/Restore block draw everywhere.
225 while (!fControlIndices.empty()) {
226 this->popControl(fCullRect);
227 }
228 }
229
230 void setCurrentOp(int currentOp) { fCurrentOp = currentOp; }
231
232
233 template <typename T> void operator()(const T& op) {
234 this->updateCTM(op);
235 this->trackBounds(op);
236 }
237
238 // In this file, SkRect are in local coordinates, Bounds are translated back to identity space.
239 typedef SkRect Bounds;
240
241 // Adjust rect for all paints that may affect its geometry, then map it to identity space.
243 // Inverted rectangles really confuse our BBHs.
244 rect.sort();
245
246 // Adjust the rect for its own paint.
247 if (!AdjustForPaint(paint, &rect)) {
248 // The paint could do anything to our bounds. The only safe answer is the cull.
249 return fCullRect;
250 }
251
252 // Adjust rect for all the paints from the SaveLayers we're inside.
253 if (!this->adjustForSaveLayerPaints(&rect)) {
254 // Same deal as above.
255 return fCullRect;
256 }
257
258 // Map the rect back to identity space.
259 fCTM.mapRect(&rect);
260
261 // Nothing can draw outside the cull rect.
262 if (!rect.intersect(fCullRect)) {
263 return Bounds::MakeEmpty();
264 }
265
266 return rect;
267 }
268
269private:
270 struct SaveBounds {
271 int controlOps; // Number of control ops in this Save block, including the Save.
272 Bounds bounds; // Bounds of everything in the block.
273 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block.
274 SkMatrix ctm;
275 };
276
277 // Only Restore, SetMatrix, Concat, and Translate change the CTM.
278 template <typename T> void updateCTM(const T&) {}
279 void updateCTM(const Restore& op) { fCTM = op.matrix; }
280 void updateCTM(const SetMatrix& op) { fCTM = op.matrix; }
281 void updateCTM(const SetM44& op) { fCTM = op.matrix.asM33(); }
282 void updateCTM(const Concat44& op) { fCTM.preConcat(op.matrix.asM33()); }
283 void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); }
284 void updateCTM(const Scale& op) { fCTM.preScale(op.sx, op.sy); }
285 void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); }
286
287 // The bounds of these ops must be calculated when we hit the Restore
288 // from the bounds of the ops in the same Save block.
289 void trackBounds(const Save&) { this->pushSaveBlock(nullptr); }
290 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); }
291 void trackBounds(const SaveBehind&) { this->pushSaveBlock(nullptr); }
292 void trackBounds(const Restore&) {
293 const bool isSaveLayer = fSaveStack.back().paint != nullptr;
294 fBounds[fCurrentOp] = this->popSaveBlock();
295 fMeta [fCurrentOp].isDraw = isSaveLayer;
296 }
297
298 void trackBounds(const SetMatrix&) { this->pushControl(); }
299 void trackBounds(const SetM44&) { this->pushControl(); }
300 void trackBounds(const Concat&) { this->pushControl(); }
301 void trackBounds(const Concat44&) { this->pushControl(); }
302 void trackBounds(const Scale&) { this->pushControl(); }
303 void trackBounds(const Translate&) { this->pushControl(); }
304 void trackBounds(const ClipRect&) { this->pushControl(); }
305 void trackBounds(const ClipRRect&) { this->pushControl(); }
306 void trackBounds(const ClipPath&) { this->pushControl(); }
307 void trackBounds(const ClipRegion&) { this->pushControl(); }
308 void trackBounds(const ClipShader&) { this->pushControl(); }
309 void trackBounds(const ResetClip&) { this->pushControl(); }
310
311
312 // For all other ops, we can calculate and store the bounds directly now.
313 template <typename T> void trackBounds(const T& op) {
314 fBounds[fCurrentOp] = this->bounds(op);
315 fMeta [fCurrentOp].isDraw = true;
316 this->updateSaveBounds(fBounds[fCurrentOp]);
317 }
318
319 void pushSaveBlock(const SkPaint* paint) {
320 // Starting a new Save block. Push a new entry to represent that.
321 SaveBounds sb;
322 sb.controlOps = 0;
323 // If the paint affects transparent black,
324 // the bound shouldn't be smaller than the cull.
325 sb.bounds =
326 PaintMayAffectTransparentBlack(paint) ? fCullRect : Bounds::MakeEmpty();
327 sb.paint = paint;
328 sb.ctm = this->fCTM;
329
330 fSaveStack.push_back(sb);
331 this->pushControl();
332 }
333
334 static bool PaintMayAffectTransparentBlack(const SkPaint* paint) {
335 if (paint) {
336 // FIXME: this is very conservative
337 if ((paint->getImageFilter() &&
338 as_IFB(paint->getImageFilter())->affectsTransparentBlack()) ||
339 (paint->getColorFilter() &&
340 as_CFB(paint->getColorFilter())->affectsTransparentBlack())) {
341 return true;
342 }
343 const auto bm = paint->asBlendMode();
344 if (!bm) {
345 return true; // can we query other blenders for this?
346 }
347
348 // Unusual blendmodes require us to process a saved layer
349 // even with operations outisde the clip.
350 // For example, DstIn is used by masking layers.
351 // https://code.google.com/p/skia/issues/detail?id=1291
352 // https://crbug.com/401593
353 switch (bm.value()) {
354 // For each of the following transfer modes, if the source
355 // alpha is zero (our transparent black), the resulting
356 // blended alpha is not necessarily equal to the original
357 // destination alpha.
365 return true;
366 default:
367 break;
368 }
369 }
370 return false;
371 }
372
373 Bounds popSaveBlock() {
374 // We're done the Save block. Apply the block's bounds to all control ops inside it.
375 SaveBounds sb = fSaveStack.back();
376 fSaveStack.pop_back();
377
378 while (sb.controlOps --> 0) {
379 this->popControl(sb.bounds);
380 }
381
382 // This whole Save block may be part another Save block.
383 this->updateSaveBounds(sb.bounds);
384
385 // If called from a real Restore (not a phony one for balance), it'll need the bounds.
386 return sb.bounds;
387 }
388
389 void pushControl() {
390 fControlIndices.push_back(fCurrentOp);
391 if (!fSaveStack.empty()) {
392 fSaveStack.back().controlOps++;
393 }
394 }
395
396 void popControl(const Bounds& bounds) {
397 fBounds[fControlIndices.back()] = bounds;
398 fMeta [fControlIndices.back()].isDraw = false;
399 fControlIndices.pop_back();
400 }
401
402 void updateSaveBounds(const Bounds& bounds) {
403 // If we're in a Save block, expand its bounds to cover these bounds too.
404 if (!fSaveStack.empty()) {
405 fSaveStack.back().bounds.join(bounds);
406 }
407 }
408
409 Bounds bounds(const DrawPaint&) const { return fCullRect; }
410 Bounds bounds(const DrawBehind&) const { return fCullRect; }
411 Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw.
412
413 Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
414 Bounds bounds(const DrawRegion& op) const {
415 SkRect rect = SkRect::Make(op.region.getBounds());
416 return this->adjustAndMap(rect, &op.paint);
417 }
418 Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); }
419 // Tighter arc bounds?
420 Bounds bounds(const DrawArc& op) const { return this->adjustAndMap(op.oval, &op.paint); }
421 Bounds bounds(const DrawRRect& op) const {
422 return this->adjustAndMap(op.rrect.rect(), &op.paint);
423 }
424 Bounds bounds(const DrawDRRect& op) const {
425 return this->adjustAndMap(op.outer.rect(), &op.paint);
426 }
427 Bounds bounds(const DrawImage& op) const {
428 const SkImage* image = op.image.get();
429 SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height());
430
431 return this->adjustAndMap(rect, op.paint);
432 }
433 Bounds bounds(const DrawImageLattice& op) const {
434 return this->adjustAndMap(op.dst, op.paint);
435 }
436 Bounds bounds(const DrawImageRect& op) const {
437 return this->adjustAndMap(op.dst, op.paint);
438 }
439 Bounds bounds(const DrawPath& op) const {
440 return op.path.isInverseFillType() ? fCullRect
441 : this->adjustAndMap(op.path.getBounds(), &op.paint);
442 }
443 Bounds bounds(const DrawPoints& op) const {
444 SkRect dst;
445 dst.setBounds(op.pts, op.count);
446
447 // Pad the bounding box a little to make sure hairline points' bounds aren't empty.
448 SkScalar stroke = std::max(op.paint.getStrokeWidth(), 0.01f);
449 dst.outset(stroke/2, stroke/2);
450
451 return this->adjustAndMap(dst, &op.paint);
452 }
453 Bounds bounds(const DrawPatch& op) const {
454 SkRect dst;
456 return this->adjustAndMap(dst, &op.paint);
457 }
458 Bounds bounds(const DrawVertices& op) const {
459 return this->adjustAndMap(op.vertices->bounds(), &op.paint);
460 }
461 Bounds bounds(const DrawMesh& op) const {
462 return this->adjustAndMap(op.mesh.bounds(), &op.paint);
463 }
464 Bounds bounds(const DrawAtlas& op) const {
465 if (op.cull) {
466 // TODO: <reed> can we pass nullptr for the paint? Isn't cull already "correct"
467 // for the paint (by the caller)?
468 return this->adjustAndMap(*op.cull, op.paint);
469 } else {
470 return fCullRect;
471 }
472 }
473
474 Bounds bounds(const DrawShadowRec& op) const {
476 SkDrawShadowMetrics::GetLocalBounds(op.path, op.rec, fCTM, &bounds);
477 return this->adjustAndMap(bounds, nullptr);
478 }
479
480 Bounds bounds(const DrawPicture& op) const {
481 SkRect dst = op.picture->cullRect();
482 op.matrix.mapRect(&dst);
483 return this->adjustAndMap(dst, op.paint);
484 }
485
486 Bounds bounds(const DrawTextBlob& op) const {
487 SkRect dst = op.blob->bounds();
488 dst.offset(op.x, op.y);
489 return this->adjustAndMap(dst, &op.paint);
490 }
491
492 Bounds bounds(const DrawSlug& op) const {
493 SkRect dst = op.slug->sourceBoundsWithOrigin();
494 return this->adjustAndMap(dst, &op.paint);
495 }
496
497 Bounds bounds(const DrawDrawable& op) const {
498 return this->adjustAndMap(op.worstCaseBounds, nullptr);
499 }
500
501 Bounds bounds(const DrawAnnotation& op) const {
502 return this->adjustAndMap(op.rect, nullptr);
503 }
504 Bounds bounds(const DrawEdgeAAQuad& op) const {
505 SkRect bounds = op.rect;
506 if (op.clip) {
507 bounds.setBounds(op.clip, 4);
508 }
509 return this->adjustAndMap(bounds, nullptr);
510 }
511 Bounds bounds(const DrawEdgeAAImageSet& op) const {
513 int clipIndex = 0;
514 for (int i = 0; i < op.count; ++i) {
515 SkRect entryBounds = op.set[i].fDstRect;
516 if (op.set[i].fHasClip) {
517 entryBounds.setBounds(op.dstClips + clipIndex, 4);
518 clipIndex += 4;
519 }
520 if (op.set[i].fMatrixIndex >= 0) {
521 op.preViewMatrices[op.set[i].fMatrixIndex].mapRect(&entryBounds);
522 }
523 rect.join(this->adjustAndMap(entryBounds, nullptr));
524 }
525 return rect;
526 }
527
528 // Returns true if rect was meaningfully adjusted for the effects of paint,
529 // false if the paint could affect the rect in unknown ways.
530 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
531 if (paint) {
532 if (paint->canComputeFastBounds()) {
533 *rect = paint->computeFastBounds(*rect, rect);
534 return true;
535 }
536 return false;
537 }
538 return true;
539 }
540
541 bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const {
542 for (int i = fSaveStack.size() - 1 - savesToIgnore; i >= 0; i--) {
543 SkMatrix inverse;
544 if (!fSaveStack[i].ctm.invert(&inverse)) {
545 return false;
546 }
547 inverse.mapRect(rect);
548 if (!AdjustForPaint(fSaveStack[i].paint, rect)) {
549 return false;
550 }
551 fSaveStack[i].ctm.mapRect(rect);
552 }
553 return true;
554 }
555
556 // We do not guarantee anything for operations outside of the cull rect
557 const SkRect fCullRect;
558
559 // Conservative identity-space bounds for each op in the SkRecord.
560 Bounds* fBounds;
561
562 // Parallel array to fBounds, holding metadata for each bounds rect.
564
565 // We walk fCurrentOp through the SkRecord,
566 // as we go using updateCTM() to maintain the exact CTM (fCTM).
567 int fCurrentOp;
568 SkMatrix fCTM;
569
570 // Used to track the bounds of Save/Restore blocks and the control ops inside them.
571 SkTDArray<SaveBounds> fSaveStack;
572 SkTDArray<int> fControlIndices;
573};
574
575} // namespace SkRecords
576
577void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record,
578 SkRect bounds[], SkBBoxHierarchy::Metadata meta[]) {
579 {
580 SkRecords::FillBounds visitor(cullRect, record, bounds, meta);
581 for (int i = 0; i < record.count(); i++) {
582 visitor.setCurrentOp(i);
583 record.visit(i, visitor);
584 }
585 }
586}
SkColor4f color
SkPathOp ops[]
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kSrcOut
r = s * (1-da)
@ kDstIn
r = d * sa
@ kModulate
r = s*d
@ kDstATop
r = d*sa + s*(1-da)
@ kSrcIn
r = s * da
@ kClear
r = 0
static SkColorFilterBase * as_CFB(SkColorFilter *filter)
static SkImageFilter_Base * as_IFB(SkImageFilter *filter)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
static bool left(const SkPoint &p0, const SkPoint &p1)
void SkRecordFillBounds(const SkRect &cullRect, const SkRecord &record, SkRect bounds[], SkBBoxHierarchy::Metadata meta[])
void SkRecordDraw(const SkRecord &record, SkCanvas *canvas, SkPicture const *const drawablePicts[], SkDrawable *const drawables[], int drawableCount, const SkBBoxHierarchy *bbh, SkPicture::AbortCallback *callback)
#define DRAW(T, call)
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
Type::kYUV Type::kRGBA() int(0.7 *637)
virtual void search(const SkRect &query, std::vector< int > *results) const =0
static void ResetClip(SkCanvas *canvas)
static void DrawBehind(SkCanvas *canvas, const SkPaint &paint)
static int SaveBehind(SkCanvas *canvas, const SkRect *subset)
SkRect getLocalClipBounds() const
void drawDrawable(SkDrawable *drawable, const SkMatrix *matrix=nullptr)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
bool affectsTransparentBlack() const
bool affectsTransparentBlack() const
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
static const SkMatrix & I()
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:263
SkMatrix & preConcat(const SkMatrix &other)
Definition SkMatrix.cpp:674
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition SkMatrix.cpp:315
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
auto visit(int i, F &&f) const -> decltype(f(SkRecords::NoOp()))
Definition SkRecord.h:45
int count() const
Definition SkRecord.h:38
FillBounds(const SkRect &cullRect, const SkRecord &record, SkRect bounds[], SkBBoxHierarchy::Metadata meta[])
void setCurrentOp(int currentOp)
void operator()(const T &op)
Bounds adjustAndMap(SkRect rect, const SkPaint *paint) const
const T & back() const
Definition SkTDArray.h:162
int size() const
Definition SkTDArray.h:138
bool empty() const
Definition SkTDArray.h:135
void push_back(const T &v)
Definition SkTDArray.h:219
void pop_back()
Definition SkTDArray.h:223
T * get() const
Definition SkRefCnt.h:303
const Paint & paint
float SkScalar
Definition extension.cpp:12
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static void drawPath(SkPath &path, SkCanvas *canvas, SkColor color, const SkRect &clip, SkPaint::Cap cap, SkPaint::Join join, SkPaint::Style style, SkPathFillType fill, SkScalar strokeWidth)
Definition linepaths.cpp:22
double y
double x
void GetLocalBounds(const SkPath &path, const SkDrawShadowRec &rec, const SkMatrix &ctm, SkRect *bounds)
skia_private::AutoTArray< SkCanvas::ImageSetEntry > set
Definition SkRecords.h:362
experimental_DrawEdgeAAImageSet(r.set.get(), r.count, r.dstClips, r.preViewMatrices, r.sampling, r.paint, r.constraint)) template<> void Draw
SkBlendMode mode
Definition SkRecords.h:336
clipRRect(r.rrect, r.opAA.op(), r.opAA.aa())) DRAW(ClipRect
SkCanvas::SaveLayerFlags saveLayerFlags
Definition SkRecords.h:192
drawTextBlob(r.blob.get(), r.x, r.y, r.paint)) DRAW(DrawSlug
sk_sp< const SkImage > atlas
Definition SkRecords.h:331
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
drawSlug(r.slug.get(), r.paint)) DRAW(DrawAtlas
Optional< SkRect > bounds
Definition SkRecords.h:189
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
PODArray< SkRect > texs
Definition SkRecords.h:333
PODArray< SkPoint > dstClips
Definition SkRecords.h:364
drawAnnotation(r.rect, r.key.c_str(), r.value.get())) DRAW(DrawEdgeAAQuad
SkScalar backdropScale
Definition SkRecords.h:193
sk_sp< const SkImage > image
Definition SkRecords.h:269
ClipOpAndAA opAA SkRegion region
Definition SkRecords.h:238
sk_sp< const SkPicture > picture
Definition SkRecords.h:299
clipPath(r.path, r.opAA.op(), r.opAA.aa())) DRAW(ClipRRect
sk_sp< const SkImageFilter > backdrop
Definition SkRecords.h:191
SkRRect rrect
Definition SkRecords.h:232
SkString key
Definition SkRecords.h:352
experimental_DrawEdgeAAQuad(r.rect, r.clip, r.aa, r.color, r.mode)) DRAW(DrawEdgeAAImageSet
drawPicture(r.picture.get(), &r.matrix, r.paint)) DRAW(DrawTextBlob
SkRect dst
Definition SkRecords.h:278
SkRect oval
Definition SkRecords.h:249
PODArray< SkRSXform > xforms
Definition SkRecords.h:332
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
PODArray< SkMatrix > preViewMatrices
Definition SkRecords.h:365
drawAtlas(r.atlas.get(), r.xforms, r.texs, r.colors, r.count, r.mode, r.sampling, r.cull, r.paint)) DRAW(DrawAnnotation
SkMesh mesh
Definition SkRecords.h:345
PODArray< SkColor > colors
Definition SkRecords.h:276
SkSamplingOptions sampling
Definition SkRecords.h:337
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition SkRecords.h:208
Optional< SkPaint > paint
Definition SkRecords.h:190
#define T
const Scalar scale
int fYCount
number of y-coordinates
Definition SkCanvas.h:1617
const SkIRect * fBounds
source bounds to draw from
Definition SkCanvas.h:1618
const int * fYDivs
y-axis values dividing bitmap
Definition SkCanvas.h:1614
int fXCount
number of x-coordinates
Definition SkCanvas.h:1616
const RectType * fRectTypes
array of fill types
Definition SkCanvas.h:1615
const SkColor * fColors
array of colors
Definition SkCanvas.h:1619
const int * fXDivs
x-axis values dividing bitmap
Definition SkCanvas.h:1613
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
void outset(float dx, float dy)
Definition SkRect.h:1077
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
void offset(float dx, float dy)
Definition SkRect.h:1016
void setBounds(const SkPoint pts[], int count)
Definition SkRect.h:881
void set(const SkIRect &src)
Definition SkRect.h:849