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
27namespace flutter {
28namespace testing {
29
30static 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.
37class 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
290extern bool operator==(const MockCanvas::SaveData& a,
291 const MockCanvas::SaveData& b);
292extern std::ostream& operator<<(std::ostream& os,
293 const MockCanvas::SaveData& data);
294extern bool operator==(const MockCanvas::SaveLayerData& a,
295 const MockCanvas::SaveLayerData& b);
296extern std::ostream& operator<<(std::ostream& os,
297 const MockCanvas::SaveLayerData& data);
298extern bool operator==(const MockCanvas::RestoreData& a,
299 const MockCanvas::RestoreData& b);
300extern std::ostream& operator<<(std::ostream& os,
301 const MockCanvas::RestoreData& data);
302extern bool operator==(const MockCanvas::ConcatMatrixData& a,
303 const MockCanvas::ConcatMatrixData& b);
304extern std::ostream& operator<<(std::ostream& os,
305 const MockCanvas::ConcatMatrixData& data);
306extern bool operator==(const MockCanvas::SetMatrixData& a,
307 const MockCanvas::SetMatrixData& b);
308extern std::ostream& operator<<(std::ostream& os,
309 const MockCanvas::SetMatrixData& data);
310extern bool operator==(const MockCanvas::DrawRectData& a,
311 const MockCanvas::DrawRectData& b);
312extern std::ostream& operator<<(std::ostream& os,
313 const MockCanvas::DrawRectData& data);
314extern bool operator==(const MockCanvas::DrawPathData& a,
315 const MockCanvas::DrawPathData& b);
316extern std::ostream& operator<<(std::ostream& os,
317 const MockCanvas::DrawPathData& data);
318extern bool operator==(const MockCanvas::DrawTextData& a,
319 const MockCanvas::DrawTextData& b);
320extern std::ostream& operator<<(std::ostream& os,
321 const MockCanvas::DrawTextData& data);
322extern bool operator==(const MockCanvas::DrawImageData& a,
323 const MockCanvas::DrawImageData& b);
324extern std::ostream& operator<<(std::ostream& os,
325 const MockCanvas::DrawImageData& data);
326extern bool operator==(const MockCanvas::DrawImageDataNoPaint& a,
327 const MockCanvas::DrawImageDataNoPaint& b);
328extern std::ostream& operator<<(std::ostream& os,
329 const MockCanvas::DrawImageDataNoPaint& data);
330extern bool operator==(const MockCanvas::DrawDisplayListData& a,
331 const MockCanvas::DrawDisplayListData& b);
332extern std::ostream& operator<<(std::ostream& os,
333 const MockCanvas::DrawDisplayListData& data);
334extern bool operator==(const MockCanvas::DrawShadowData& a,
335 const MockCanvas::DrawShadowData& b);
336extern std::ostream& operator<<(std::ostream& os,
337 const MockCanvas::DrawShadowData& data);
338extern bool operator==(const MockCanvas::ClipRectData& a,
339 const MockCanvas::ClipRectData& b);
340extern std::ostream& operator<<(std::ostream& os,
341 const MockCanvas::ClipRectData& data);
342extern bool operator==(const MockCanvas::ClipRRectData& a,
343 const MockCanvas::ClipRRectData& b);
344extern std::ostream& operator<<(std::ostream& os,
345 const MockCanvas::ClipRRectData& data);
346extern bool operator==(const MockCanvas::ClipPathData& a,
347 const MockCanvas::ClipPathData& b);
348extern std::ostream& operator<<(std::ostream& os,
349 const MockCanvas::ClipPathData& data);
350extern std::ostream& operator<<(std::ostream& os,
351 const MockCanvas::DrawCallData& data);
352extern bool operator==(const MockCanvas::DrawCall& a,
353 const MockCanvas::DrawCall& b);
354extern std::ostream& operator<<(std::ostream& os,
355 const MockCanvas::DrawCall& draw);
356extern bool operator==(const MockCanvas::DrawPaintData& a,
357 const MockCanvas::DrawPaintData& b);
358extern 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

source code of flutter_engine/flutter/testing/mock_canvas.h