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 TESTING_MOCK_CANVAS_H_ |
6 | #define TESTING_MOCK_CANVAS_H_ |
7 | |
8 | #include <ostream> |
9 | #include <variant> |
10 | #include <vector> |
11 | |
12 | #include "flutter/display_list/dl_canvas.h" |
13 | #include "flutter/display_list/utils/dl_matrix_clip_tracker.h" |
14 | #include "gtest/gtest.h" |
15 | #include "third_party/skia/include/core/SkCanvas.h" |
16 | #include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" |
17 | #include "third_party/skia/include/core/SkClipOp.h" |
18 | #include "third_party/skia/include/core/SkData.h" |
19 | #include "third_party/skia/include/core/SkImage.h" |
20 | #include "third_party/skia/include/core/SkImageFilter.h" |
21 | #include "third_party/skia/include/core/SkM44.h" |
22 | #include "third_party/skia/include/core/SkPath.h" |
23 | #include "third_party/skia/include/core/SkRRect.h" |
24 | #include "third_party/skia/include/core/SkRect.h" |
25 | #include "third_party/skia/include/utils/SkNWayCanvas.h" |
26 | |
27 | namespace flutter { |
28 | namespace testing { |
29 | |
30 | static constexpr SkRect kEmptyRect = SkRect::MakeEmpty(); |
31 | |
32 | // Mock |SkCanvas|, useful for writing tests that use Skia but do not interact |
33 | // with the GPU. |
34 | // |
35 | // The |MockCanvas| stores a list of |DrawCall| that the test can later verify |
36 | // against the expected list of primitives to be drawn. |
37 | class MockCanvas final : public DlCanvas { |
38 | public: |
39 | enum ClipEdgeStyle { |
40 | kHard_ClipEdgeStyle, |
41 | kSoft_ClipEdgeStyle, |
42 | }; |
43 | |
44 | struct SaveData { |
45 | int save_to_layer; |
46 | }; |
47 | |
48 | struct SaveLayerData { |
49 | SkRect save_bounds; |
50 | DlPaint restore_paint; |
51 | std::shared_ptr<DlImageFilter> backdrop_filter; |
52 | int save_to_layer; |
53 | }; |
54 | |
55 | struct RestoreData { |
56 | int restore_to_layer; |
57 | }; |
58 | |
59 | struct ConcatMatrixData { |
60 | SkM44 matrix; |
61 | }; |
62 | |
63 | struct SetMatrixData { |
64 | SkM44 matrix; |
65 | }; |
66 | |
67 | struct DrawRectData { |
68 | SkRect rect; |
69 | DlPaint paint; |
70 | }; |
71 | |
72 | struct DrawPathData { |
73 | SkPath path; |
74 | DlPaint paint; |
75 | }; |
76 | |
77 | struct DrawTextData { |
78 | sk_sp<SkData> serialized_text; |
79 | DlPaint paint; |
80 | SkPoint offset; |
81 | }; |
82 | |
83 | struct DrawImageDataNoPaint { |
84 | sk_sp<DlImage> image; |
85 | SkScalar x; |
86 | SkScalar y; |
87 | DlImageSampling options; |
88 | }; |
89 | |
90 | struct DrawImageData { |
91 | sk_sp<DlImage> image; |
92 | SkScalar x; |
93 | SkScalar y; |
94 | DlImageSampling options; |
95 | DlPaint paint; |
96 | }; |
97 | |
98 | struct DrawDisplayListData { |
99 | sk_sp<DisplayList> display_list; |
100 | SkScalar opacity; |
101 | }; |
102 | |
103 | struct DrawShadowData { |
104 | SkPath path; |
105 | DlColor color; |
106 | SkScalar elevation; |
107 | bool transparent_occluder; |
108 | SkScalar dpr; |
109 | }; |
110 | |
111 | struct ClipRectData { |
112 | SkRect rect; |
113 | ClipOp clip_op; |
114 | ClipEdgeStyle style; |
115 | }; |
116 | |
117 | struct ClipRRectData { |
118 | SkRRect rrect; |
119 | ClipOp clip_op; |
120 | ClipEdgeStyle style; |
121 | }; |
122 | |
123 | struct ClipPathData { |
124 | SkPath path; |
125 | ClipOp clip_op; |
126 | ClipEdgeStyle style; |
127 | }; |
128 | |
129 | struct DrawPaintData { |
130 | DlPaint paint; |
131 | }; |
132 | |
133 | // Discriminated union of all the different |DrawCall| types. It is roughly |
134 | // equivalent to the different methods in |SkCanvas|' public API. |
135 | using DrawCallData = std::variant<SaveData, |
136 | SaveLayerData, |
137 | RestoreData, |
138 | ConcatMatrixData, |
139 | SetMatrixData, |
140 | DrawRectData, |
141 | DrawPathData, |
142 | DrawTextData, |
143 | DrawImageDataNoPaint, |
144 | DrawImageData, |
145 | DrawDisplayListData, |
146 | DrawShadowData, |
147 | ClipRectData, |
148 | ClipRRectData, |
149 | ClipPathData, |
150 | DrawPaintData>; |
151 | |
152 | // A single call made against this canvas. |
153 | struct DrawCall { |
154 | int layer; |
155 | DrawCallData data; |
156 | }; |
157 | |
158 | MockCanvas(); |
159 | MockCanvas(int width, int height); |
160 | ~MockCanvas(); |
161 | |
162 | const std::vector<DrawCall>& draw_calls() const { return draw_calls_; } |
163 | void reset_draw_calls() { draw_calls_.clear(); } |
164 | |
165 | SkISize GetBaseLayerSize() const override; |
166 | SkImageInfo GetImageInfo() const override; |
167 | |
168 | void Save() override; |
169 | void SaveLayer(const SkRect* bounds, |
170 | const DlPaint* paint = nullptr, |
171 | const DlImageFilter* backdrop = nullptr) override; |
172 | void Restore() override; |
173 | int GetSaveCount() const { return current_layer_; } |
174 | void RestoreToCount(int restore_count) { |
175 | while (current_layer_ > restore_count) { |
176 | Restore(); |
177 | } |
178 | } |
179 | |
180 | // clang-format off |
181 | |
182 | // 2x3 2D affine subset of a 4x4 transform in row major order |
183 | void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, |
184 | SkScalar myx, SkScalar myy, SkScalar myt) override; |
185 | // full 4x4 transform in row major order |
186 | void TransformFullPerspective( |
187 | SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, |
188 | SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, |
189 | SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, |
190 | SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override; |
191 | // clang-format on |
192 | |
193 | void Translate(SkScalar tx, SkScalar ty) override; |
194 | void Scale(SkScalar sx, SkScalar sy) override; |
195 | void Rotate(SkScalar degrees) override; |
196 | void Skew(SkScalar sx, SkScalar sy) override; |
197 | void TransformReset() override; |
198 | void Transform(const SkMatrix* matrix) override; |
199 | void Transform(const SkM44* matrix44) override; |
200 | void SetTransform(const SkMatrix* matrix) override; |
201 | void SetTransform(const SkM44* matrix44) override; |
202 | using DlCanvas::SetTransform; |
203 | using DlCanvas::Transform; |
204 | |
205 | SkM44 GetTransformFullPerspective() const override; |
206 | SkMatrix GetTransform() const override; |
207 | |
208 | void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; |
209 | void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; |
210 | void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; |
211 | |
212 | SkRect GetDestinationClipBounds() const override; |
213 | SkRect GetLocalClipBounds() const override; |
214 | bool QuickReject(const SkRect& bounds) const override; |
215 | |
216 | void DrawPaint(const DlPaint& paint) override; |
217 | void DrawColor(DlColor color, DlBlendMode mode) override; |
218 | void DrawLine(const SkPoint& p0, |
219 | const SkPoint& p1, |
220 | const DlPaint& paint) override; |
221 | void DrawRect(const SkRect& rect, const DlPaint& paint) override; |
222 | void DrawOval(const SkRect& bounds, const DlPaint& paint) override; |
223 | void DrawCircle(const SkPoint& center, |
224 | SkScalar radius, |
225 | const DlPaint& paint) override; |
226 | void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override; |
227 | void DrawDRRect(const SkRRect& outer, |
228 | const SkRRect& inner, |
229 | const DlPaint& paint) override; |
230 | void DrawPath(const SkPath& path, const DlPaint& paint) override; |
231 | void DrawArc(const SkRect& bounds, |
232 | SkScalar start, |
233 | SkScalar sweep, |
234 | bool useCenter, |
235 | const DlPaint& paint) override; |
236 | void DrawPoints(PointMode mode, |
237 | uint32_t count, |
238 | const SkPoint pts[], |
239 | const DlPaint& paint) override; |
240 | void DrawVertices(const DlVertices* vertices, |
241 | DlBlendMode mode, |
242 | const DlPaint& paint) override; |
243 | |
244 | void DrawImage(const sk_sp<DlImage>& image, |
245 | const SkPoint point, |
246 | DlImageSampling sampling, |
247 | const DlPaint* paint = nullptr) override; |
248 | void DrawImageRect( |
249 | const sk_sp<DlImage>& image, |
250 | const SkRect& src, |
251 | const SkRect& dst, |
252 | DlImageSampling sampling, |
253 | const DlPaint* paint = nullptr, |
254 | SrcRectConstraint constraint = SrcRectConstraint::kFast) override; |
255 | void DrawImageNine(const sk_sp<DlImage>& image, |
256 | const SkIRect& center, |
257 | const SkRect& dst, |
258 | DlFilterMode filter, |
259 | const DlPaint* paint = nullptr) override; |
260 | void DrawAtlas(const sk_sp<DlImage>& atlas, |
261 | const SkRSXform xform[], |
262 | const SkRect tex[], |
263 | const DlColor colors[], |
264 | int count, |
265 | DlBlendMode mode, |
266 | DlImageSampling sampling, |
267 | const SkRect* cullRect, |
268 | const DlPaint* paint = nullptr) override; |
269 | |
270 | void DrawDisplayList(const sk_sp<DisplayList> display_list, |
271 | SkScalar opacity) override; |
272 | void DrawTextBlob(const sk_sp<SkTextBlob>& blob, |
273 | SkScalar x, |
274 | SkScalar y, |
275 | const DlPaint& paint) override; |
276 | void DrawShadow(const SkPath& path, |
277 | const DlColor color, |
278 | const SkScalar elevation, |
279 | bool transparent_occluder, |
280 | SkScalar dpr) override; |
281 | |
282 | void Flush() override; |
283 | |
284 | private: |
285 | DisplayListMatrixClipTracker tracker_; |
286 | std::vector<DrawCall> draw_calls_; |
287 | int current_layer_; |
288 | }; |
289 | |
290 | extern bool operator==(const MockCanvas::SaveData& a, |
291 | const MockCanvas::SaveData& b); |
292 | extern std::ostream& operator<<(std::ostream& os, |
293 | const MockCanvas::SaveData& data); |
294 | extern bool operator==(const MockCanvas::SaveLayerData& a, |
295 | const MockCanvas::SaveLayerData& b); |
296 | extern std::ostream& operator<<(std::ostream& os, |
297 | const MockCanvas::SaveLayerData& data); |
298 | extern bool operator==(const MockCanvas::RestoreData& a, |
299 | const MockCanvas::RestoreData& b); |
300 | extern std::ostream& operator<<(std::ostream& os, |
301 | const MockCanvas::RestoreData& data); |
302 | extern bool operator==(const MockCanvas::ConcatMatrixData& a, |
303 | const MockCanvas::ConcatMatrixData& b); |
304 | extern std::ostream& operator<<(std::ostream& os, |
305 | const MockCanvas::ConcatMatrixData& data); |
306 | extern bool operator==(const MockCanvas::SetMatrixData& a, |
307 | const MockCanvas::SetMatrixData& b); |
308 | extern std::ostream& operator<<(std::ostream& os, |
309 | const MockCanvas::SetMatrixData& data); |
310 | extern bool operator==(const MockCanvas::DrawRectData& a, |
311 | const MockCanvas::DrawRectData& b); |
312 | extern std::ostream& operator<<(std::ostream& os, |
313 | const MockCanvas::DrawRectData& data); |
314 | extern bool operator==(const MockCanvas::DrawPathData& a, |
315 | const MockCanvas::DrawPathData& b); |
316 | extern std::ostream& operator<<(std::ostream& os, |
317 | const MockCanvas::DrawPathData& data); |
318 | extern bool operator==(const MockCanvas::DrawTextData& a, |
319 | const MockCanvas::DrawTextData& b); |
320 | extern std::ostream& operator<<(std::ostream& os, |
321 | const MockCanvas::DrawTextData& data); |
322 | extern bool operator==(const MockCanvas::DrawImageData& a, |
323 | const MockCanvas::DrawImageData& b); |
324 | extern std::ostream& operator<<(std::ostream& os, |
325 | const MockCanvas::DrawImageData& data); |
326 | extern bool operator==(const MockCanvas::DrawImageDataNoPaint& a, |
327 | const MockCanvas::DrawImageDataNoPaint& b); |
328 | extern std::ostream& operator<<(std::ostream& os, |
329 | const MockCanvas::DrawImageDataNoPaint& data); |
330 | extern bool operator==(const MockCanvas::DrawDisplayListData& a, |
331 | const MockCanvas::DrawDisplayListData& b); |
332 | extern std::ostream& operator<<(std::ostream& os, |
333 | const MockCanvas::DrawDisplayListData& data); |
334 | extern bool operator==(const MockCanvas::DrawShadowData& a, |
335 | const MockCanvas::DrawShadowData& b); |
336 | extern std::ostream& operator<<(std::ostream& os, |
337 | const MockCanvas::DrawShadowData& data); |
338 | extern bool operator==(const MockCanvas::ClipRectData& a, |
339 | const MockCanvas::ClipRectData& b); |
340 | extern std::ostream& operator<<(std::ostream& os, |
341 | const MockCanvas::ClipRectData& data); |
342 | extern bool operator==(const MockCanvas::ClipRRectData& a, |
343 | const MockCanvas::ClipRRectData& b); |
344 | extern std::ostream& operator<<(std::ostream& os, |
345 | const MockCanvas::ClipRRectData& data); |
346 | extern bool operator==(const MockCanvas::ClipPathData& a, |
347 | const MockCanvas::ClipPathData& b); |
348 | extern std::ostream& operator<<(std::ostream& os, |
349 | const MockCanvas::ClipPathData& data); |
350 | extern std::ostream& operator<<(std::ostream& os, |
351 | const MockCanvas::DrawCallData& data); |
352 | extern bool operator==(const MockCanvas::DrawCall& a, |
353 | const MockCanvas::DrawCall& b); |
354 | extern std::ostream& operator<<(std::ostream& os, |
355 | const MockCanvas::DrawCall& draw); |
356 | extern bool operator==(const MockCanvas::DrawPaintData& a, |
357 | const MockCanvas::DrawPaintData& b); |
358 | extern std::ostream& operator<<(std::ostream& os, |
359 | const MockCanvas::DrawPaintData& data); |
360 | } // namespace testing |
361 | } // namespace flutter |
362 | |
363 | #endif // TESTING_MOCK_CANVAS_H_ |
364 | |