| Flutter Impeller |

canvas_recorder.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_
6 #define FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_
7
8 #include <cstdint>
9
10 #include "impeller/aiks/canvas.h"
11
12 #define FLT_CANVAS_RECORDER_OP_ARG(name) \
13 CanvasRecorderOp::k##name, &Canvas::name
14
15 namespace impeller {
16 /// TODO(tbd): These are very similar to `flutter::DisplayListOpType`. When
17 /// golden tests can be written at a higher level, migrate these to
18 /// flutter::DisplayListOpType.
19 enum CanvasRecorderOp : uint16_t {
20 kNew,
21 kSave,
22 kSaveLayer,
23 kRestore,
24 kRestoreToCount,
25 kResetTransform,
26 kTransform,
27 kConcat,
28 kPreConcat,
29 kTranslate,
30 kScale2,
31 kScale3,
32 kSkew,
33 kRotate,
34 kDrawPath,
35 kDrawPaint,
36 kDrawLine,
37 kDrawRect,
38 kDrawOval,
39 kDrawRRect,
40 kDrawCircle,
41 kDrawPoints,
42 kDrawImage,
43 kDrawImageRect,
44 kClipPath,
45 kClipRect,
46 kClipOval,
47 kClipRRect,
48 kDrawTextFrame,
49 kDrawVertices,
50 kDrawAtlas,
51 };
52
53 // Canvas recorder should only be used when IMPELLER_TRACE_CANVAS is defined
54 // (never in production code).
55 #ifdef IMPELLER_TRACE_CANVAS
56 /// Static polymorphic replacement for impeller::Canvas that records methods
57 /// called on an impeller::Canvas and forwards it to a real instance.
58 /// TODO(https://github.com/flutter/flutter/issues/135718): Move this recorder
59 /// to the DisplayList level when golden tests can be written at the ui.Canvas
60 /// layer.
61 template <typename Serializer>
62 class CanvasRecorder {
63 public:
64 CanvasRecorder() : canvas_() { serializer_.Write(CanvasRecorderOp::kNew); }
65
66 explicit CanvasRecorder(Rect cull_rect) : canvas_(cull_rect) {
67 serializer_.Write(CanvasRecorderOp::kNew);
68 }
69
70 explicit CanvasRecorder(IRect cull_rect) : canvas_(cull_rect) {
71 serializer_.Write(CanvasRecorderOp::kNew);
72 }
73
74 ~CanvasRecorder() {}
75
76 const Serializer& GetSerializer() const { return serializer_; }
77
78 template <typename ReturnType>
79 ReturnType ExecuteAndSerialize(CanvasRecorderOp op,
80 ReturnType (Canvas::*canvasMethod)()) {
81 serializer_.Write(op);
82 return (canvas_.*canvasMethod)();
83 }
84
85 template <typename FuncType, typename... Args>
86 auto ExecuteAndSerialize(CanvasRecorderOp op,
87 FuncType canvasMethod,
88 Args&&... args)
89 -> decltype((std::declval<Canvas>().*
90 canvasMethod)(std::forward<Args>(args)...)) {
91 // Serialize each argument
92 (serializer_.Write(std::forward<Args>(args)), ...);
93 serializer_.Write(op);
94 return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
95 }
96
97 template <typename FuncType, typename... Args>
98 auto ExecuteAndSkipArgSerialize(CanvasRecorderOp op,
99 FuncType canvasMethod,
100 Args&&... args)
101 -> decltype((std::declval<Canvas>().*
102 canvasMethod)(std::forward<Args>(args)...)) {
103 serializer_.Write(op);
104 return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
105 }
106
107 //////////////////////////////////////////////////////////////////////////////
108 // Canvas Static Polymorphism
109 // ////////////////////////////////////////////////
110 //////////////////////////////////////////////////////////////////////////////
111
112 void Save() {
113 return ExecuteAndSerialize(CanvasRecorderOp::kSave, &Canvas::Save);
114 }
115
116 void SaveLayer(
117 const Paint& paint,
118 std::optional<Rect> bounds = std::nullopt,
119 const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr,
120 ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown) {
121 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(SaveLayer), paint,
122 bounds, backdrop_filter, bounds_promise);
123 }
124
125 bool Restore() {
126 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Restore));
127 }
128
129 size_t GetSaveCount() const { return canvas_.GetSaveCount(); }
130
131 void RestoreToCount(size_t count) {
132 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(RestoreToCount),
133 count);
134 }
135
136 const Matrix& GetCurrentTransform() const {
137 return canvas_.GetCurrentTransform();
138 }
139
140 const std::optional<Rect> GetCurrentLocalCullingBounds() const {
141 return canvas_.GetCurrentLocalCullingBounds();
142 }
143
144 void ResetTransform() {
145 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ResetTransform));
146 }
147
148 void Transform(const Matrix& transform) {
149 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Transform),
150 transform);
151 }
152
153 void Concat(const Matrix& transform) {
154 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Concat), transform);
155 }
156
157 void PreConcat(const Matrix& transform) {
158 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(PreConcat),
159 transform);
160 }
161
162 void Translate(const Vector3& offset) {
163 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Translate), offset);
164 }
165
166 void Scale(const Vector2& scale) {
167 return ExecuteAndSerialize(
168 CanvasRecorderOp::kScale2,
169 static_cast<void (Canvas::*)(const Vector2&)>(&Canvas::Scale), scale);
170 }
171
172 void Scale(const Vector3& scale) {
173 return ExecuteAndSerialize(
174 CanvasRecorderOp::kScale3,
175 static_cast<void (Canvas::*)(const Vector3&)>(&Canvas::Scale), scale);
176 }
177
178 void Skew(Scalar sx, Scalar sy) {
179 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Skew), sx, sy);
180 }
181
182 void Rotate(Radians radians) {
183 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Rotate), radians);
184 }
185
186 void DrawPath(Path path, const Paint& paint) {
187 serializer_.Write(path);
188 serializer_.Write(paint);
189 return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPath),
190 std::move(path), paint);
191 }
192
193 void DrawPaint(const Paint& paint) {
194 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPaint), paint);
195 }
196
197 void DrawLine(const Point& p0, const Point& p1, const Paint& paint) {
198 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawLine), p0, p1,
199 paint);
200 }
201
202 void DrawRect(Rect rect, const Paint& paint) {
203 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRect), rect,
204 paint);
205 }
206
207 void DrawOval(const Rect& rect, const Paint& paint) {
208 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawOval), rect,
209 paint);
210 }
211
212 void DrawRRect(const Rect& rect,
213 const Size& corner_radii,
214 const Paint& paint) {
215 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRRect), rect,
216 corner_radii, paint);
217 }
218
219 void DrawCircle(Point center, Scalar radius, const Paint& paint) {
220 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawCircle), center,
221 radius, paint);
222 }
223
224 void DrawPoints(std::vector<Point> points,
225 Scalar radius,
226 const Paint& paint,
227 PointStyle point_style) {
228 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPoints), points,
229 radius, paint, point_style);
230 }
231
232 void DrawImage(const std::shared_ptr<Image>& image,
233 Point offset,
234 const Paint& paint,
235 SamplerDescriptor sampler = {}) {
236 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImage), image,
237 offset, paint, sampler);
238 }
239
240 void DrawImageRect(
241 const std::shared_ptr<Image>& image,
242 Rect source,
243 Rect dest,
244 const Paint& paint,
245 SamplerDescriptor sampler = {},
246 SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast) {
247 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImageRect), image,
248 source, dest, paint, sampler,
249 src_rect_constraint);
250 }
251
252 void ClipPath(
253 Path path,
254 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
255 serializer_.Write(path);
256 serializer_.Write(clip_op);
257 return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipPath),
258 std::move(path), clip_op);
259 }
260
261 void ClipRect(
262 const Rect& rect,
263 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
264 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRect), rect,
265 clip_op);
266 }
267
268 void ClipOval(
269 const Rect& bounds,
270 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
271 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipOval), bounds,
272 clip_op);
273 }
274
275 void ClipRRect(
276 const Rect& rect,
277 const Size& corner_radii,
278 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
279 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRRect), rect,
280 corner_radii, clip_op);
281 }
282
283 void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
284 Point position,
285 const Paint& paint) {
286 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawTextFrame),
287 text_frame, position, paint);
288 }
289
290 void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
291 BlendMode blend_mode,
292 const Paint& paint) {
293 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawVertices),
294 vertices, blend_mode, paint);
295 }
296
297 void DrawAtlas(const std::shared_ptr<Image>& atlas,
298 std::vector<Matrix> transforms,
299 std::vector<Rect> texture_coordinates,
300 std::vector<Color> colors,
301 BlendMode blend_mode,
302 SamplerDescriptor sampler,
303 std::optional<Rect> cull_rect,
304 const Paint& paint) {
305 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawAtlas), //
306 atlas, //
307 transforms, //
308 texture_coordinates, //
309 colors, //
310 blend_mode, //
311 sampler, //
312 cull_rect, //
313 paint);
314 }
315
316 Picture EndRecordingAsPicture() { return canvas_.EndRecordingAsPicture(); }
317
318 private:
319 Canvas canvas_;
320 Serializer serializer_;
321 };
322 #endif
323
324 } // namespace impeller
325
326 #endif // FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::kResetTransform
@ kResetTransform
Definition: canvas_recorder.h:25
impeller::kPreConcat
@ kPreConcat
Definition: canvas_recorder.h:28
impeller::kDrawImage
@ kDrawImage
Definition: canvas_recorder.h:42
impeller::kClipPath
@ kClipPath
Definition: canvas_recorder.h:44
impeller::kClipOval
@ kClipOval
Definition: canvas_recorder.h:46
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::SourceRectConstraint::kFast
@ kFast
Faster, but may sample outside the bounds of the source rectangle.
impeller::kConcat
@ kConcat
Definition: canvas_recorder.h:27
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::PointStyle
PointStyle
Definition: canvas.h:41
impeller::kRotate
@ kRotate
Definition: canvas_recorder.h:33
impeller::Vector2
Point Vector2
Definition: point.h:320
impeller::ContentBoundsPromise
ContentBoundsPromise
Definition: entity_pass.h:28
impeller::ContentBoundsPromise::kUnknown
@ kUnknown
The caller makes no claims related to the size of the bounds.
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::kSave
@ kSave
Definition: canvas_recorder.h:21
impeller::kDrawCircle
@ kDrawCircle
Definition: canvas_recorder.h:40
impeller::kDrawTextFrame
@ kDrawTextFrame
Definition: canvas_recorder.h:48
impeller::kScale2
@ kScale2
Definition: canvas_recorder.h:30
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:264
impeller::Canvas::Save
void Save()
Definition: canvas.cc:136
impeller::kDrawRect
@ kDrawRect
Definition: canvas_recorder.h:37
impeller::kSkew
@ kSkew
Definition: canvas_recorder.h:32
impeller::kClipRRect
@ kClipRRect
Definition: canvas_recorder.h:47
impeller::SourceRectConstraint
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
Definition: canvas.h:50
impeller::kDrawImageRect
@ kDrawImageRect
Definition: canvas_recorder.h:43
canvas.h
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
impeller::kTransform
@ kTransform
Definition: canvas_recorder.h:26
impeller::kDrawAtlas
@ kDrawAtlas
Definition: canvas_recorder.h:50
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:662
impeller::kDrawPaint
@ kDrawPaint
Definition: canvas_recorder.h:35
impeller::kNew
@ kNew
Definition: canvas_recorder.h:20
impeller::kSaveLayer
@ kSaveLayer
Definition: canvas_recorder.h:22
impeller::kDrawPoints
@ kDrawPoints
Definition: canvas_recorder.h:41
scale
const Scalar scale
Definition: stroke_path_geometry.cc:297
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:61
impeller::kDrawOval
@ kDrawOval
Definition: canvas_recorder.h:38
impeller::kScale3
@ kScale3
Definition: canvas_recorder.h:31
offset
Point offset
Definition: stroke_path_geometry.cc:300
impeller::kDrawVertices
@ kDrawVertices
Definition: canvas_recorder.h:49
impeller::kDrawLine
@ kDrawLine
Definition: canvas_recorder.h:36
impeller::kDrawPath
@ kDrawPath
Definition: canvas_recorder.h:34
impeller::kDrawRRect
@ kDrawRRect
Definition: canvas_recorder.h:39
impeller
Definition: aiks_blur_unittests.cc:20
impeller::kRestore
@ kRestore
Definition: canvas_recorder.h:23
impeller::kTranslate
@ kTranslate
Definition: canvas_recorder.h:29
impeller::CanvasRecorderOp
CanvasRecorderOp
Definition: canvas_recorder.h:19
impeller::kClipRect
@ kClipRect
Definition: canvas_recorder.h:45
FLT_CANVAS_RECORDER_OP_ARG
#define FLT_CANVAS_RECORDER_OP_ARG(name)
Definition: canvas_recorder.h:12
impeller::kRestoreToCount
@ kRestoreToCount
Definition: canvas_recorder.h:24