Flutter Engine
mock_canvas.cc
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 #include "flutter/testing/mock_canvas.h"
6 
7 #include "flutter/fml/logging.h"
8 #include "third_party/skia/include/core/SkImageInfo.h"
9 #include "third_party/skia/include/core/SkPicture.h"
10 #include "third_party/skia/include/core/SkSerialProcs.h"
11 #include "third_party/skia/include/core/SkSize.h"
12 #include "third_party/skia/include/core/SkTextBlob.h"
13 
14 namespace flutter {
15 namespace testing {
16 
17 constexpr SkISize kSize = SkISize::Make(64, 64);
18 
20  : SkCanvasVirtualEnforcer<SkCanvas>(kSize.fWidth, kSize.fHeight),
21  internal_canvas_(imageInfo().width(), imageInfo().height()),
22  current_layer_(0) {
23  internal_canvas_.addCanvas(this);
24 }
25 
27  EXPECT_EQ(current_layer_, 0);
28 }
29 
31  draw_calls_.emplace_back(
32  DrawCall{current_layer_, SaveData{current_layer_ + 1}});
33  current_layer_++; // Must go here; func params order of eval is undefined
34 }
35 
36 SkCanvas::SaveLayerStrategy MockCanvas::getSaveLayerStrategy(
37  const SaveLayerRec& rec) {
38  // saveLayer calls this prior to running, so we use it to track saveLayer
39  // calls
40  draw_calls_.emplace_back(DrawCall{
41  current_layer_,
42  SaveLayerData{rec.fBounds ? *rec.fBounds : SkRect(),
43  rec.fPaint ? *rec.fPaint : SkPaint(),
44  rec.fBackdrop ? sk_ref_sp<SkImageFilter>(rec.fBackdrop)
45  : sk_sp<SkImageFilter>(),
46  current_layer_ + 1}});
47  current_layer_++; // Must go here; func params order of eval is undefined
48  return kNoLayer_SaveLayerStrategy;
49 }
50 
52  FML_DCHECK(current_layer_ > 0);
53 
54  draw_calls_.emplace_back(
55  DrawCall{current_layer_, RestoreData{current_layer_ - 1}});
56  current_layer_--; // Must go here; func params order of eval is undefined
57 }
58 
59 void MockCanvas::didConcat(const SkMatrix& matrix) {
60  draw_calls_.emplace_back(DrawCall{current_layer_, ConcatMatrixData{matrix}});
61 }
62 
63 void MockCanvas::didConcat44(const SkM44& matrix) {
64  draw_calls_.emplace_back(
65  DrawCall{current_layer_, ConcatMatrix44Data{matrix}});
66 }
67 
68 void MockCanvas::didScale(SkScalar x, SkScalar y) {
69  SkMatrix m;
70  m.setScale(x, y);
71  this->didConcat(m);
72 }
73 
74 void MockCanvas::didTranslate(SkScalar x, SkScalar y) {
75  SkMatrix m;
76  m.setTranslate(x, y);
77  this->didConcat(m);
78 }
79 
80 void MockCanvas::didSetMatrix(const SkMatrix& matrix) {
81  draw_calls_.emplace_back(DrawCall{current_layer_, SetMatrixData{matrix}});
82 }
83 
84 void MockCanvas::onDrawTextBlob(const SkTextBlob* text,
85  SkScalar x,
86  SkScalar y,
87  const SkPaint& paint) {
88  // This duplicates existing logic in SkCanvas::onDrawPicture
89  // that should probably be split out so it doesn't need to be here as well.
90  SkRect storage;
91  const SkRect* bounds = nullptr;
92  if (paint.canComputeFastBounds()) {
93  storage = text->bounds().makeOffset(x, y);
94  SkRect tmp;
95  if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
96  return;
97  }
98  bounds = &storage;
99  }
100 
101  draw_calls_.emplace_back(DrawCall{
102  current_layer_, DrawTextData{text ? text->serialize(SkSerialProcs{})
103  : SkData::MakeUninitialized(0),
104  paint, SkPoint::Make(x, y)}});
105 }
106 
107 void MockCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
108  draw_calls_.emplace_back(DrawCall{current_layer_, DrawRectData{rect, paint}});
109 }
110 
111 void MockCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
112  draw_calls_.emplace_back(DrawCall{current_layer_, DrawPathData{path, paint}});
113 }
114 
116  const SkDrawShadowRec& rec) {
117  (void)rec; // Can't use b/c Skia keeps this type anonymous.
118  draw_calls_.emplace_back(DrawCall{current_layer_, DrawShadowData{path}});
119 }
120 
121 void MockCanvas::onDrawPicture(const SkPicture* picture,
122  const SkMatrix* matrix,
123  const SkPaint* paint) {
124  // This duplicates existing logic in SkCanvas::onDrawPicture
125  // that should probably be split out so it doesn't need to be here as well.
126  if (!paint || paint->canComputeFastBounds()) {
127  SkRect bounds = picture->cullRect();
128  if (paint) {
129  paint->computeFastBounds(bounds, &bounds);
130  }
131  if (matrix) {
132  matrix->mapRect(&bounds);
133  }
134  if (this->quickReject(bounds)) {
135  return;
136  }
137  }
138 
139  draw_calls_.emplace_back(DrawCall{
140  current_layer_,
142  picture ? picture->serialize() : SkData::MakeUninitialized(0),
143  paint ? *paint : SkPaint(), matrix ? *matrix : SkMatrix()}});
144 }
145 
146 void MockCanvas::onClipRect(const SkRect& rect,
147  SkClipOp op,
148  ClipEdgeStyle style) {
149  draw_calls_.emplace_back(
150  DrawCall{current_layer_, ClipRectData{rect, op, style}});
151 }
152 
153 void MockCanvas::onClipRRect(const SkRRect& rrect,
154  SkClipOp op,
155  ClipEdgeStyle style) {
156  draw_calls_.emplace_back(
157  DrawCall{current_layer_, ClipRRectData{rrect, op, style}});
158 }
159 
160 void MockCanvas::onClipPath(const SkPath& path,
161  SkClipOp op,
162  ClipEdgeStyle style) {
163  draw_calls_.emplace_back(
164  DrawCall{current_layer_, ClipPathData{path, op, style}});
165 }
166 
167 bool MockCanvas::onDoSaveBehind(const SkRect*) {
168  FML_DCHECK(false);
169  return false;
170 }
171 
172 void MockCanvas::onDrawAnnotation(const SkRect&, const char[], SkData*) {
173  FML_DCHECK(false);
174 }
175 
176 void MockCanvas::onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) {
177  FML_DCHECK(false);
178 }
179 
180 void MockCanvas::onDrawDrawable(SkDrawable*, const SkMatrix*) {
181  FML_DCHECK(false);
182 }
183 
184 void MockCanvas::onDrawPatch(const SkPoint[12],
185  const SkColor[4],
186  const SkPoint[4],
187  SkBlendMode,
188  const SkPaint&) {
189  FML_DCHECK(false);
190 }
191 
192 void MockCanvas::onDrawPaint(const SkPaint& skPaint) {
193  draw_calls_.emplace_back(DrawCall{current_layer_, DrawPaint{skPaint}});
194 }
195 
196 void MockCanvas::onDrawBehind(const SkPaint&) {
197  FML_DCHECK(false);
198 }
199 
201  size_t,
202  const SkPoint[],
203  const SkPaint&) {
204  FML_DCHECK(false);
205 }
206 
207 void MockCanvas::onDrawRegion(const SkRegion&, const SkPaint&) {
208  FML_DCHECK(false);
209 }
210 
211 void MockCanvas::onDrawOval(const SkRect&, const SkPaint&) {
212  FML_DCHECK(false);
213 }
214 
215 void MockCanvas::onDrawArc(const SkRect&,
216  SkScalar,
217  SkScalar,
218  bool,
219  const SkPaint&) {
220  FML_DCHECK(false);
221 }
222 
223 void MockCanvas::onDrawRRect(const SkRRect&, const SkPaint&) {
224  FML_DCHECK(false);
225 }
226 
227 void MockCanvas::onDrawImage(const SkImage*,
228  SkScalar,
229  SkScalar,
230  const SkPaint*) {
231  FML_DCHECK(false);
232 }
233 
234 void MockCanvas::onDrawImageRect(const SkImage*,
235  const SkRect*,
236  const SkRect&,
237  const SkPaint*,
238  SrcRectConstraint) {
239  FML_DCHECK(false);
240 }
241 
242 void MockCanvas::onDrawImageNine(const SkImage*,
243  const SkIRect&,
244  const SkRect&,
245  const SkPaint*) {
246  FML_DCHECK(false);
247 }
248 
249 void MockCanvas::onDrawImageLattice(const SkImage*,
250  const Lattice&,
251  const SkRect&,
252  const SkPaint*) {
253  FML_DCHECK(false);
254 }
255 
256 void MockCanvas::onDrawVerticesObject(const SkVertices*,
257  SkBlendMode,
258  const SkPaint&) {
259  FML_DCHECK(false);
260 }
261 
262 void MockCanvas::onDrawAtlas(const SkImage*,
263  const SkRSXform[],
264  const SkRect[],
265  const SkColor[],
266  int,
267  SkBlendMode,
268  const SkRect*,
269  const SkPaint*) {
270  FML_DCHECK(false);
271 }
272 
273 void MockCanvas::onDrawEdgeAAQuad(const SkRect&,
274  const SkPoint[4],
275  QuadAAFlags,
276  const SkColor4f&,
277  SkBlendMode) {
278  FML_DCHECK(false);
279 }
280 
281 void MockCanvas::onDrawEdgeAAImageSet(const ImageSetEntry[],
282  int,
283  const SkPoint[],
284  const SkMatrix[],
285  const SkPaint*,
286  SrcRectConstraint) {
287  FML_DCHECK(false);
288 }
289 
290 void MockCanvas::onClipRegion(const SkRegion&, SkClipOp) {
291  FML_DCHECK(false);
292 }
293 
295  return a.save_to_layer == b.save_to_layer;
296 }
297 
298 std::ostream& operator<<(std::ostream& os, const MockCanvas::SaveData& data) {
299  return os << data.save_to_layer;
300 }
301 
303  const MockCanvas::SaveLayerData& b) {
304  return a.save_bounds == b.save_bounds && a.restore_paint == b.restore_paint &&
307 }
308 
309 std::ostream& operator<<(std::ostream& os,
310  const MockCanvas::SaveLayerData& data) {
311  return os << data.save_bounds << " " << data.restore_paint << " "
312  << data.backdrop_filter << " " << data.save_to_layer;
313 }
314 
316  const MockCanvas::RestoreData& b) {
317  return a.restore_to_layer == b.restore_to_layer;
318 }
319 
320 std::ostream& operator<<(std::ostream& os,
321  const MockCanvas::RestoreData& data) {
322  return os << data.restore_to_layer;
323 }
324 
326  const MockCanvas::ConcatMatrixData& b) {
327  return a.matrix == b.matrix;
328 }
329 
330 std::ostream& operator<<(std::ostream& os,
331  const MockCanvas::ConcatMatrixData& data) {
332  return os << data.matrix;
333 }
334 
337  return a.matrix == b.matrix;
338 }
339 
340 std::ostream& operator<<(std::ostream& os,
341  const MockCanvas::ConcatMatrix44Data& data) {
342  return os << data.matrix;
343 }
344 
346  const MockCanvas::SetMatrixData& b) {
347  return a.matrix == b.matrix;
348 }
349 
350 std::ostream& operator<<(std::ostream& os,
351  const MockCanvas::SetMatrixData& data) {
352  return os << data.matrix;
353 }
354 
356  const MockCanvas::DrawRectData& b) {
357  return a.rect == b.rect && a.paint == b.paint;
358 }
359 
360 std::ostream& operator<<(std::ostream& os,
361  const MockCanvas::DrawRectData& data) {
362  return os << data.rect << " " << data.paint;
363 }
364 
366  const MockCanvas::DrawPathData& b) {
367  return a.path == b.path && a.paint == b.paint;
368 }
369 
370 std::ostream& operator<<(std::ostream& os,
371  const MockCanvas::DrawPathData& data) {
372  return os << data.path << " " << data.paint;
373 }
374 
376  const MockCanvas::DrawTextData& b) {
377  return a.serialized_text->equals(b.serialized_text.get()) &&
378  a.paint == b.paint && a.offset == b.offset;
379 }
380 
381 std::ostream& operator<<(std::ostream& os,
382  const MockCanvas::DrawTextData& data) {
383  return os << data.serialized_text << " " << data.paint << " " << data.offset;
384 }
385 
387  const MockCanvas::DrawPictureData& b) {
388  return a.serialized_picture->equals(b.serialized_picture.get()) &&
389  a.paint == b.paint && a.matrix == b.matrix;
390 }
391 
392 std::ostream& operator<<(std::ostream& os,
393  const MockCanvas::DrawPictureData& data) {
394  return os << data.serialized_picture << " " << data.paint << " "
395  << data.matrix;
396 }
397 
399  const MockCanvas::DrawShadowData& b) {
400  return a.path == b.path;
401 }
402 
403 std::ostream& operator<<(std::ostream& os,
404  const MockCanvas::DrawShadowData& data) {
405  return os << data.path;
406 }
407 
409  const MockCanvas::ClipRectData& b) {
410  return a.rect == b.rect && a.clip_op == b.clip_op && a.style == b.style;
411 }
412 
413 std::ostream& operator<<(std::ostream& os,
414  const MockCanvas::ClipRectData& data) {
415  return os << data.rect << " " << data.clip_op << " " << data.style;
416 }
417 
419  const MockCanvas::ClipRRectData& b) {
420  return a.rrect == b.rrect && a.clip_op == b.clip_op && a.style == b.style;
421 }
422 
423 std::ostream& operator<<(std::ostream& os,
424  const MockCanvas::ClipRRectData& data) {
425  return os << data.rrect << " " << data.clip_op << " " << data.style;
426 }
427 
429  const MockCanvas::ClipPathData& b) {
430  return a.path == b.path && a.clip_op == b.clip_op && a.style == b.style;
431 }
432 
433 std::ostream& operator<<(std::ostream& os,
434  const MockCanvas::ClipPathData& data) {
435  return os << data.path << " " << data.clip_op << " " << data.style;
436 }
437 
438 std::ostream& operator<<(std::ostream& os,
439  const MockCanvas::DrawCallData& data) {
440  std::visit([&os](auto& d) { os << d; }, data);
441  return os;
442 }
443 
445  return a.layer == b.layer && a.data == b.data;
446 }
447 
448 std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawCall& draw) {
449  return os << "[Layer: " << draw.layer << ", Data: " << draw.data << "]";
450 }
451 
453  const MockCanvas::DrawPaint& b) {
454  return a.paint == b.paint;
455 }
456 
457 std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawPaint& data) {
458  return os << data.paint;
459 }
460 
461 } // namespace testing
462 } // namespace flutter
std::variant< SaveData, SaveLayerData, RestoreData, ConcatMatrixData, ConcatMatrix44Data, SetMatrixData, DrawRectData, DrawPathData, DrawTextData, DrawPictureData, DrawShadowData, ClipRectData, ClipRRectData, ClipPathData, DrawPaint > DrawCallData
Definition: mock_canvas.h:131
void onDrawRegion(const SkRegion &, const SkPaint &) override
Definition: mock_canvas.cc:207
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
void onDrawRect(const SkRect &rect, const SkPaint &paint) override
Definition: mock_canvas.cc:107
#define FML_DCHECK(condition)
Definition: logging.h:86
std::ostream & operator<<(std::ostream &os, const MockTexture::PaintCall &data)
Definition: mock_texture.cc:28
void onDrawAtlas(const SkImage *, const SkRSXform[], const SkRect[], const SkColor[], int, SkBlendMode, const SkRect *, const SkPaint *) override
Definition: mock_canvas.cc:262
void onDrawImageRect(const SkImage *, const SkRect *, const SkRect &, const SkPaint *, SrcRectConstraint) override
Definition: mock_canvas.cc:234
void onClipRegion(const SkRegion &, SkClipOp) override
Definition: mock_canvas.cc:290
void onDrawAnnotation(const SkRect &, const char[], SkData *) override
Definition: mock_canvas.cc:172
void didScale(SkScalar x, SkScalar y) override
Definition: mock_canvas.cc:68
void onDrawShadowRec(const SkPath &path, const SkDrawShadowRec &rec) override
Definition: mock_canvas.cc:115
void onDrawOval(const SkRect &, const SkPaint &) override
Definition: mock_canvas.cc:211
void onClipRRect(const SkRRect &rrect, SkClipOp op, ClipEdgeStyle style) override
Definition: mock_canvas.cc:153
void onDrawPaint(const SkPaint &) override
Definition: mock_canvas.cc:192
constexpr SkISize kSize
Definition: mock_canvas.cc:17
void onDrawArc(const SkRect &, SkScalar, SkScalar, bool, const SkPaint &) override
Definition: mock_canvas.cc:215
void onDrawRRect(const SkRRect &, const SkPaint &) override
Definition: mock_canvas.cc:223
void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint &) override
Definition: mock_canvas.cc:200
void onDrawDRRect(const SkRRect &, const SkRRect &, const SkPaint &) override
Definition: mock_canvas.cc:176
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec &rec) override
Definition: mock_canvas.cc:36
void onDrawEdgeAAImageSet(const ImageSetEntry[], int, const SkPoint[], const SkMatrix[], const SkPaint *, SrcRectConstraint) override
Definition: mock_canvas.cc:281
void onDrawVerticesObject(const SkVertices *, SkBlendMode, const SkPaint &) override
Definition: mock_canvas.cc:256
void onDrawPath(const SkPath &path, const SkPaint &paint) override
Definition: mock_canvas.cc:111
void onDrawBehind(const SkPaint &) override
Definition: mock_canvas.cc:196
void onDrawDrawable(SkDrawable *, const SkMatrix *) override
Definition: mock_canvas.cc:180
void onDrawPicture(const SkPicture *picture, const SkMatrix *matrix, const SkPaint *paint) override
Definition: mock_canvas.cc:121
int32_t height
bool operator==(const MockTexture::PaintCall &a, const MockTexture::PaintCall &b)
Definition: mock_texture.cc:21
void didTranslate(SkScalar x, SkScalar y) override
Definition: mock_canvas.cc:74
int32_t width
void onClipPath(const SkPath &path, SkClipOp op, ClipEdgeStyle style) override
Definition: mock_canvas.cc:160
void onDrawEdgeAAQuad(const SkRect &, const SkPoint[4], QuadAAFlags, const SkColor4f &, SkBlendMode) override
Definition: mock_canvas.cc:273
void onDrawImageLattice(const SkImage *, const Lattice &, const SkRect &, const SkPaint *) override
Definition: mock_canvas.cc:249
void onDrawImageNine(const SkImage *, const SkIRect &, const SkRect &, const SkPaint *) override
Definition: mock_canvas.cc:242
void onDrawTextBlob(const SkTextBlob *text, SkScalar x, SkScalar y, const SkPaint &paint) override
Definition: mock_canvas.cc:84
void didConcat(const SkMatrix &matrix) override
Definition: mock_canvas.cc:59
void didConcat44(const SkM44 &) override
Definition: mock_canvas.cc:63
void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode, const SkPaint &) override
Definition: mock_canvas.cc:184
void didSetMatrix(const SkMatrix &matrix) override
Definition: mock_canvas.cc:80
void onClipRect(const SkRect &rect, SkClipOp op, ClipEdgeStyle style) override
Definition: mock_canvas.cc:146
void willRestore() override
Definition: mock_canvas.cc:51
bool onDoSaveBehind(const SkRect *) override
Definition: mock_canvas.cc:167
void onDrawImage(const SkImage *image, SkScalar x, SkScalar y, const SkPaint *paint) override
Definition: mock_canvas.cc:227