| 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 kDrawRect,
37 kDrawRRect,
38 kDrawCircle,
39 kDrawPoints,
40 kDrawImage,
41 kDrawImageRect,
42 kClipPath,
43 kClipRect,
44 kClipRRect,
45 kDrawPicture,
46 kDrawTextFrame,
47 kDrawVertices,
48 kDrawAtlas,
49 };
50
51 // Canvas recorder should only be used when IMPELLER_TRACE_CANVAS is defined
52 // (never in production code).
53 #ifdef IMPELLER_TRACE_CANVAS
54 /// Static polymorphic replacement for impeller::Canvas that records methods
55 /// called on an impeller::Canvas and forwards it to a real instance.
56 /// TODO(https://github.com/flutter/flutter/issues/135718): Move this recorder
57 /// to the DisplayList level when golden tests can be written at the ui.Canvas
58 /// layer.
59 template <typename Serializer>
60 class CanvasRecorder {
61 public:
62 CanvasRecorder() : canvas_() { serializer_.Write(CanvasRecorderOp::kNew); }
63
64 explicit CanvasRecorder(Rect cull_rect) : canvas_(cull_rect) {
65 serializer_.Write(CanvasRecorderOp::kNew);
66 }
67
68 explicit CanvasRecorder(IRect cull_rect) : canvas_(cull_rect) {
69 serializer_.Write(CanvasRecorderOp::kNew);
70 }
71
72 ~CanvasRecorder() {}
73
74 const Serializer& GetSerializer() const { return serializer_; }
75
76 template <typename ReturnType>
77 ReturnType ExecuteAndSerialize(CanvasRecorderOp op,
78 ReturnType (Canvas::*canvasMethod)()) {
79 serializer_.Write(op);
80 return (canvas_.*canvasMethod)();
81 }
82
83 template <typename FuncType, typename... Args>
84 auto ExecuteAndSerialize(CanvasRecorderOp op,
85 FuncType canvasMethod,
86 Args&&... args)
87 -> decltype((std::declval<Canvas>().*
88 canvasMethod)(std::forward<Args>(args)...)) {
89 // Serialize each argument
90 (serializer_.Write(std::forward<Args>(args)), ...);
91 serializer_.Write(op);
92 return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
93 }
94
95 template <typename FuncType, typename... Args>
96 auto ExecuteAndSkipArgSerialize(CanvasRecorderOp op,
97 FuncType canvasMethod,
98 Args&&... args)
99 -> decltype((std::declval<Canvas>().*
100 canvasMethod)(std::forward<Args>(args)...)) {
101 serializer_.Write(op);
102 return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
103 }
104
105 //////////////////////////////////////////////////////////////////////////////
106 // Canvas Static Polymorphism
107 // ////////////////////////////////////////////////
108 //////////////////////////////////////////////////////////////////////////////
109
110 void Save() {
111 return ExecuteAndSerialize(CanvasRecorderOp::kSave, &Canvas::Save);
112 }
113
114 void SaveLayer(
115 const Paint& paint,
116 std::optional<Rect> bounds = std::nullopt,
117 const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr) {
118 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(SaveLayer), paint,
119 bounds, backdrop_filter);
120 }
121
122 bool Restore() {
123 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Restore));
124 }
125
126 size_t GetSaveCount() const { return canvas_.GetSaveCount(); }
127
128 void RestoreToCount(size_t count) {
129 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(RestoreToCount),
130 count);
131 }
132
133 const Matrix& GetCurrentTransform() const {
134 return canvas_.GetCurrentTransform();
135 }
136
137 const std::optional<Rect> GetCurrentLocalCullingBounds() const {
138 return canvas_.GetCurrentLocalCullingBounds();
139 }
140
141 void ResetTransform() {
142 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ResetTransform));
143 }
144
145 void Transform(const Matrix& transform) {
146 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Transform),
147 transform);
148 }
149
150 void Concat(const Matrix& transform) {
151 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Concat), transform);
152 }
153
154 void PreConcat(const Matrix& transform) {
155 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(PreConcat),
156 transform);
157 }
158
159 void Translate(const Vector3& offset) {
160 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Translate), offset);
161 }
162
163 void Scale(const Vector2& scale) {
164 return ExecuteAndSerialize(
165 CanvasRecorderOp::kScale2,
166 static_cast<void (Canvas::*)(const Vector2&)>(&Canvas::Scale), scale);
167 }
168
169 void Scale(const Vector3& scale) {
170 return ExecuteAndSerialize(
171 CanvasRecorderOp::kScale3,
172 static_cast<void (Canvas::*)(const Vector3&)>(&Canvas::Scale), scale);
173 }
174
175 void Skew(Scalar sx, Scalar sy) {
176 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Skew), sx, sy);
177 }
178
179 void Rotate(Radians radians) {
180 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Rotate), radians);
181 }
182
183 void DrawPath(Path path, const Paint& paint) {
184 serializer_.Write(path);
185 serializer_.Write(paint);
186 return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPath),
187 std::move(path), paint);
188 }
189
190 void DrawPaint(const Paint& paint) {
191 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPaint), paint);
192 }
193
194 void DrawRect(Rect rect, const Paint& paint) {
195 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRect), rect,
196 paint);
197 }
198
199 void DrawRRect(const Rect& rect,
200 const Size& corner_radii,
201 const Paint& paint) {
202 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRRect), rect,
203 corner_radii, paint);
204 }
205
206 void DrawCircle(Point center, Scalar radius, const Paint& paint) {
207 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawCircle), center,
208 radius, paint);
209 }
210
211 void DrawPoints(std::vector<Point> points,
212 Scalar radius,
213 const Paint& paint,
214 PointStyle point_style) {
215 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPoints), points,
216 radius, paint, point_style);
217 }
218
219 void DrawImage(const std::shared_ptr<Image>& image,
220 Point offset,
221 const Paint& paint,
222 SamplerDescriptor sampler = {}) {
223 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImage), image,
224 offset, paint, sampler);
225 }
226
227 void DrawImageRect(const std::shared_ptr<Image>& image,
228 Rect source,
229 Rect dest,
230 const Paint& paint,
231 SamplerDescriptor sampler = {}) {
232 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImageRect), image,
233 source, dest, paint, sampler);
234 }
235
236 void ClipPath(
237 Path path,
238 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
239 serializer_.Write(path);
240 serializer_.Write(clip_op);
241 return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipPath),
242 std::move(path), clip_op);
243 }
244
245 void ClipRect(
246 const Rect& rect,
247 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
248 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRect), rect,
249 clip_op);
250 }
251
252 void ClipRRect(
253 const Rect& rect,
254 const Size& corner_radii,
255 Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
256 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRRect), rect,
257 corner_radii, clip_op);
258 }
259
260 void DrawPicture(const Picture& picture) {
261 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPicture),
262 picture);
263 }
264
265 void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
266 Point position,
267 const Paint& paint) {
268 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawTextFrame),
269 text_frame, position, paint);
270 }
271
272 void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
273 BlendMode blend_mode,
274 const Paint& paint) {
275 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawVertices),
276 vertices, blend_mode, paint);
277 }
278
279 void DrawAtlas(const std::shared_ptr<Image>& atlas,
280 std::vector<Matrix> transforms,
281 std::vector<Rect> texture_coordinates,
282 std::vector<Color> colors,
283 BlendMode blend_mode,
284 SamplerDescriptor sampler,
285 std::optional<Rect> cull_rect,
286 const Paint& paint) {
287 return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawAtlas), //
288 atlas, //
289 transforms, //
290 texture_coordinates, //
291 colors, //
292 blend_mode, //
293 sampler, //
294 cull_rect, //
295 paint);
296 }
297
298 Picture EndRecordingAsPicture() { return canvas_.EndRecordingAsPicture(); }
299
300 private:
301 Canvas canvas_;
302 Serializer serializer_;
303 };
304 #endif
305
306 } // namespace impeller
307
308 #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:40
impeller::kClipPath
@ kClipPath
Definition: canvas_recorder.h:42
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::kConcat
@ kConcat
Definition: canvas_recorder.h:27
impeller::kDrawPicture
@ kDrawPicture
Definition: canvas_recorder.h:45
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::PointStyle
PointStyle
Definition: canvas.h:40
impeller::kRotate
@ kRotate
Definition: canvas_recorder.h:33
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::kSave
@ kSave
Definition: canvas_recorder.h:21
impeller::kDrawCircle
@ kDrawCircle
Definition: canvas_recorder.h:38
impeller::kDrawTextFrame
@ kDrawTextFrame
Definition: canvas_recorder.h:46
impeller::kScale2
@ kScale2
Definition: canvas_recorder.h:30
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:222
impeller::Canvas::Save
void Save()
Definition: canvas.cc:132
impeller::kDrawRect
@ kDrawRect
Definition: canvas_recorder.h:36
impeller::kSkew
@ kSkew
Definition: canvas_recorder.h:32
impeller::kClipRRect
@ kClipRRect
Definition: canvas_recorder.h:44
impeller::kDrawImageRect
@ kDrawImageRect
Definition: canvas_recorder.h:41
canvas.h
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:488
impeller::kTransform
@ kTransform
Definition: canvas_recorder.h:26
impeller::kDrawAtlas
@ kDrawAtlas
Definition: canvas_recorder.h:48
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:489
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:39
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:59
impeller::kScale3
@ kScale3
Definition: canvas_recorder.h:31
impeller::kDrawVertices
@ kDrawVertices
Definition: canvas_recorder.h:47
impeller::kDrawPath
@ kDrawPath
Definition: canvas_recorder.h:34
impeller::kDrawRRect
@ kDrawRRect
Definition: canvas_recorder.h:37
impeller
Definition: aiks_context.cc:10
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:43
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