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/testing/assertions_skia.h" |
13 | #include "gtest/gtest.h" |
14 | #include "third_party/skia/include/core/SkCanvas.h" |
15 | #include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" |
16 | #include "third_party/skia/include/core/SkClipOp.h" |
17 | #include "third_party/skia/include/core/SkData.h" |
18 | #include "third_party/skia/include/core/SkImageFilter.h" |
19 | #include "third_party/skia/include/core/SkM44.h" |
20 | #include "third_party/skia/include/core/SkPath.h" |
21 | #include "third_party/skia/include/core/SkRRect.h" |
22 | #include "third_party/skia/include/core/SkRect.h" |
23 | #include "third_party/skia/include/utils/SkNWayCanvas.h" |
24 | |
25 | namespace flutter { |
26 | namespace testing { |
27 | |
28 | static constexpr SkRect kEmptyRect = SkRect::MakeEmpty(); |
29 | |
30 | // Mock |SkCanvas|, useful for writing tests that use Skia but do not interact |
31 | // with the GPU. |
32 | // |
33 | // The |MockCanvas| stores a list of |DrawCall| that the test can later verify |
34 | // against the expected list of primitives to be drawn. |
35 | class MockCanvas : public SkCanvasVirtualEnforcer<SkCanvas> { |
36 | public: |
37 | using SkCanvas::kHard_ClipEdgeStyle; |
38 | using SkCanvas::kSoft_ClipEdgeStyle; |
39 | |
40 | struct SaveData { |
41 | int save_to_layer; |
42 | }; |
43 | |
44 | struct SaveLayerData { |
45 | SkRect save_bounds; |
46 | SkPaint restore_paint; |
47 | sk_sp<SkImageFilter> backdrop_filter; |
48 | int save_to_layer; |
49 | }; |
50 | |
51 | struct RestoreData { |
52 | int restore_to_layer; |
53 | }; |
54 | |
55 | struct ConcatMatrixData { |
56 | SkMatrix matrix; |
57 | }; |
58 | |
59 | struct ConcatMatrix44Data { |
60 | SkM44 matrix; |
61 | }; |
62 | |
63 | struct SetMatrixData { |
64 | SkMatrix matrix; |
65 | }; |
66 | |
67 | struct DrawRectData { |
68 | SkRect rect; |
69 | SkPaint paint; |
70 | }; |
71 | |
72 | struct DrawPathData { |
73 | SkPath path; |
74 | SkPaint paint; |
75 | }; |
76 | |
77 | struct DrawTextData { |
78 | sk_sp<SkData> serialized_text; |
79 | SkPaint paint; |
80 | SkPoint offset; |
81 | }; |
82 | |
83 | struct DrawPictureData { |
84 | sk_sp<SkData> serialized_picture; |
85 | SkPaint paint; |
86 | SkMatrix matrix; |
87 | }; |
88 | |
89 | struct DrawShadowData { |
90 | SkPath path; |
91 | }; |
92 | |
93 | struct ClipRectData { |
94 | SkRect rect; |
95 | SkClipOp clip_op; |
96 | ClipEdgeStyle style; |
97 | }; |
98 | |
99 | struct ClipRRectData { |
100 | SkRRect rrect; |
101 | SkClipOp clip_op; |
102 | ClipEdgeStyle style; |
103 | }; |
104 | |
105 | struct ClipPathData { |
106 | SkPath path; |
107 | SkClipOp clip_op; |
108 | ClipEdgeStyle style; |
109 | }; |
110 | |
111 | // Discriminated union of all the different |DrawCall| types. It is roughly |
112 | // equivalent to the different methods in |SkCanvas|' public API. |
113 | using DrawCallData = std::variant<SaveData, |
114 | SaveLayerData, |
115 | RestoreData, |
116 | ConcatMatrixData, |
117 | ConcatMatrix44Data, |
118 | SetMatrixData, |
119 | DrawRectData, |
120 | DrawPathData, |
121 | DrawTextData, |
122 | DrawPictureData, |
123 | DrawShadowData, |
124 | ClipRectData, |
125 | ClipRRectData, |
126 | ClipPathData>; |
127 | |
128 | // A single call made against this canvas. |
129 | struct DrawCall { |
130 | int layer; |
131 | DrawCallData data; |
132 | }; |
133 | |
134 | MockCanvas(); |
135 | ~MockCanvas() override; |
136 | |
137 | SkNWayCanvas* internal_canvas() { return &internal_canvas_; } |
138 | |
139 | const std::vector<DrawCall>& draw_calls() const { return draw_calls_; } |
140 | |
141 | protected: |
142 | // Save/restore/set operations that we track. |
143 | void willSave() override; |
144 | SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; |
145 | void willRestore() override; |
146 | void didRestore() override {} |
147 | void didConcat(const SkMatrix& matrix) override; |
148 | void didConcat44(const SkM44&) override; |
149 | void didScale(SkScalar x, SkScalar y) override; |
150 | void didTranslate(SkScalar x, SkScalar y) override; |
151 | void didSetMatrix(const SkMatrix& matrix) override; |
152 | |
153 | // Draw and clip operations that we track. |
154 | void onDrawRect(const SkRect& rect, const SkPaint& paint) override; |
155 | void onDrawPath(const SkPath& path, const SkPaint& paint) override; |
156 | void onDrawTextBlob(const SkTextBlob* text, |
157 | SkScalar x, |
158 | SkScalar y, |
159 | const SkPaint& paint) override; |
160 | void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override; |
161 | void onDrawPicture(const SkPicture* picture, |
162 | const SkMatrix* matrix, |
163 | const SkPaint* paint) override; |
164 | void onClipRect(const SkRect& rect, |
165 | SkClipOp op, |
166 | ClipEdgeStyle style) override; |
167 | void onClipRRect(const SkRRect& rrect, |
168 | SkClipOp op, |
169 | ClipEdgeStyle style) override; |
170 | void onClipPath(const SkPath& path, |
171 | SkClipOp op, |
172 | ClipEdgeStyle style) override; |
173 | |
174 | // Operations that we don't track. |
175 | bool onDoSaveBehind(const SkRect*) override; |
176 | void onDrawAnnotation(const SkRect&, const char[], SkData*) override; |
177 | void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; |
178 | void onDrawDrawable(SkDrawable*, const SkMatrix*) override; |
179 | void onDrawPatch(const SkPoint[12], |
180 | const SkColor[4], |
181 | const SkPoint[4], |
182 | SkBlendMode, |
183 | const SkPaint&) override; |
184 | void onDrawPaint(const SkPaint&) override; |
185 | void onDrawBehind(const SkPaint&) override; |
186 | void onDrawPoints(PointMode, |
187 | size_t, |
188 | const SkPoint[], |
189 | const SkPaint&) override; |
190 | void onDrawRegion(const SkRegion&, const SkPaint&) override; |
191 | void onDrawOval(const SkRect&, const SkPaint&) override; |
192 | void onDrawArc(const SkRect&, |
193 | SkScalar, |
194 | SkScalar, |
195 | bool, |
196 | const SkPaint&) override; |
197 | void onDrawRRect(const SkRRect&, const SkPaint&) override; |
198 | void onDrawImage(const SkImage* image, |
199 | SkScalar x, |
200 | SkScalar y, |
201 | const SkPaint* paint) override; |
202 | void onDrawImageRect(const SkImage*, |
203 | const SkRect*, |
204 | const SkRect&, |
205 | const SkPaint*, |
206 | SrcRectConstraint) override; |
207 | void onDrawImageNine(const SkImage*, |
208 | const SkIRect&, |
209 | const SkRect&, |
210 | const SkPaint*) override; |
211 | void onDrawImageLattice(const SkImage*, |
212 | const Lattice&, |
213 | const SkRect&, |
214 | const SkPaint*) override; |
215 | void onDrawVerticesObject(const SkVertices*, |
216 | SkBlendMode, |
217 | const SkPaint&) override; |
218 | void onDrawAtlas(const SkImage*, |
219 | const SkRSXform[], |
220 | const SkRect[], |
221 | const SkColor[], |
222 | int, |
223 | SkBlendMode, |
224 | const SkRect*, |
225 | const SkPaint*) override; |
226 | void onDrawEdgeAAQuad(const SkRect&, |
227 | const SkPoint[4], |
228 | QuadAAFlags, |
229 | const SkColor4f&, |
230 | SkBlendMode) override; |
231 | void onDrawEdgeAAImageSet(const ImageSetEntry[], |
232 | int, |
233 | const SkPoint[], |
234 | const SkMatrix[], |
235 | const SkPaint*, |
236 | SrcRectConstraint) override; |
237 | void onClipRegion(const SkRegion&, SkClipOp) override; |
238 | |
239 | private: |
240 | SkNWayCanvas internal_canvas_; |
241 | |
242 | std::vector<DrawCall> draw_calls_; |
243 | int current_layer_; |
244 | }; |
245 | |
246 | extern bool operator==(const MockCanvas::SaveData& a, |
247 | const MockCanvas::SaveData& b); |
248 | extern std::ostream& operator<<(std::ostream& os, |
249 | const MockCanvas::SaveData& data); |
250 | extern bool operator==(const MockCanvas::SaveLayerData& a, |
251 | const MockCanvas::SaveLayerData& b); |
252 | extern std::ostream& operator<<(std::ostream& os, |
253 | const MockCanvas::SaveLayerData& data); |
254 | extern bool operator==(const MockCanvas::RestoreData& a, |
255 | const MockCanvas::RestoreData& b); |
256 | extern std::ostream& operator<<(std::ostream& os, |
257 | const MockCanvas::RestoreData& data); |
258 | extern bool operator==(const MockCanvas::ConcatMatrixData& a, |
259 | const MockCanvas::ConcatMatrixData& b); |
260 | extern std::ostream& operator<<(std::ostream& os, |
261 | const MockCanvas::ConcatMatrixData& data); |
262 | extern bool operator==(const MockCanvas::ConcatMatrix44Data& a, |
263 | const MockCanvas::ConcatMatrix44Data& b); |
264 | extern std::ostream& operator<<(std::ostream& os, |
265 | const MockCanvas::ConcatMatrix44Data& data); |
266 | extern bool operator==(const MockCanvas::SetMatrixData& a, |
267 | const MockCanvas::SetMatrixData& b); |
268 | extern std::ostream& operator<<(std::ostream& os, |
269 | const MockCanvas::SetMatrixData& data); |
270 | extern bool operator==(const MockCanvas::DrawRectData& a, |
271 | const MockCanvas::DrawRectData& b); |
272 | extern std::ostream& operator<<(std::ostream& os, |
273 | const MockCanvas::DrawRectData& data); |
274 | extern bool operator==(const MockCanvas::DrawPathData& a, |
275 | const MockCanvas::DrawPathData& b); |
276 | extern std::ostream& operator<<(std::ostream& os, |
277 | const MockCanvas::DrawPathData& data); |
278 | extern bool operator==(const MockCanvas::DrawTextData& a, |
279 | const MockCanvas::DrawTextData& b); |
280 | extern std::ostream& operator<<(std::ostream& os, |
281 | const MockCanvas::DrawTextData& data); |
282 | extern bool operator==(const MockCanvas::DrawPictureData& a, |
283 | const MockCanvas::DrawPictureData& b); |
284 | extern std::ostream& operator<<(std::ostream& os, |
285 | const MockCanvas::DrawPictureData& data); |
286 | extern bool operator==(const MockCanvas::DrawShadowData& a, |
287 | const MockCanvas::DrawShadowData& b); |
288 | extern std::ostream& operator<<(std::ostream& os, |
289 | const MockCanvas::DrawShadowData& data); |
290 | extern bool operator==(const MockCanvas::ClipRectData& a, |
291 | const MockCanvas::ClipRectData& b); |
292 | extern std::ostream& operator<<(std::ostream& os, |
293 | const MockCanvas::ClipRectData& data); |
294 | extern bool operator==(const MockCanvas::ClipRRectData& a, |
295 | const MockCanvas::ClipRRectData& b); |
296 | extern std::ostream& operator<<(std::ostream& os, |
297 | const MockCanvas::ClipRRectData& data); |
298 | extern bool operator==(const MockCanvas::ClipPathData& a, |
299 | const MockCanvas::ClipPathData& b); |
300 | extern std::ostream& operator<<(std::ostream& os, |
301 | const MockCanvas::ClipPathData& data); |
302 | extern std::ostream& operator<<(std::ostream& os, |
303 | const MockCanvas::DrawCallData& data); |
304 | extern bool operator==(const MockCanvas::DrawCall& a, |
305 | const MockCanvas::DrawCall& b); |
306 | extern std::ostream& operator<<(std::ostream& os, |
307 | const MockCanvas::DrawCall& draw); |
308 | |
309 | } // namespace testing |
310 | } // namespace flutter |
311 | |
312 | #endif // TESTING_MOCK_CANVAS_H_ |
313 | |