Flutter Engine
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/lib/ui/painting/canvas.h"
6 
7 #include <cmath>
8 
9 #include "flutter/flow/layers/physical_shape_layer.h"
10 #include "flutter/lib/ui/painting/image.h"
11 #include "flutter/lib/ui/painting/matrix.h"
12 #include "flutter/lib/ui/ui_dart_state.h"
13 #include "flutter/lib/ui/window/platform_configuration.h"
14 #include "flutter/lib/ui/window/window.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "third_party/skia/include/core/SkCanvas.h"
17 #include "third_party/skia/include/core/SkRSXform.h"
22 
23 using tonic::ToDart;
24 
25 namespace flutter {
26 
27 static void Canvas_constructor(Dart_NativeArguments args) {
30 }
31 
33 
34 #define FOR_EACH_BINDING(V) \
35  V(Canvas, save) \
36  V(Canvas, saveLayerWithoutBounds) \
37  V(Canvas, saveLayer) \
38  V(Canvas, restore) \
39  V(Canvas, getSaveCount) \
40  V(Canvas, translate) \
41  V(Canvas, scale) \
42  V(Canvas, rotate) \
43  V(Canvas, skew) \
44  V(Canvas, transform) \
45  V(Canvas, clipRect) \
46  V(Canvas, clipRRect) \
47  V(Canvas, clipPath) \
48  V(Canvas, drawColor) \
49  V(Canvas, drawLine) \
50  V(Canvas, drawPaint) \
51  V(Canvas, drawRect) \
52  V(Canvas, drawRRect) \
53  V(Canvas, drawDRRect) \
54  V(Canvas, drawOval) \
55  V(Canvas, drawCircle) \
56  V(Canvas, drawArc) \
57  V(Canvas, drawPath) \
58  V(Canvas, drawImage) \
59  V(Canvas, drawImageRect) \
60  V(Canvas, drawImageNine) \
61  V(Canvas, drawPicture) \
62  V(Canvas, drawPoints) \
63  V(Canvas, drawVertices) \
64  V(Canvas, drawAtlas) \
65  V(Canvas, drawShadow)
66 
68 
69 void Canvas::RegisterNatives(tonic::DartLibraryNatives* natives) {
70  natives->Register({{"Canvas_constructor", Canvas_constructor, 6, true},
72 }
73 
75  double left,
76  double top,
77  double right,
78  double bottom) {
79  if (!recorder) {
80  Dart_ThrowException(
81  ToDart("Canvas constructor called with non-genuine PictureRecorder."));
82  return nullptr;
83  }
84  fml::RefPtr<Canvas> canvas = fml::MakeRefCounted<Canvas>(
85  recorder->BeginRecording(SkRect::MakeLTRB(left, top, right, bottom)));
86  recorder->set_canvas(canvas);
87  return canvas;
88 }
89 
90 Canvas::Canvas(SkCanvas* canvas) : canvas_(canvas) {}
91 
93 
94 void Canvas::save() {
95  if (!canvas_) {
96  return;
97  }
98  canvas_->save();
99 }
100 
102  const PaintData& paint_data) {
103  if (!canvas_) {
104  return;
105  }
106  canvas_->saveLayer(nullptr, paint.paint());
107 }
108 
109 void Canvas::saveLayer(double left,
110  double top,
111  double right,
112  double bottom,
113  const Paint& paint,
114  const PaintData& paint_data) {
115  if (!canvas_) {
116  return;
117  }
118  SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
119  canvas_->saveLayer(&bounds, paint.paint());
120 }
121 
123  if (!canvas_) {
124  return;
125  }
126  canvas_->restore();
127 }
128 
130  if (!canvas_) {
131  return 0;
132  }
133  return canvas_->getSaveCount();
134 }
135 
136 void Canvas::translate(double dx, double dy) {
137  if (!canvas_) {
138  return;
139  }
140  canvas_->translate(dx, dy);
141 }
142 
143 void Canvas::scale(double sx, double sy) {
144  if (!canvas_) {
145  return;
146  }
147  canvas_->scale(sx, sy);
148 }
149 
150 void Canvas::rotate(double radians) {
151  if (!canvas_) {
152  return;
153  }
154  canvas_->rotate(radians * 180.0 / M_PI);
155 }
156 
157 void Canvas::skew(double sx, double sy) {
158  if (!canvas_) {
159  return;
160  }
161  canvas_->skew(sx, sy);
162 }
163 
164 void Canvas::transform(const tonic::Float64List& matrix4) {
165  if (!canvas_) {
166  return;
167  }
168  canvas_->concat(ToSkMatrix(matrix4));
169 }
170 
171 void Canvas::clipRect(double left,
172  double top,
173  double right,
174  double bottom,
175  SkClipOp clipOp,
176  bool doAntiAlias) {
177  if (!canvas_) {
178  return;
179  }
180  canvas_->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
181  doAntiAlias);
182 }
183 
184 void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) {
185  if (!canvas_) {
186  return;
187  }
188  canvas_->clipRRect(rrect.sk_rrect, doAntiAlias);
189 }
190 
191 void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) {
192  if (!canvas_) {
193  return;
194  }
195  if (!path) {
196  Dart_ThrowException(
197  ToDart("Canvas.clipPath called with non-genuine Path."));
198  return;
199  }
200  canvas_->clipPath(path->path(), doAntiAlias);
201 }
202 
203 void Canvas::drawColor(SkColor color, SkBlendMode blend_mode) {
204  if (!canvas_) {
205  return;
206  }
207  canvas_->drawColor(color, blend_mode);
208 }
209 
210 void Canvas::drawLine(double x1,
211  double y1,
212  double x2,
213  double y2,
214  const Paint& paint,
215  const PaintData& paint_data) {
216  if (!canvas_) {
217  return;
218  }
219  canvas_->drawLine(x1, y1, x2, y2, *paint.paint());
220 }
221 
222 void Canvas::drawPaint(const Paint& paint, const PaintData& paint_data) {
223  if (!canvas_) {
224  return;
225  }
226  canvas_->drawPaint(*paint.paint());
227 }
228 
229 void Canvas::drawRect(double left,
230  double top,
231  double right,
232  double bottom,
233  const Paint& paint,
234  const PaintData& paint_data) {
235  if (!canvas_) {
236  return;
237  }
238  canvas_->drawRect(SkRect::MakeLTRB(left, top, right, bottom), *paint.paint());
239 }
240 
241 void Canvas::drawRRect(const RRect& rrect,
242  const Paint& paint,
243  const PaintData& paint_data) {
244  if (!canvas_) {
245  return;
246  }
247  canvas_->drawRRect(rrect.sk_rrect, *paint.paint());
248 }
249 
250 void Canvas::drawDRRect(const RRect& outer,
251  const RRect& inner,
252  const Paint& paint,
253  const PaintData& paint_data) {
254  if (!canvas_) {
255  return;
256  }
257  canvas_->drawDRRect(outer.sk_rrect, inner.sk_rrect, *paint.paint());
258 }
259 
260 void Canvas::drawOval(double left,
261  double top,
262  double right,
263  double bottom,
264  const Paint& paint,
265  const PaintData& paint_data) {
266  if (!canvas_) {
267  return;
268  }
269  canvas_->drawOval(SkRect::MakeLTRB(left, top, right, bottom), *paint.paint());
270 }
271 
272 void Canvas::drawCircle(double x,
273  double y,
274  double radius,
275  const Paint& paint,
276  const PaintData& paint_data) {
277  if (!canvas_) {
278  return;
279  }
280  canvas_->drawCircle(x, y, radius, *paint.paint());
281 }
282 
283 void Canvas::drawArc(double left,
284  double top,
285  double right,
286  double bottom,
287  double startAngle,
288  double sweepAngle,
289  bool useCenter,
290  const Paint& paint,
291  const PaintData& paint_data) {
292  if (!canvas_) {
293  return;
294  }
295  canvas_->drawArc(SkRect::MakeLTRB(left, top, right, bottom),
296  startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
297  useCenter, *paint.paint());
298 }
299 
301  const Paint& paint,
302  const PaintData& paint_data) {
303  if (!canvas_) {
304  return;
305  }
306  if (!path) {
307  Dart_ThrowException(
308  ToDart("Canvas.drawPath called with non-genuine Path."));
309  return;
310  }
311  canvas_->drawPath(path->path(), *paint.paint());
312 }
313 
314 void Canvas::drawImage(const CanvasImage* image,
315  double x,
316  double y,
317  const Paint& paint,
318  const PaintData& paint_data) {
319  if (!canvas_) {
320  return;
321  }
322  if (!image) {
323  Dart_ThrowException(
324  ToDart("Canvas.drawImage called with non-genuine Image."));
325  return;
326  }
327  canvas_->drawImage(image->image(), x, y, paint.paint());
328 }
329 
331  double src_left,
332  double src_top,
333  double src_right,
334  double src_bottom,
335  double dst_left,
336  double dst_top,
337  double dst_right,
338  double dst_bottom,
339  const Paint& paint,
340  const PaintData& paint_data) {
341  if (!canvas_) {
342  return;
343  }
344  if (!image) {
345  Dart_ThrowException(
346  ToDart("Canvas.drawImageRect called with non-genuine Image."));
347  return;
348  }
349  SkRect src = SkRect::MakeLTRB(src_left, src_top, src_right, src_bottom);
350  SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
351  canvas_->drawImageRect(image->image(), src, dst, paint.paint(),
352  SkCanvas::kFast_SrcRectConstraint);
353 }
354 
356  double center_left,
357  double center_top,
358  double center_right,
359  double center_bottom,
360  double dst_left,
361  double dst_top,
362  double dst_right,
363  double dst_bottom,
364  const Paint& paint,
365  const PaintData& paint_data) {
366  if (!canvas_) {
367  return;
368  }
369  if (!image) {
370  Dart_ThrowException(
371  ToDart("Canvas.drawImageNine called with non-genuine Image."));
372  return;
373  }
374  SkRect center =
375  SkRect::MakeLTRB(center_left, center_top, center_right, center_bottom);
376  SkIRect icenter;
377  center.round(&icenter);
378  SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
379  canvas_->drawImageNine(image->image(), icenter, dst, paint.paint());
380 }
381 
382 void Canvas::drawPicture(Picture* picture) {
383  if (!canvas_) {
384  return;
385  }
386  if (!picture) {
387  Dart_ThrowException(
388  ToDart("Canvas.drawPicture called with non-genuine Picture."));
389  return;
390  }
391  canvas_->drawPicture(picture->picture().get());
392 }
393 
394 void Canvas::drawPoints(const Paint& paint,
395  const PaintData& paint_data,
396  SkCanvas::PointMode point_mode,
397  const tonic::Float32List& points) {
398  if (!canvas_) {
399  return;
400  }
401 
402  static_assert(sizeof(SkPoint) == sizeof(float) * 2,
403  "SkPoint doesn't use floats.");
404 
405  canvas_->drawPoints(point_mode,
406  points.num_elements() / 2, // SkPoints have two floats.
407  reinterpret_cast<const SkPoint*>(points.data()),
408  *paint.paint());
409 }
410 
411 void Canvas::drawVertices(const Vertices* vertices,
412  SkBlendMode blend_mode,
413  const Paint& paint,
414  const PaintData& paint_data) {
415  if (!canvas_) {
416  return;
417  }
418  if (!vertices) {
419  Dart_ThrowException(
420  ToDart("Canvas.drawVertices called with non-genuine Vertices."));
421  return;
422  }
423  canvas_->drawVertices(vertices->vertices(), blend_mode, *paint.paint());
424 }
425 
426 void Canvas::drawAtlas(const Paint& paint,
427  const PaintData& paint_data,
428  CanvasImage* atlas,
429  const tonic::Float32List& transforms,
430  const tonic::Float32List& rects,
431  const tonic::Int32List& colors,
432  SkBlendMode blend_mode,
433  const tonic::Float32List& cull_rect) {
434  if (!canvas_) {
435  return;
436  }
437  if (!atlas) {
438  Dart_ThrowException(
439  ToDart("Canvas.drawAtlas or Canvas.drawRawAtlas called with "
440  "non-genuine Image."));
441  return;
442  }
443 
444  sk_sp<SkImage> skImage = atlas->image();
445 
446  static_assert(sizeof(SkRSXform) == sizeof(float) * 4,
447  "SkRSXform doesn't use floats.");
448  static_assert(sizeof(SkRect) == sizeof(float) * 4,
449  "SkRect doesn't use floats.");
450 
451  canvas_->drawAtlas(
452  skImage.get(), reinterpret_cast<const SkRSXform*>(transforms.data()),
453  reinterpret_cast<const SkRect*>(rects.data()),
454  reinterpret_cast<const SkColor*>(colors.data()),
455  rects.num_elements() / 4, // SkRect have four floats.
456  blend_mode, reinterpret_cast<const SkRect*>(cull_rect.data()),
457  paint.paint());
458 }
459 
461  SkColor color,
462  double elevation,
463  bool transparentOccluder) {
464  if (!path) {
465  Dart_ThrowException(
466  ToDart("Canvas.drawShader called with non-genuine Path."));
467  return;
468  }
469  SkScalar dpr = UIDartState::Current()
471  ->get_window(0)
472  ->viewport_metrics()
474  flutter::PhysicalShapeLayer::DrawShadow(canvas_, path->path(), color,
475  elevation, transparentOccluder, dpr);
476 }
477 
479  canvas_ = nullptr;
480  if (dart_wrapper()) {
482  }
483 }
484 
485 } // namespace flutter
void saveLayer(double left, double top, double right, double bottom, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:109
G_BEGIN_DECLS FlValue * args
void drawColor(SkColor color, SkBlendMode blend_mode)
Definition: canvas.cc:203
SkRRect sk_rrect
Definition: rrect.h:16
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
void saveLayerWithoutBounds(const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:101
void skew(double sx, double sy)
Definition: canvas.cc:157
static fml::RefPtr< Canvas > Create(PictureRecorder *recorder, double left, double top, double right, double bottom)
Definition: canvas.cc:74
void drawPaint(const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:222
const sk_sp< SkVertices > & vertices() const
Definition: vertices.h:34
void drawPicture(Picture *picture)
Definition: canvas.cc:382
void drawRRect(const RRect &rrect, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:241
void DartCallConstructor(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:218
void transform(const tonic::Float64List &matrix4)
Definition: canvas.cc:164
void drawOval(double left, double top, double right, double bottom, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:260
SkCanvas * BeginRecording(SkRect bounds)
#define FOR_EACH_BINDING(V)
Definition: canvas.cc:34
void Invalidate()
Definition: canvas.cc:478
void drawLine(double x1, double y1, double x2, double y2, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:210
void drawPath(const CanvasPath *path, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:300
sk_sp< SkPicture > picture() const
Definition: picture.h:30
const SkPaint * paint() const
Definition: paint.h:18
#define DART_NATIVE_CALLBACK(CLASS, METHOD)
void clipRect(double left, double top, double right, double bottom, SkClipOp clipOp, bool doAntiAlias=true)
Definition: canvas.cc:171
void clipRRect(const RRect &rrect, bool doAntiAlias=true)
Definition: canvas.cc:184
void save()
Definition: canvas.cc:94
void drawImageNine(const CanvasImage *image, double center_left, double center_top, double center_right, double center_bottom, double dst_left, double dst_top, double dst_right, double dst_bottom, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:355
SkCanvas * canvas() const
Definition: canvas.h:167
void drawAtlas(const Paint &paint, const PaintData &paint_data, CanvasImage *atlas, const tonic::Float32List &transforms, const tonic::Float32List &rects, const tonic::Int32List &colors, SkBlendMode blend_mode, const tonic::Float32List &cull_rect)
Definition: canvas.cc:426
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
void scale(double sx, double sy)
Definition: canvas.cc:143
const SkPath & path() const
Definition: path.h:111
void rotate(double radians)
Definition: canvas.cc:150
void drawDRRect(const RRect &outer, const RRect &inner, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:250
static void ThrowIfUIOperationsProhibited()
PlatformConfiguration * platform_configuration() const
Definition: ui_dart_state.h:48
int getSaveCount()
Definition: canvas.cc:129
void drawCircle(double x, double y, double radius, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:272
void drawArc(double left, double top, double right, double bottom, double startAngle, double sweepAngle, bool useCenter, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:283
void drawImage(const CanvasImage *image, double x, double y, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:314
void restore()
Definition: canvas.cc:122
void clipPath(const CanvasPath *path, bool doAntiAlias=true)
Definition: canvas.cc:191
static void Canvas_constructor(Dart_NativeArguments args)
Definition: canvas.cc:27
~Canvas() override
Definition: canvas.cc:92
static void DrawShadow(SkCanvas *canvas, const SkPath &path, SkColor color, float elevation, bool transparentOccluder, SkScalar dpr)
#define DART_REGISTER_NATIVE(CLASS, METHOD)
Dart_Handle ToDart(const T &object)
void drawImageRect(const CanvasImage *image, double src_left, double src_top, double src_right, double src_bottom, double dst_left, double dst_top, double dst_right, double dst_bottom, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:330
void translate(double dx, double dy)
Definition: canvas.cc:136
SkMatrix ToSkMatrix(const tonic::Float64List &matrix4)
Definition: matrix.cc:20
Window * get_window(int window_id)
Retrieves the Window with the given ID managed by the PlatformConfiguration.
void drawRect(double left, double top, double right, double bottom, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:229
Dart_WeakPersistentHandle dart_wrapper() const
void drawShadow(const CanvasPath *path, SkColor color, double elevation, bool transparentOccluder)
Definition: canvas.cc:460
sk_sp< SkImage > image() const
Definition: image.h:37
const ViewportMetrics & viewport_metrics() const
Definition: window.h:27
void drawVertices(const Vertices *vertices, SkBlendMode blend_mode, const Paint &paint, const PaintData &paint_data)
Definition: canvas.cc:411
void drawPoints(const Paint &paint, const PaintData &paint_data, SkCanvas::PointMode point_mode, const tonic::Float32List &points)
Definition: canvas.cc:394
void set_canvas(fml::RefPtr< Canvas > canvas)
static UIDartState * Current()