Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MSKPPlayer.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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 "tools/MSKPPlayer.h"
9
19#include "src/base/SkTLazy.h"
22#include "tools/SkSharingProc.h"
23
24using namespace skia_private;
25
26///////////////////////////////////////////////////////////////////////////////
27
28// Base Cmd struct.
30 virtual ~Cmd() = default;
31 virtual bool isFullRedraw(SkCanvas*) const = 0;
32 virtual void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const = 0;
33 // If this command draws another layer, return it's ID. Otherwise, -1.
34 virtual int layerID() const { return -1; }
35};
36
37// Draws a SkPicture.
40 SkIRect fClipRect = SkIRect::MakeEmpty(); // clip for picture (no clip if empty).
41
42 bool isFullRedraw(SkCanvas* canvas) const override {
43 if (fClipRect.isEmpty()) {
44 return false;
45 }
47 }
48
49 void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override {
50 if (!fClipRect.isEmpty()) {
51 canvas->save();
52 canvas->clipIRect(fClipRect);
53 }
54 canvas->drawPicture(fContent.get());
55 if (!fClipRect.isEmpty()) {
56 canvas->restore();
57 }
58 }
59};
60
61// Draws another layer. Stores the ID of the layer to draw and what command index on that
62// layer should be current when the layer is drawn. The layer contents are updated to the
63// stored command index before the layer is drawn.
72
73 bool isFullRedraw(SkCanvas* canvas) const override { return false; }
74 void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override;
75 int layerID() const override { return fLayerId; }
76};
77
79 const LayerMap& layerMap,
80 LayerStateMap* layerStateMap) const {
81 const LayerCmds& layer = layerMap.at(fLayerId);
82 LayerState* layerState = &(*layerStateMap)[fLayerId];
83 if (!layerState->fSurface) {
84 layerState->fCurrCmd = 0;
85 layerState->fSurface = MSKPPlayer::MakeSurfaceForLayer(layer, canvas);
86 if (!layerState->fSurface) {
87 SkDebugf("Couldn't create surface for layer");
88 return;
89 }
90 }
91 size_t cmd = layerState->fCurrCmd;
92 if (cmd > fLayerCmdCnt) {
93 // If the layer contains contents from later commands then replay from the beginning.
94 cmd = 0;
95 }
96 SkCanvas* layerCanvas = layerState->fSurface->getCanvas();
97 // Check if there is a full redraw between cmd and fLayerCmdCnt and if so jump to it and ensure
98 // we clear the canvas if starting from a full redraw.
99 for (size_t checkCmd = fLayerCmdCnt - 1; checkCmd > cmd; --checkCmd) {
100 if (layer.fCmds[checkCmd]->isFullRedraw(layerCanvas)) {
101 cmd = checkCmd;
102 break;
103 }
104 }
105 for (; cmd < fLayerCmdCnt; ++cmd) {
106 if (cmd == 0 || layer.fCmds[cmd]->isFullRedraw(layerCanvas)) {
107 layerState->fSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
108 }
109 layer.fCmds[cmd]->draw(layerCanvas, layerMap, layerStateMap);
110 }
111 layerState->fCurrCmd = fLayerCmdCnt;
112 const SkPaint* paint = fPaint.isValid() ? fPaint.get() : nullptr;
113 canvas->drawImageRect(layerState->fSurface->makeImageSnapshot(),
114 fSrcRect,
115 fDstRect,
116 fSampling,
117 paint,
119}
120
121///////////////////////////////////////////////////////////////////////////////
122
124public:
125 CmdRecordCanvas(LayerCmds* dst, LayerMap* offscreenLayers, const SkIRect* clipRect = nullptr)
126 : fDst(dst), fOffscreenLayers(offscreenLayers) {
127 if (clipRect) {
128 fClipRect = *clipRect;
129 }
130 fRecorder.beginRecording(SkRect::Make(dst->fDimensions));
131 }
132 ~CmdRecordCanvas() override { this->recordPicCmd(); }
133
134protected:
135 void onDrawPaint(const SkPaint& paint) override {
136 fRecorder.getRecordingCanvas()->drawPaint(paint);
137 }
138
139 void onDrawBehind(const SkPaint& paint) override {
141 }
142
143 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
144 fRecorder.getRecordingCanvas()->drawRect(rect, paint);
145 }
146
147 void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
148 fRecorder.getRecordingCanvas()->drawRRect(rrect, paint);
149 }
150
151 void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
152 fRecorder.getRecordingCanvas()->drawDRRect(outer, inner, paint);
153 }
154
155 void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
156 fRecorder.getRecordingCanvas()->drawOval(rect, paint);
157 }
158
159 void onDrawArc(const SkRect& rect,
160 SkScalar startAngle,
161 SkScalar sweepAngle,
162 bool useCenter,
163 const SkPaint& paint) override {
164 fRecorder.getRecordingCanvas()->drawArc(rect, startAngle, sweepAngle, useCenter, paint);
165 }
166
167 void onDrawPath(const SkPath& path, const SkPaint& paint) override {
168 fRecorder.getRecordingCanvas()->drawPath(path, paint);
169 }
170
171 void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
172 fRecorder.getRecordingCanvas()->drawRegion(region, paint);
173 }
174
175 void onDrawTextBlob(const SkTextBlob* blob,
176 SkScalar x,
177 SkScalar y,
178 const SkPaint& paint) override {
179 fRecorder.getRecordingCanvas()->drawTextBlob(blob, x, y, paint);
180 }
181
182 void onDrawPatch(const SkPoint cubics[12],
183 const SkColor colors[4],
184 const SkPoint texCoords[4],
185 SkBlendMode mode,
186 const SkPaint& paint) override {
187 fRecorder.getRecordingCanvas()->drawPatch(cubics, colors, texCoords, mode, paint);
188 }
189
191 size_t count,
192 const SkPoint pts[],
193 const SkPaint& paint) override {
194 fRecorder.getRecordingCanvas()->drawPoints(mode, count, pts, paint);
195 }
196
198 SkScalar dx,
199 SkScalar dy,
200 const SkSamplingOptions& sampling,
201 const SkPaint* paint) override {
202 fRecorder.getRecordingCanvas()->drawImage(image, dx, dy, sampling, paint);
203 }
204
206 const SkRect& src,
207 const SkRect& dst,
208 const SkSamplingOptions& sampling,
209 const SkPaint* paint,
210 SrcRectConstraint constraint) override {
211 if (fNextDrawImageFromLayerID != -1) {
212 this->recordPicCmd();
213 auto drawLayer = std::make_unique<DrawLayerCmd>();
214 drawLayer->fLayerId = fNextDrawImageFromLayerID;
215 drawLayer->fLayerCmdCnt = fOffscreenLayers->at(fNextDrawImageFromLayerID).fCmds.size();
216 drawLayer->fSrcRect = src;
217 drawLayer->fDstRect = dst;
218 drawLayer->fSampling = sampling;
219 drawLayer->fConstraint = constraint;
220 if (paint) {
221 drawLayer->fPaint.init(*paint);
222 }
223 fDst->fCmds.push_back(std::move(drawLayer));
224 fNextDrawImageFromLayerID = -1;
225 return;
226 }
227 fRecorder.getRecordingCanvas()->drawImageRect(image, src, dst, sampling, paint, constraint);
228 }
229
231 const Lattice& lattice,
232 const SkRect& dst,
233 SkFilterMode mode,
234 const SkPaint* paint) override {
235 fRecorder.getRecordingCanvas()->drawImageLattice(image, lattice, dst, mode, paint);
236 }
237
239 const SkRSXform rsxForms[],
240 const SkRect src[],
241 const SkColor colors[],
242 int count,
243 SkBlendMode mode,
244 const SkSamplingOptions& sampling,
245 const SkRect* cull,
246 const SkPaint* paint) override {
248 rsxForms,
249 src,
250 colors,
251 count,
252 mode,
253 sampling,
254 cull,
255 paint);
256 }
257
259 int count,
260 const SkPoint dstClips[],
261 const SkMatrix preViewMatrices[],
262 const SkSamplingOptions& sampling,
263 const SkPaint* paint,
264 SrcRectConstraint constraint) override {
266 count,
267 dstClips,
268 preViewMatrices,
269 sampling,
270 paint,
271 constraint);
272 }
273
274#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
275 void onDrawEdgeAAQuad(const SkRect& rect,
276 const SkPoint clip[4],
277 SkCanvas::QuadAAFlags aaFlags,
278 const SkColor4f& color,
279 SkBlendMode mode) override {}
280#else
281 void onDrawEdgeAAQuad(const SkRect& rect,
282 const SkPoint clip[4],
283 SkCanvas::QuadAAFlags aaFlags,
284 const SkColor4f& color,
285 SkBlendMode mode) override {
287 clip,
288 aaFlags,
289 color,
290 mode);
291 }
292#endif
293
294 void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override {
295 static constexpr char kOffscreenLayerDraw[] = "OffscreenLayerDraw";
296 static constexpr char kSurfaceID[] = "SurfaceID";
297 TArray<SkString> tokens;
298 SkStrSplit(key, "|", kStrict_SkStrSplitMode, &tokens);
299 if (tokens.size() == 2) {
300 if (tokens[0].equals(kOffscreenLayerDraw)) {
301 // Indicates that the next drawPicture command contains the SkPicture to render
302 // to the layer identified by the ID. 'rect' indicates the dirty area to update
303 // (and indicates the layer size if this command is introducing a new layer id).
304 fNextDrawPictureToLayerID = std::stoi(tokens[1].c_str());
305 fNextDrawPictureToLayerClipRect = rect.roundOut();
306 if (fOffscreenLayers->find(fNextDrawPictureToLayerID) == fOffscreenLayers->end()) {
307 SkASSERT(fNextDrawPictureToLayerClipRect.left() == 0 &&
308 fNextDrawPictureToLayerClipRect.top() == 0);
309 (*fOffscreenLayers)[fNextDrawPictureToLayerID].fDimensions =
310 fNextDrawPictureToLayerClipRect.size();
311 }
312 // The next draw picture will notice that fNextDrawPictureToLayerID is set and
313 // redirect the picture to the offscreen layer.
314 return;
315 } else if (tokens[0].equals(kSurfaceID)) {
316 // Indicates that the following drawImageRect should draw an offscreen layer
317 // to this layer.
318 fNextDrawImageFromLayerID = std::stoi(tokens[1].c_str());
319 return;
320 }
321 }
322 }
323
324 void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override {
325 fRecorder.getRecordingCanvas()->private_draw_shadow_rec(path, rec);
326 }
327
328 void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
329 fRecorder.getRecordingCanvas()->drawDrawable(drawable, matrix);
330 }
331
332 void onDrawPicture(const SkPicture* picture,
333 const SkMatrix* matrix,
334 const SkPaint* paint) override {
335 if (fNextDrawPictureToLayerID != -1) {
336 SkASSERT(!matrix);
337 SkASSERT(!paint);
338 LayerCmds* layer = &fOffscreenLayers->at(fNextDrawPictureToLayerID);
339 CmdRecordCanvas sc(layer, fOffscreenLayers, &fNextDrawPictureToLayerClipRect);
340 picture->playback(&sc);
341 fNextDrawPictureToLayerID = -1;
342 fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
343 return;
344 }
345 if (paint) {
346 this->saveLayer(nullptr, paint);
347 }
348 if (matrix) {
349 this->save();
350 this->concat(*matrix);
351 }
352
353 picture->playback(this);
354
355 if (matrix) {
356 this->restore();
357 }
358 if (paint) {
359 this->restore();
360 }
361 }
362
363private:
364 void recordPicCmd() {
365 auto cmd = std::make_unique<PicCmd>();
366 cmd->fContent = fRecorder.finishRecordingAsPicture();
367 cmd->fClipRect = fClipRect;
368 if (cmd->fContent) {
369 fDst->fCmds.push_back(std::move(cmd));
370 }
371 // Set up to accumulate again.
372 fRecorder.beginRecording(SkRect::Make(fDst->fDimensions));
373 }
374
375 SkPictureRecorder fRecorder; // accumulates draws until we draw an offscreen into this layer.
376 LayerCmds* fDst = nullptr;
377 SkIRect fClipRect = SkIRect::MakeEmpty();
378 int fNextDrawPictureToLayerID = -1;
379 SkIRect fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
380 int fNextDrawImageFromLayerID = -1;
381 LayerMap* fOffscreenLayers = nullptr;
382};
383
384///////////////////////////////////////////////////////////////////////////////
385
386std::unique_ptr<MSKPPlayer> MSKPPlayer::Make(SkStreamSeekable* stream) {
387 auto deserialContext = std::make_unique<SkSharingDeserialContext>();
388 SkDeserialProcs procs;
390 procs.fImageCtx = deserialContext.get();
391
392 int pageCount = SkMultiPictureDocument::ReadPageCount(stream);
393 if (!pageCount) {
394 return nullptr;
395 }
396 std::vector<SkDocumentPage> pages(pageCount);
397 if (!SkMultiPictureDocument::Read(stream, pages.data(), pageCount, &procs)) {
398 return nullptr;
399 }
400 std::unique_ptr<MSKPPlayer> result(new MSKPPlayer);
401 result->fRootLayers.reserve(pages.size());
402 for (const auto& page : pages) {
403 SkISize dims = {SkScalarCeilToInt(page.fSize.width()),
404 SkScalarCeilToInt(page.fSize.height())};
405 result->fRootLayers.emplace_back();
406 result->fRootLayers.back().fDimensions = dims;
407 result->fMaxDimensions.fWidth = std::max(dims.width() , result->fMaxDimensions.width() );
408 result->fMaxDimensions.fHeight = std::max(dims.height(), result->fMaxDimensions.height());
409 CmdRecordCanvas sc(&result->fRootLayers.back(), &result->fOffscreenLayers);
410 page.fPicture->playback(&sc);
411 }
412 return result;
413}
414
415MSKPPlayer::~MSKPPlayer() = default;
416
418 if (i < 0 || i >= this->numFrames()) {
419 return {-1, -1};
420 }
421 return fRootLayers[i].fDimensions;
422}
423
424bool MSKPPlayer::playFrame(SkCanvas* canvas, int i) {
425 if (i < 0 || i >= this->numFrames()) {
426 return false;
427 }
428
429 // Find the first offscreen layer that has a valid surface. If it's recording context
430 // differs from the passed canvas's then reset all the layers. Playback will
431 // automatically allocate new surfaces for offscreen layers as they're encountered.
432 for (const auto& ols : fOffscreenLayerStates) {
433 const LayerState& state = ols.second;
434 if (state.fSurface) {
435 if (state.fSurface->recordingContext() != canvas->recordingContext()) {
436 this->resetLayers();
437 }
438 break;
439 }
440 }
441
442 // Replay all the commands for this frame to the caller's canvas.
443 const LayerCmds& layer = fRootLayers[i];
444 for (const auto& cmd : layer.fCmds) {
445 cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
446 }
447 return true;
448}
449
450sk_sp<SkSurface> MSKPPlayer::MakeSurfaceForLayer(const LayerCmds& layer, SkCanvas* rootCanvas) {
451 // Assume layer has same surface props and info as this (mskp doesn't currently record this
452 // data).
453 SkSurfaceProps props;
454 rootCanvas->getProps(&props);
455 return rootCanvas->makeSurface(rootCanvas->imageInfo().makeDimensions(layer.fDimensions),
456 &props);
457}
458
459void MSKPPlayer::resetLayers() { fOffscreenLayerStates.clear(); }
460
462 for (auto& [id, state] : fOffscreenLayerStates) {
463 state.fCurrCmd = -1;
464 }
465}
466
468 // Iterate over layers not states as states are lazily created in playback but here we want to
469 // create any that don't already exist.
470 for (auto& [id, layer] : fOffscreenLayers) {
471 LayerState& state = fOffscreenLayerStates[id];
472 if (!state.fSurface || state.fSurface->recordingContext() != canvas->recordingContext()) {
473 state.fCurrCmd = -1;
474 state.fSurface = MakeSurfaceForLayer(fOffscreenLayers[id], canvas);
475 }
476 }
477}
478
479std::vector<int> MSKPPlayer::layerIDs(int frame) const {
480 std::vector<int> result;
481 if (frame < 0) {
482 result.reserve(fOffscreenLayers.size());
483 for (auto& [id, _] : fOffscreenLayers) {
484 result.push_back(id);
485 }
486 return result;
487 }
488 if (frame < static_cast<int>(fRootLayers.size())) {
489 this->collectReferencedLayers(fRootLayers[frame], &result);
490 }
491 return result;
492}
493
495 auto iter = fOffscreenLayerStates.find(layerID);
496 if (iter == fOffscreenLayerStates.end() || !iter->second.fSurface) {
497 return nullptr;
498 }
499 return iter->second.fSurface->makeImageSnapshot();
500}
501
502void MSKPPlayer::collectReferencedLayers(const LayerCmds& layer, std::vector<int>* out) const {
503 for (const auto& cmd : layer.fCmds) {
504 if (int id = cmd->layerID(); id >= 0) {
505 // Linear, but we'd need to have a lot of layers to actually care.
506 if (std::find(out->begin(), out->end(), id) == out->end()) {
507 out->push_back(id);
508 auto iter = fOffscreenLayers.find(id);
509 SkASSERT(iter != fOffscreenLayers.end());
510 this->collectReferencedLayers(iter->second, out);
511 }
512 }
513 }
514}
int count
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
uint32_t SkColor
Definition SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition SkColor.h:99
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
static bool equals(T *a, T *b)
SkFilterMode
#define SkScalarCeilToInt(x)
Definition SkScalar.h:36
void SkStrSplit(const char *str, const char *delimiters, SkStrSplitMode splitMode, TArray< SkString > *out)
@ kStrict_SkStrSplitMode
void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint) override
void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint &paint) override
void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &sampling, const SkPaint *paint, SrcRectConstraint constraint) override
void onDrawBehind(const SkPaint &paint) override
void onDrawAtlas2(const SkImage *image, const SkRSXform rsxForms[], const SkRect src[], const SkColor colors[], int count, SkBlendMode mode, const SkSamplingOptions &sampling, const SkRect *cull, const SkPaint *paint) override
void onDrawOval(const SkRect &rect, const SkPaint &paint) override
void onDrawDrawable(SkDrawable *drawable, const SkMatrix *matrix) override
CmdRecordCanvas(LayerCmds *dst, LayerMap *offscreenLayers, const SkIRect *clipRect=nullptr)
void onDrawRegion(const SkRegion &region, const SkPaint &paint) override
void onDrawAnnotation(const SkRect &rect, const char key[], SkData *value) override
void onDrawShadowRec(const SkPath &path, const SkDrawShadowRec &rec) override
void onDrawPath(const SkPath &path, const SkPaint &paint) override
void onDrawImage2(const SkImage *image, SkScalar dx, SkScalar dy, const SkSamplingOptions &sampling, const SkPaint *paint) override
void onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint) override
void onDrawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode) override
void onDrawRRect(const SkRRect &rrect, const SkPaint &paint) override
void onDrawPaint(const SkPaint &paint) override
void onDrawArc(const SkRect &rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint) override
void onDrawRect(const SkRect &rect, const SkPaint &paint) override
void onDrawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint) override
void onDrawImageLattice2(const SkImage *image, const Lattice &lattice, const SkRect &dst, SkFilterMode mode, const SkPaint *paint) override
void onDrawPicture(const SkPicture *picture, const SkMatrix *matrix, const SkPaint *paint) override
void onDrawImageRect2(const SkImage *image, const SkRect &src, const SkRect &dst, const SkSamplingOptions &sampling, const SkPaint *paint, SrcRectConstraint constraint) override
int numFrames() const
Definition MSKPPlayer.h:38
void rewindLayers()
std::vector< int > layerIDs(int frame=-1) const
sk_sp< SkImage > layerSnapshot(int layerID) const
static std::unique_ptr< MSKPPlayer > Make(SkStreamSeekable *stream)
void resetLayers()
bool playFrame(SkCanvas *canvas, int i)
SkISize frameDimensions(int i) const
void allocateLayers(SkCanvas *)
static void DrawBehind(SkCanvas *canvas, const SkPaint &paint)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
bool getProps(SkSurfaceProps *props) const
void drawRect(const SkRect &rect, const SkPaint &paint)
void drawOval(const SkRect &oval, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint &paint)
void restore()
Definition SkCanvas.cpp:465
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
void clipIRect(const SkIRect &irect, SkClipOp op=SkClipOp::kIntersect)
Definition SkCanvas.h:991
virtual GrRecordingContext * recordingContext() const
void drawPaint(const SkPaint &paint)
void private_draw_shadow_rec(const SkPath &, const SkDrawShadowRec &)
void drawDrawable(SkDrawable *drawable, const SkMatrix *matrix=nullptr)
virtual SkISize getBaseLayerSize() const
Definition SkCanvas.cpp:373
SrcRectConstraint
Definition SkCanvas.h:1541
void experimental_DrawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode)
void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint *paint=nullptr, SrcRectConstraint constraint=kStrict_SrcRectConstraint)
void drawRRect(const SkRRect &rrect, const SkPaint &paint)
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
void drawImageLattice(const SkImage *image, const Lattice &lattice, const SkRect &dst, SkFilterMode filter, const SkPaint *paint=nullptr)
void drawRegion(const SkRegion &region, const SkPaint &paint)
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void drawAtlas(const SkImage *atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkBlendMode mode, const SkSamplingOptions &sampling, const SkRect *cullRect, const SkPaint *paint)
void drawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint)
void concat(const SkMatrix &matrix)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
SkImageInfo imageInfo() const
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
SkCanvas * getRecordingCanvas()
sk_sp< SkPicture > finishRecordingAsPicture()
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
T * get()
Definition SkTLazy.h:83
bool isValid() const
Definition SkTLazy.h:77
T * get() const
Definition SkRefCnt.h:303
const Paint & paint
sk_sp< SkImage > image
Definition examples.cpp:29
double frame
Definition examples.cpp:31
float SkScalar
Definition extension.cpp:12
AtkStateType state
GAsyncResult * result
double y
double x
SK_API bool Read(SkStreamSeekable *src, SkDocumentPage *dstArray, int dstArrayCount, const SkDeserialProcs *=nullptr)
SK_API int ReadPageCount(SkStreamSeekable *src)
virtual bool isFullRedraw(SkCanvas *) const =0
virtual ~Cmd()=default
virtual int layerID() const
virtual void draw(SkCanvas *canvas, const LayerMap &, LayerStateMap *) const =0
bool isFullRedraw(SkCanvas *canvas) const override
SkCanvas::SrcRectConstraint fConstraint
SkTLazy< SkPaint > fPaint
SkSamplingOptions fSampling
void draw(SkCanvas *canvas, const LayerMap &, LayerStateMap *) const override
int layerID() const override
sk_sp< SkPicture > fContent
bool isFullRedraw(SkCanvas *canvas) const override
void draw(SkCanvas *canvas, const LayerMap &, LayerStateMap *) const override
SkDeserialImageProc fImageProc
constexpr int32_t top() const
Definition SkRect.h:120
constexpr SkISize size() const
Definition SkRect.h:172
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
static constexpr SkIRect MakeEmpty()
Definition SkRect.h:45
bool isEmpty() const
Definition SkRect.h:202
constexpr int32_t left() const
Definition SkRect.h:113
bool contains(int32_t x, int32_t y) const
Definition SkRect.h:463
int32_t fWidth
Definition SkSize.h:17
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
SkImageInfo makeDimensions(SkISize newSize) const
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
static sk_sp< SkImage > deserializeImage(const void *data, size_t length, void *ctx)
const uintptr_t id