| Flutter Impeller |

dl_dispatcher.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 "impeller/display_list/dl_dispatcher.h"
6
7 #include <algorithm>
8 #include <cstring>
9 #include <memory>
10 #include <optional>
11 #include <utility>
12 #include <vector>
13
14 #include "flutter/fml/logging.h"
15 #include "flutter/fml/trace_event.h"
16 #include "impeller/aiks/color_filter.h"
17 #include "impeller/core/formats.h"
18 #include "impeller/display_list/dl_vertices_geometry.h"
19 #include "impeller/display_list/nine_patch_converter.h"
20 #include "impeller/display_list/skia_conversions.h"
21 #include "impeller/entity/contents/filters/filter_contents.h"
22 #include "impeller/entity/contents/filters/inputs/filter_input.h"
23 #include "impeller/entity/contents/runtime_effect_contents.h"
24 #include "impeller/entity/entity.h"
25 #include "impeller/geometry/path.h"
26 #include "impeller/geometry/path_builder.h"
27 #include "impeller/geometry/scalar.h"
28 #include "impeller/geometry/sigma.h"
29
30 #if IMPELLER_ENABLE_3D
31 #include "impeller/entity/contents/scene_contents.h"
32 #endif // IMPELLER_ENABLE_3D
33
34 namespace impeller {
35
36 #define UNIMPLEMENTED \
37 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
38
39 DlDispatcher::DlDispatcher() = default;
40
41 DlDispatcher::DlDispatcher(Rect cull_rect) : canvas_(cull_rect) {}
42
43 DlDispatcher::DlDispatcher(IRect cull_rect) : canvas_(cull_rect) {}
44
45 DlDispatcher::~DlDispatcher() = default;
46
47 static BlendMode ToBlendMode(flutter::DlBlendMode mode) {
48 switch (mode) {
49 case flutter::DlBlendMode::kClear:
50 return BlendMode::kClear;
51 case flutter::DlBlendMode::kSrc:
52 return BlendMode::kSource;
53 case flutter::DlBlendMode::kDst:
54 return BlendMode::kDestination;
55 case flutter::DlBlendMode::kSrcOver:
56 return BlendMode::kSourceOver;
57 case flutter::DlBlendMode::kDstOver:
58 return BlendMode::kDestinationOver;
59 case flutter::DlBlendMode::kSrcIn:
60 return BlendMode::kSourceIn;
61 case flutter::DlBlendMode::kDstIn:
62 return BlendMode::kDestinationIn;
63 case flutter::DlBlendMode::kSrcOut:
64 return BlendMode::kSourceOut;
65 case flutter::DlBlendMode::kDstOut:
66 return BlendMode::kDestinationOut;
67 case flutter::DlBlendMode::kSrcATop:
68 return BlendMode::kSourceATop;
69 case flutter::DlBlendMode::kDstATop:
70 return BlendMode::kDestinationATop;
71 case flutter::DlBlendMode::kXor:
72 return BlendMode::kXor;
73 case flutter::DlBlendMode::kPlus:
74 return BlendMode::kPlus;
75 case flutter::DlBlendMode::kModulate:
76 return BlendMode::kModulate;
77 case flutter::DlBlendMode::kScreen:
78 return BlendMode::kScreen;
79 case flutter::DlBlendMode::kOverlay:
80 return BlendMode::kOverlay;
81 case flutter::DlBlendMode::kDarken:
82 return BlendMode::kDarken;
83 case flutter::DlBlendMode::kLighten:
84 return BlendMode::kLighten;
85 case flutter::DlBlendMode::kColorDodge:
86 return BlendMode::kColorDodge;
87 case flutter::DlBlendMode::kColorBurn:
88 return BlendMode::kColorBurn;
89 case flutter::DlBlendMode::kHardLight:
90 return BlendMode::kHardLight;
91 case flutter::DlBlendMode::kSoftLight:
92 return BlendMode::kSoftLight;
93 case flutter::DlBlendMode::kDifference:
94 return BlendMode::kDifference;
95 case flutter::DlBlendMode::kExclusion:
96 return BlendMode::kExclusion;
97 case flutter::DlBlendMode::kMultiply:
98 return BlendMode::kMultiply;
99 case flutter::DlBlendMode::kHue:
100 return BlendMode::kHue;
101 case flutter::DlBlendMode::kSaturation:
102 return BlendMode::kSaturation;
103 case flutter::DlBlendMode::kColor:
104 return BlendMode::kColor;
105 case flutter::DlBlendMode::kLuminosity:
106 return BlendMode::kLuminosity;
107 }
108 FML_UNREACHABLE();
109 }
110
111 static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) {
112 switch (tile_mode) {
113 case flutter::DlTileMode::kClamp:
114 return Entity::TileMode::kClamp;
115 case flutter::DlTileMode::kRepeat:
116 return Entity::TileMode::kRepeat;
117 case flutter::DlTileMode::kMirror:
118 return Entity::TileMode::kMirror;
119 case flutter::DlTileMode::kDecal:
120 return Entity::TileMode::kDecal;
121 }
122 }
123
124 static impeller::SamplerDescriptor ToSamplerDescriptor(
125 const flutter::DlImageSampling options) {
126 impeller::SamplerDescriptor desc;
127 switch (options) {
128 case flutter::DlImageSampling::kNearestNeighbor:
129 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
130 desc.label = "Nearest Sampler";
131 break;
132 case flutter::DlImageSampling::kLinear:
133 // Impeller doesn't support cubic sampling, but linear is closer to correct
134 // than nearest for this case.
135 case flutter::DlImageSampling::kCubic:
136 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
137 desc.label = "Linear Sampler";
138 break;
139 case flutter::DlImageSampling::kMipmapLinear:
140 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
141 desc.mip_filter = impeller::MipFilter::kLinear;
142 desc.label = "Mipmap Linear Sampler";
143 break;
144 }
145 return desc;
146 }
147
148 static impeller::SamplerDescriptor ToSamplerDescriptor(
149 const flutter::DlFilterMode options) {
150 impeller::SamplerDescriptor desc;
151 switch (options) {
152 case flutter::DlFilterMode::kNearest:
153 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
154 desc.label = "Nearest Sampler";
155 break;
156 case flutter::DlFilterMode::kLinear:
157 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
158 desc.label = "Linear Sampler";
159 break;
160 default:
161 break;
162 }
163 return desc;
164 }
165
166 static Matrix ToMatrix(const SkMatrix& m) {
167 return Matrix{
168 // clang-format off
169 m[0], m[3], 0, m[6],
170 m[1], m[4], 0, m[7],
171 0, 0, 1, 0,
172 m[2], m[5], 0, m[8],
173 // clang-format on
174 };
175 }
176
177 // |flutter::DlOpReceiver|
178 void DlDispatcher::setAntiAlias(bool aa) {
179 // Nothing to do because AA is implicit.
180 }
181
182 static Paint::Style ToStyle(flutter::DlDrawStyle style) {
183 switch (style) {
184 case flutter::DlDrawStyle::kFill:
185 return Paint::Style::kFill;
186 case flutter::DlDrawStyle::kStroke:
187 return Paint::Style::kStroke;
188 case flutter::DlDrawStyle::kStrokeAndFill:
189 UNIMPLEMENTED;
190 break;
191 }
192 return Paint::Style::kFill;
193 }
194
195 // |flutter::DlOpReceiver|
196 void DlDispatcher::setDrawStyle(flutter::DlDrawStyle style) {
197 paint_.style = ToStyle(style);
198 }
199
200 // |flutter::DlOpReceiver|
201 void DlDispatcher::setColor(flutter::DlColor color) {
202 paint_.color = {
203 color.getRedF(),
204 color.getGreenF(),
205 color.getBlueF(),
206 color.getAlphaF(),
207 };
208 }
209
210 // |flutter::DlOpReceiver|
211 void DlDispatcher::setStrokeWidth(SkScalar width) {
212 paint_.stroke_width = width;
213 }
214
215 // |flutter::DlOpReceiver|
216 void DlDispatcher::setStrokeMiter(SkScalar limit) {
217 paint_.stroke_miter = limit;
218 }
219
220 // |flutter::DlOpReceiver|
221 void DlDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
222 switch (cap) {
223 case flutter::DlStrokeCap::kButt:
224 paint_.stroke_cap = Cap::kButt;
225 break;
226 case flutter::DlStrokeCap::kRound:
227 paint_.stroke_cap = Cap::kRound;
228 break;
229 case flutter::DlStrokeCap::kSquare:
230 paint_.stroke_cap = Cap::kSquare;
231 break;
232 }
233 }
234
235 // |flutter::DlOpReceiver|
236 void DlDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
237 switch (join) {
238 case flutter::DlStrokeJoin::kMiter:
239 paint_.stroke_join = Join::kMiter;
240 break;
241 case flutter::DlStrokeJoin::kRound:
242 paint_.stroke_join = Join::kRound;
243 break;
244 case flutter::DlStrokeJoin::kBevel:
245 paint_.stroke_join = Join::kBevel;
246 break;
247 }
248 }
249
250 static std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
251 auto result = std::vector<Color>();
252 if (colors == nullptr) {
253 return result;
254 }
255 for (int i = 0; i < count; i++) {
256 result.push_back(skia_conversions::ToColor(colors[i]));
257 }
258 return result;
259 }
260
261 static std::optional<ColorSource::Type> ToColorSourceType(
262 flutter::DlColorSourceType type) {
263 switch (type) {
264 case flutter::DlColorSourceType::kColor:
265 return ColorSource::Type::kColor;
266 case flutter::DlColorSourceType::kImage:
267 return ColorSource::Type::kImage;
268 case flutter::DlColorSourceType::kLinearGradient:
269 return ColorSource::Type::kLinearGradient;
270 case flutter::DlColorSourceType::kRadialGradient:
271 return ColorSource::Type::kRadialGradient;
272 case flutter::DlColorSourceType::kConicalGradient:
273 return ColorSource::Type::kConicalGradient;
274 case flutter::DlColorSourceType::kSweepGradient:
275 return ColorSource::Type::kSweepGradient;
276 case flutter::DlColorSourceType::kRuntimeEffect:
277 return ColorSource::Type::kRuntimeEffect;
278 #ifdef IMPELLER_ENABLE_3D
279 case flutter::DlColorSourceType::kScene:
280 return ColorSource::Type::kScene;
281 #endif // IMPELLER_ENABLE_3D
282 }
283 }
284
285 // |flutter::DlOpReceiver|
286 void DlDispatcher::setColorSource(const flutter::DlColorSource* source) {
287 if (!source) {
288 paint_.color_source = ColorSource::MakeColor();
289 return;
290 }
291
292 std::optional<ColorSource::Type> type = ToColorSourceType(source->type());
293
294 if (!type.has_value()) {
295 FML_LOG(ERROR) << "Requested ColorSourceType::kUnknown";
296 paint_.color_source = ColorSource::MakeColor();
297 return;
298 }
299
300 switch (type.value()) {
301 case ColorSource::Type::kColor: {
302 const flutter::DlColorColorSource* color = source->asColor();
303
304 paint_.color_source = ColorSource::MakeColor();
305 setColor(color->color());
306 FML_DCHECK(color);
307 return;
308 }
309 case ColorSource::Type::kLinearGradient: {
310 const flutter::DlLinearGradientColorSource* linear =
311 source->asLinearGradient();
312 FML_DCHECK(linear);
313 auto start_point = skia_conversions::ToPoint(linear->start_point());
314 auto end_point = skia_conversions::ToPoint(linear->end_point());
315 std::vector<Color> colors;
316 std::vector<float> stops;
317 skia_conversions::ConvertStops(linear, colors, stops);
318
319 auto tile_mode = ToTileMode(linear->tile_mode());
320 auto matrix = ToMatrix(linear->matrix());
321
322 paint_.color_source = ColorSource::MakeLinearGradient(
323 start_point, end_point, std::move(colors), std::move(stops),
324 tile_mode, matrix);
325 return;
326 }
327 case ColorSource::Type::kConicalGradient: {
328 const flutter::DlConicalGradientColorSource* conical_gradient =
329 source->asConicalGradient();
330 FML_DCHECK(conical_gradient);
331 Point center = skia_conversions::ToPoint(conical_gradient->end_center());
332 SkScalar radius = conical_gradient->end_radius();
333 Point focus_center =
334 skia_conversions::ToPoint(conical_gradient->start_center());
335 SkScalar focus_radius = conical_gradient->start_radius();
336 std::vector<Color> colors;
337 std::vector<float> stops;
338 skia_conversions::ConvertStops(conical_gradient, colors, stops);
339
340 auto tile_mode = ToTileMode(conical_gradient->tile_mode());
341 auto matrix = ToMatrix(conical_gradient->matrix());
342
343 paint_.color_source = ColorSource::MakeConicalGradient(
344 center, radius, std::move(colors), std::move(stops), focus_center,
345 focus_radius, tile_mode, matrix);
346 return;
347 }
348 case ColorSource::Type::kRadialGradient: {
349 const flutter::DlRadialGradientColorSource* radialGradient =
350 source->asRadialGradient();
351 FML_DCHECK(radialGradient);
352 auto center = skia_conversions::ToPoint(radialGradient->center());
353 auto radius = radialGradient->radius();
354 std::vector<Color> colors;
355 std::vector<float> stops;
356 skia_conversions::ConvertStops(radialGradient, colors, stops);
357
358 auto tile_mode = ToTileMode(radialGradient->tile_mode());
359 auto matrix = ToMatrix(radialGradient->matrix());
360 paint_.color_source =
361 ColorSource::MakeRadialGradient(center, radius, std::move(colors),
362 std::move(stops), tile_mode, matrix);
363 return;
364 }
365 case ColorSource::Type::kSweepGradient: {
366 const flutter::DlSweepGradientColorSource* sweepGradient =
367 source->asSweepGradient();
368 FML_DCHECK(sweepGradient);
369
370 auto center = skia_conversions::ToPoint(sweepGradient->center());
371 auto start_angle = Degrees(sweepGradient->start());
372 auto end_angle = Degrees(sweepGradient->end());
373 std::vector<Color> colors;
374 std::vector<float> stops;
375 skia_conversions::ConvertStops(sweepGradient, colors, stops);
376
377 auto tile_mode = ToTileMode(sweepGradient->tile_mode());
378 auto matrix = ToMatrix(sweepGradient->matrix());
379 paint_.color_source = ColorSource::MakeSweepGradient(
380 center, start_angle, end_angle, std::move(colors), std::move(stops),
381 tile_mode, matrix);
382 return;
383 }
384 case ColorSource::Type::kImage: {
385 const flutter::DlImageColorSource* image_color_source = source->asImage();
386 FML_DCHECK(image_color_source &&
387 image_color_source->image()->impeller_texture());
388 auto texture = image_color_source->image()->impeller_texture();
389 auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode());
390 auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode());
391 auto desc = ToSamplerDescriptor(image_color_source->sampling());
392 auto matrix = ToMatrix(image_color_source->matrix());
393 paint_.color_source = ColorSource::MakeImage(texture, x_tile_mode,
394 y_tile_mode, desc, matrix);
395 return;
396 }
397 case ColorSource::Type::kRuntimeEffect: {
398 const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
399 source->asRuntimeEffect();
400 auto runtime_stage =
401 runtime_effect_color_source->runtime_effect()->runtime_stage();
402 auto uniform_data = runtime_effect_color_source->uniform_data();
403 auto samplers = runtime_effect_color_source->samplers();
404
405 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
406
407 for (auto& sampler : samplers) {
408 if (sampler == nullptr) {
409 return;
410 }
411 auto* image = sampler->asImage();
412 if (!sampler->asImage()) {
413 UNIMPLEMENTED;
414 return;
415 }
416 FML_DCHECK(image->image()->impeller_texture());
417 texture_inputs.push_back({
418 .sampler_descriptor = ToSamplerDescriptor(image->sampling()),
419 .texture = image->image()->impeller_texture(),
420 });
421 }
422
423 paint_.color_source = ColorSource::MakeRuntimeEffect(
424 runtime_stage, uniform_data, texture_inputs);
425 return;
426 }
427 case ColorSource::Type::kScene: {
428 #ifdef IMPELLER_ENABLE_3D
429 const flutter::DlSceneColorSource* scene_color_source = source->asScene();
430 std::shared_ptr<scene::Node> scene_node =
431 scene_color_source->scene_node();
432 Matrix camera_transform = scene_color_source->camera_matrix();
433
434 paint_.color_source =
435 ColorSource::MakeScene(scene_node, camera_transform);
436 #else // IMPELLER_ENABLE_3D
437 FML_LOG(ERROR) << "ColorSourceType::kScene can only be used if Impeller "
438 "Scene is enabled.";
439 #endif // IMPELLER_ENABLE_3D
440 return;
441 }
442 }
443 }
444
445 static std::shared_ptr<ColorFilter> ToColorFilter(
446 const flutter::DlColorFilter* filter) {
447 if (filter == nullptr) {
448 return nullptr;
449 }
450 switch (filter->type()) {
451 case flutter::DlColorFilterType::kBlend: {
452 auto dl_blend = filter->asBlend();
453 auto blend_mode = ToBlendMode(dl_blend->mode());
454 auto color = skia_conversions::ToColor(dl_blend->color());
455 return ColorFilter::MakeBlend(blend_mode, color);
456 }
457 case flutter::DlColorFilterType::kMatrix: {
458 const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
459 impeller::ColorMatrix color_matrix;
460 dl_matrix->get_matrix(color_matrix.array);
461 return ColorFilter::MakeMatrix(color_matrix);
462 }
463 case flutter::DlColorFilterType::kSrgbToLinearGamma:
464 return ColorFilter::MakeSrgbToLinear();
465 case flutter::DlColorFilterType::kLinearToSrgbGamma:
466 return ColorFilter::MakeLinearToSrgb();
467 }
468 return nullptr;
469 }
470
471 // |flutter::DlOpReceiver|
472 void DlDispatcher::setColorFilter(const flutter::DlColorFilter* filter) {
473 paint_.color_filter = ToColorFilter(filter);
474 }
475
476 // |flutter::DlOpReceiver|
477 void DlDispatcher::setInvertColors(bool invert) {
478 paint_.invert_colors = invert;
479 }
480
481 // |flutter::DlOpReceiver|
482 void DlDispatcher::setBlendMode(flutter::DlBlendMode dl_mode) {
483 paint_.blend_mode = ToBlendMode(dl_mode);
484 }
485
486 // |flutter::DlOpReceiver|
487 void DlDispatcher::setPathEffect(const flutter::DlPathEffect* effect) {
488 // Needs https://github.com/flutter/flutter/issues/95434
489 UNIMPLEMENTED;
490 }
491
492 static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style) {
493 switch (blur_style) {
494 case flutter::DlBlurStyle::kNormal:
495 return FilterContents::BlurStyle::kNormal;
496 case flutter::DlBlurStyle::kSolid:
497 return FilterContents::BlurStyle::kSolid;
498 case flutter::DlBlurStyle::kOuter:
499 return FilterContents::BlurStyle::kOuter;
500 case flutter::DlBlurStyle::kInner:
501 return FilterContents::BlurStyle::kInner;
502 }
503 }
504
505 // |flutter::DlOpReceiver|
506 void DlDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
507 // Needs https://github.com/flutter/flutter/issues/95434
508 if (filter == nullptr) {
509 paint_.mask_blur_descriptor = std::nullopt;
510 return;
511 }
512 switch (filter->type()) {
513 case flutter::DlMaskFilterType::kBlur: {
514 auto blur = filter->asBlur();
515
516 paint_.mask_blur_descriptor = {
517 .style = ToBlurStyle(blur->style()),
518 .sigma = Sigma(blur->sigma()),
519 };
520 break;
521 }
522 }
523 }
524
525 static std::shared_ptr<ImageFilter> ToImageFilter(
526 const flutter::DlImageFilter* filter) {
527 if (filter == nullptr) {
528 return nullptr;
529 }
530
531 switch (filter->type()) {
532 case flutter::DlImageFilterType::kBlur: {
533 auto blur = filter->asBlur();
534 auto sigma_x = Sigma(blur->sigma_x());
535 auto sigma_y = Sigma(blur->sigma_y());
536 auto tile_mode = ToTileMode(blur->tile_mode());
537 return ImageFilter::MakeBlur(
538 sigma_x, sigma_y, FilterContents::BlurStyle::kNormal, tile_mode);
539 }
540 case flutter::DlImageFilterType::kDilate: {
541 auto dilate = filter->asDilate();
542 FML_DCHECK(dilate);
543 if (dilate->radius_x() < 0 || dilate->radius_y() < 0) {
544 return nullptr;
545 }
546 auto radius_x = Radius(dilate->radius_x());
547 auto radius_y = Radius(dilate->radius_y());
548 return ImageFilter::MakeDilate(radius_x, radius_y);
549 }
550 case flutter::DlImageFilterType::kErode: {
551 auto erode = filter->asErode();
552 FML_DCHECK(erode);
553 if (erode->radius_x() < 0 || erode->radius_y() < 0) {
554 return nullptr;
555 }
556 auto radius_x = Radius(erode->radius_x());
557 auto radius_y = Radius(erode->radius_y());
558 return ImageFilter::MakeErode(radius_x, radius_y);
559 }
560 case flutter::DlImageFilterType::kMatrix: {
561 auto matrix_filter = filter->asMatrix();
562 FML_DCHECK(matrix_filter);
563 auto matrix = ToMatrix(matrix_filter->matrix());
564 auto desc = ToSamplerDescriptor(matrix_filter->sampling());
565 return ImageFilter::MakeMatrix(matrix, desc);
566 }
567 case flutter::DlImageFilterType::kCompose: {
568 auto compose = filter->asCompose();
569 FML_DCHECK(compose);
570 auto outer_dl_filter = compose->outer();
571 auto inner_dl_filter = compose->inner();
572 auto outer_filter = ToImageFilter(outer_dl_filter.get());
573 auto inner_filter = ToImageFilter(inner_dl_filter.get());
574 if (!outer_filter) {
575 return inner_filter;
576 }
577 if (!inner_filter) {
578 return outer_filter;
579 }
580 FML_DCHECK(outer_filter && inner_filter);
581
582 return ImageFilter::MakeCompose(*inner_filter, *outer_filter);
583 }
584 case flutter::DlImageFilterType::kColorFilter: {
585 auto color_filter_image_filter = filter->asColorFilter();
586 FML_DCHECK(color_filter_image_filter);
587 auto color_filter =
588 ToColorFilter(color_filter_image_filter->color_filter().get());
589 if (!color_filter) {
590 return nullptr;
591 }
592 // When color filters are used as image filters, set the color filter's
593 // "absorb opacity" flag to false. For image filters, the snapshot
594 // opacity needs to be deferred until the result of the filter chain is
595 // being blended with the layer.
596 return ImageFilter::MakeFromColorFilter(*color_filter);
597 }
598 case flutter::DlImageFilterType::kLocalMatrix: {
599 auto local_matrix_filter = filter->asLocalMatrix();
600 FML_DCHECK(local_matrix_filter);
601 auto internal_filter = local_matrix_filter->image_filter();
602 FML_DCHECK(internal_filter);
603
604 auto image_filter = ToImageFilter(internal_filter.get());
605 if (!image_filter) {
606 return nullptr;
607 }
608
609 auto matrix = ToMatrix(local_matrix_filter->matrix());
610 return ImageFilter::MakeLocalMatrix(matrix, *image_filter);
611 }
612 }
613 }
614
615 // |flutter::DlOpReceiver|
616 void DlDispatcher::setImageFilter(const flutter::DlImageFilter* filter) {
617 paint_.image_filter = ToImageFilter(filter);
618 }
619
620 // |flutter::DlOpReceiver|
621 void DlDispatcher::save() {
622 canvas_.Save();
623 }
624
625 // |flutter::DlOpReceiver|
626 void DlDispatcher::saveLayer(const SkRect* bounds,
627 const flutter::SaveLayerOptions options,
628 const flutter::DlImageFilter* backdrop) {
629 auto paint = options.renders_with_attributes() ? paint_ : Paint{};
630 canvas_.SaveLayer(paint, skia_conversions::ToRect(bounds),
631 ToImageFilter(backdrop));
632 }
633
634 // |flutter::DlOpReceiver|
635 void DlDispatcher::restore() {
636 canvas_.Restore();
637 }
638
639 // |flutter::DlOpReceiver|
640 void DlDispatcher::translate(SkScalar tx, SkScalar ty) {
641 canvas_.Translate({tx, ty, 0.0});
642 }
643
644 // |flutter::DlOpReceiver|
645 void DlDispatcher::scale(SkScalar sx, SkScalar sy) {
646 canvas_.Scale({sx, sy, 1.0});
647 }
648
649 // |flutter::DlOpReceiver|
650 void DlDispatcher::rotate(SkScalar degrees) {
651 canvas_.Rotate(Degrees{degrees});
652 }
653
654 // |flutter::DlOpReceiver|
655 void DlDispatcher::skew(SkScalar sx, SkScalar sy) {
656 canvas_.Skew(sx, sy);
657 }
658
659 // |flutter::DlOpReceiver|
660 void DlDispatcher::transform2DAffine(SkScalar mxx,
661 SkScalar mxy,
662 SkScalar mxt,
663 SkScalar myx,
664 SkScalar myy,
665 SkScalar myt) {
666 // clang-format off
667 transformFullPerspective(
668 mxx, mxy, 0, mxt,
669 myx, myy, 0, myt,
670 0 , 0, 1, 0,
671 0 , 0, 0, 1
672 );
673 // clang-format on
674 }
675
676 // |flutter::DlOpReceiver|
677 void DlDispatcher::transformFullPerspective(SkScalar mxx,
678 SkScalar mxy,
679 SkScalar mxz,
680 SkScalar mxt,
681 SkScalar myx,
682 SkScalar myy,
683 SkScalar myz,
684 SkScalar myt,
685 SkScalar mzx,
686 SkScalar mzy,
687 SkScalar mzz,
688 SkScalar mzt,
689 SkScalar mwx,
690 SkScalar mwy,
691 SkScalar mwz,
692 SkScalar mwt) {
693 // The order of arguments is row-major but Impeller matrices are
694 // column-major.
695 // clang-format off
696 auto transform = Matrix{
697 mxx, myx, mzx, mwx,
698 mxy, myy, mzy, mwy,
699 mxz, myz, mzz, mwz,
700 mxt, myt, mzt, mwt
701 };
702 // clang-format on
703 canvas_.Transform(transform);
704 }
705
706 // |flutter::DlOpReceiver|
707 void DlDispatcher::transformReset() {
708 canvas_.ResetTransform();
709 canvas_.Transform(initial_matrix_);
710 }
711
712 static Entity::ClipOperation ToClipOperation(
713 flutter::DlCanvas::ClipOp clip_op) {
714 switch (clip_op) {
715 case flutter::DlCanvas::ClipOp::kDifference:
716 return Entity::ClipOperation::kDifference;
717 case flutter::DlCanvas::ClipOp::kIntersect:
718 return Entity::ClipOperation::kIntersect;
719 }
720 }
721
722 // |flutter::DlOpReceiver|
723 void DlDispatcher::clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) {
724 canvas_.ClipRect(skia_conversions::ToRect(rect), ToClipOperation(clip_op));
725 }
726
727 // |flutter::DlOpReceiver|
728 void DlDispatcher::clipRRect(const SkRRect& rrect, ClipOp sk_op, bool is_aa) {
729 auto clip_op = ToClipOperation(sk_op);
730 if (rrect.isRect()) {
731 canvas_.ClipRect(skia_conversions::ToRect(rrect.rect()), clip_op);
732 } else if (rrect.isOval()) {
733 canvas_.ClipOval(skia_conversions::ToRect(rrect.rect()), clip_op);
734 } else if (rrect.isSimple()) {
735 canvas_.ClipRRect(skia_conversions::ToRect(rrect.rect()),
736 skia_conversions::ToSize(rrect.getSimpleRadii()),
737 clip_op);
738 } else {
739 canvas_.ClipPath(skia_conversions::ToPath(rrect), clip_op);
740 }
741 }
742
743 // |flutter::DlOpReceiver|
744 void DlDispatcher::clipPath(const SkPath& path, ClipOp sk_op, bool is_aa) {
745 auto clip_op = ToClipOperation(sk_op);
746
747 SkRect rect;
748 if (path.isRect(&rect)) {
749 canvas_.ClipRect(skia_conversions::ToRect(rect), clip_op);
750 } else if (path.isOval(&rect)) {
751 canvas_.ClipOval(skia_conversions::ToRect(rect), clip_op);
752 } else {
753 SkRRect rrect;
754 if (path.isRRect(&rrect) && rrect.isSimple()) {
755 canvas_.ClipRRect(skia_conversions::ToRect(rrect.rect()),
756 skia_conversions::ToSize(rrect.getSimpleRadii()),
757 clip_op);
758 } else {
759 canvas_.ClipPath(skia_conversions::ToPath(path), clip_op);
760 }
761 }
762 }
763
764 // |flutter::DlOpReceiver|
765 void DlDispatcher::drawColor(flutter::DlColor color,
766 flutter::DlBlendMode dl_mode) {
767 Paint paint;
768 paint.color = skia_conversions::ToColor(color);
769 paint.blend_mode = ToBlendMode(dl_mode);
770 canvas_.DrawPaint(paint);
771 }
772
773 // |flutter::DlOpReceiver|
774 void DlDispatcher::drawPaint() {
775 canvas_.DrawPaint(paint_);
776 }
777
778 // |flutter::DlOpReceiver|
779 void DlDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
780 canvas_.DrawLine(skia_conversions::ToPoint(p0), skia_conversions::ToPoint(p1),
781 paint_);
782 }
783
784 // |flutter::DlOpReceiver|
785 void DlDispatcher::drawRect(const SkRect& rect) {
786 canvas_.DrawRect(skia_conversions::ToRect(rect), paint_);
787 }
788
789 // |flutter::DlOpReceiver|
790 void DlDispatcher::drawOval(const SkRect& bounds) {
791 canvas_.DrawOval(skia_conversions::ToRect(bounds), paint_);
792 }
793
794 // |flutter::DlOpReceiver|
795 void DlDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
796 canvas_.DrawCircle(skia_conversions::ToPoint(center), radius, paint_);
797 }
798
799 // |flutter::DlOpReceiver|
800 void DlDispatcher::drawRRect(const SkRRect& rrect) {
801 if (rrect.isSimple()) {
802 canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
803 skia_conversions::ToSize(rrect.getSimpleRadii()), paint_);
804 } else {
805 canvas_.DrawPath(skia_conversions::ToPath(rrect), paint_);
806 }
807 }
808
809 // |flutter::DlOpReceiver|
810 void DlDispatcher::drawDRRect(const SkRRect& outer, const SkRRect& inner) {
811 PathBuilder builder;
812 builder.AddPath(skia_conversions::ToPath(outer));
813 builder.AddPath(skia_conversions::ToPath(inner));
814 canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_);
815 }
816
817 // |flutter::DlOpReceiver|
818 void DlDispatcher::drawPath(const SkPath& path) {
819 SimplifyOrDrawPath(canvas_, path, paint_);
820 }
821
822 void DlDispatcher::SimplifyOrDrawPath(CanvasType& canvas,
823 const SkPath& path,
824 const Paint& paint) {
825 SkRect rect;
826
827 // We can't "optimize" a path into a rectangle if it's open.
828 bool closed;
829 if (path.isRect(&rect, &closed) && closed) {
830 canvas.DrawRect(skia_conversions::ToRect(rect), paint);
831 return;
832 }
833
834 SkRRect rrect;
835 if (path.isRRect(&rrect) && rrect.isSimple()) {
836 canvas.DrawRRect(skia_conversions::ToRect(rrect.rect()),
837 skia_conversions::ToSize(rrect.getSimpleRadii()), paint);
838 return;
839 }
840
841 SkRect oval;
842 if (path.isOval(&oval)) {
843 canvas.DrawOval(skia_conversions::ToRect(oval), paint);
844 return;
845 }
846
847 canvas.DrawPath(skia_conversions::ToPath(path), paint);
848 }
849
850 // |flutter::DlOpReceiver|
851 void DlDispatcher::drawArc(const SkRect& oval_bounds,
852 SkScalar start_degrees,
853 SkScalar sweep_degrees,
854 bool use_center) {
855 PathBuilder builder;
856 builder.AddArc(skia_conversions::ToRect(oval_bounds), Degrees(start_degrees),
857 Degrees(sweep_degrees), use_center);
858 canvas_.DrawPath(builder.TakePath(), paint_);
859 }
860
861 // |flutter::DlOpReceiver|
862 void DlDispatcher::drawPoints(PointMode mode,
863 uint32_t count,
864 const SkPoint points[]) {
865 Paint paint = paint_;
866 paint.style = Paint::Style::kStroke;
867 switch (mode) {
868 case flutter::DlCanvas::PointMode::kPoints: {
869 // Cap::kButt is also treated as a square.
870 auto point_style = paint.stroke_cap == Cap::kRound ? PointStyle::kRound
871 : PointStyle::kSquare;
872 auto radius = paint.stroke_width;
873 if (radius > 0) {
874 radius /= 2.0;
875 }
876 canvas_.DrawPoints(skia_conversions::ToPoints(points, count), radius,
877 paint, point_style);
878 } break;
879 case flutter::DlCanvas::PointMode::kLines:
880 for (uint32_t i = 1; i < count; i += 2) {
881 Point p0 = skia_conversions::ToPoint(points[i - 1]);
882 Point p1 = skia_conversions::ToPoint(points[i]);
883 canvas_.DrawLine(p0, p1, paint);
884 }
885 break;
886 case flutter::DlCanvas::PointMode::kPolygon:
887 if (count > 1) {
888 Point p0 = skia_conversions::ToPoint(points[0]);
889 for (uint32_t i = 1; i < count; i++) {
890 Point p1 = skia_conversions::ToPoint(points[i]);
891 canvas_.DrawLine(p0, p1, paint);
892 p0 = p1;
893 }
894 }
895 break;
896 }
897 }
898
899 // |flutter::DlOpReceiver|
900 void DlDispatcher::drawVertices(const flutter::DlVertices* vertices,
901 flutter::DlBlendMode dl_mode) {
902 canvas_.DrawVertices(MakeVertices(vertices), ToBlendMode(dl_mode), paint_);
903 }
904
905 // |flutter::DlOpReceiver|
906 void DlDispatcher::drawImage(const sk_sp<flutter::DlImage> image,
907 const SkPoint point,
908 flutter::DlImageSampling sampling,
909 bool render_with_attributes) {
910 if (!image) {
911 return;
912 }
913
914 auto texture = image->impeller_texture();
915 if (!texture) {
916 return;
917 }
918
919 const auto size = texture->GetSize();
920 const auto src = SkRect::MakeWH(size.width, size.height);
921 const auto dest =
922 SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);
923
924 drawImageRect(image, // image
925 src, // source rect
926 dest, // destination rect
927 sampling, // sampling options
928 render_with_attributes, // render with attributes
929 SrcRectConstraint::kStrict // constraint
930 );
931 }
932
933 // |flutter::DlOpReceiver|
934 void DlDispatcher::drawImageRect(
935 const sk_sp<flutter::DlImage> image,
936 const SkRect& src,
937 const SkRect& dst,
938 flutter::DlImageSampling sampling,
939 bool render_with_attributes,
940 SrcRectConstraint constraint = SrcRectConstraint::kFast) {
941 canvas_.DrawImageRect(
942 std::make_shared<Image>(image->impeller_texture()), // image
943 skia_conversions::ToRect(src), // source rect
944 skia_conversions::ToRect(dst), // destination rect
945 render_with_attributes ? paint_ : Paint(), // paint
946 ToSamplerDescriptor(sampling) // sampling
947 );
948 }
949
950 // |flutter::DlOpReceiver|
951 void DlDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
952 const SkIRect& center,
953 const SkRect& dst,
954 flutter::DlFilterMode filter,
955 bool render_with_attributes) {
956 NinePatchConverter converter = {};
957 converter.DrawNinePatch(
958 std::make_shared<Image>(image->impeller_texture()),
959 Rect::MakeLTRB(center.fLeft, center.fTop, center.fRight, center.fBottom),
960 skia_conversions::ToRect(dst), ToSamplerDescriptor(filter), &canvas_,
961 &paint_);
962 }
963
964 // |flutter::DlOpReceiver|
965 void DlDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
966 const SkRSXform xform[],
967 const SkRect tex[],
968 const flutter::DlColor colors[],
969 int count,
970 flutter::DlBlendMode mode,
971 flutter::DlImageSampling sampling,
972 const SkRect* cull_rect,
973 bool render_with_attributes) {
974 canvas_.DrawAtlas(std::make_shared<Image>(atlas->impeller_texture()),
975 skia_conversions::ToRSXForms(xform, count),
976 skia_conversions::ToRects(tex, count),
977 ToColors(colors, count), ToBlendMode(mode),
978 ToSamplerDescriptor(sampling),
979 skia_conversions::ToRect(cull_rect), paint_);
980 }
981
982 // |flutter::DlOpReceiver|
983 void DlDispatcher::drawDisplayList(
984 const sk_sp<flutter::DisplayList> display_list,
985 SkScalar opacity) {
986 // Save all values that must remain untouched after the operation.
987 Paint saved_paint = paint_;
988 Matrix saved_initial_matrix = initial_matrix_;
989 int restore_count = canvas_.GetSaveCount();
990
991 // The display list may alter the clip, which must be restored to the current
992 // clip at the end of playback.
993 canvas_.Save();
994
995 // Establish a new baseline for interpreting the new DL.
996 // Matrix and clip are left untouched, the current
997 // transform is saved as the new base matrix, and paint
998 // values are reset to defaults.
999 initial_matrix_ = canvas_.GetCurrentTransform();
1000 paint_ = Paint();
1001
1002 // Handle passed opacity in the most brute-force way by using
1003 // a SaveLayer. If the display_list is able to inherit the
1004 // opacity, this could also be handled by modulating all of its
1005 // attribute settings (for example, color), by the indicated
1006 // opacity.
1007 if (opacity < SK_Scalar1) {
1008 Paint save_paint;
1009 save_paint.color = Color(0, 0, 0, opacity);
1010 canvas_.SaveLayer(save_paint);
1011 }
1012
1013 // TODO(131445): Remove this restriction if we can correctly cull with
1014 // perspective transforms.
1015 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
1016 // The canvas remembers the screen-space culling bounds clipped by
1017 // the surface and the history of clip calls. DisplayList can cull
1018 // the ops based on a rectangle expressed in its "destination bounds"
1019 // so we need the canvas to transform those into the current local
1020 // coordinate space into which the DisplayList will be rendered.
1021 auto cull_bounds = canvas_.GetCurrentLocalCullingBounds();
1022 if (cull_bounds.has_value()) {
1023 Rect cull_rect = cull_bounds.value();
1024 display_list->Dispatch(
1025 *this, SkRect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
1026 cull_rect.GetRight(), cull_rect.GetBottom()));
1027 } else {
1028 display_list->Dispatch(*this);
1029 }
1030 } else {
1031 display_list->Dispatch(*this);
1032 }
1033
1034 // Restore all saved state back to what it was before we interpreted
1035 // the display_list
1036 canvas_.RestoreToCount(restore_count);
1037 initial_matrix_ = saved_initial_matrix;
1038 paint_ = saved_paint;
1039 }
1040
1041 // |flutter::DlOpReceiver|
1042 void DlDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
1043 SkScalar x,
1044 SkScalar y) {
1045 // When running with Impeller enabled Skia text blobs are converted to
1046 // Impeller text frames in paragraph_skia.cc
1047 UNIMPLEMENTED;
1048 }
1049
1050 void DlDispatcher::drawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
1051 SkScalar x,
1052 SkScalar y) {
1053 canvas_.DrawTextFrame(text_frame, //
1054 impeller::Point{x, y}, //
1055 paint_ //
1056 );
1057 }
1058
1059 // |flutter::DlOpReceiver|
1060 void DlDispatcher::drawShadow(const SkPath& path,
1061 const flutter::DlColor color,
1062 const SkScalar elevation,
1063 bool transparent_occluder,
1064 SkScalar dpr) {
1065 Color spot_color = skia_conversions::ToColor(color);
1066 spot_color.alpha *= 0.25;
1067
1068 // Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
1069 {
1070 Scalar max =
1071 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
1072 Scalar min =
1073 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
1074 Scalar luminance = (min + max) * 0.5;
1075
1076 Scalar alpha_adjust =
1077 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
1078 spot_color.alpha;
1079 Scalar color_alpha =
1080 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
1081 luminance;
1082 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
1083
1084 Scalar greyscale_alpha =
1085 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
1086
1087 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
1088 Scalar tonal_alpha = color_scale + greyscale_alpha;
1089 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
1090 spot_color = Color(unpremul_scale * spot_color.red,
1091 unpremul_scale * spot_color.green,
1092 unpremul_scale * spot_color.blue, tonal_alpha);
1093 }
1094
1095 Vector3 light_position(0, -1, 1);
1096 Scalar occluder_z = dpr * elevation;
1097
1098 constexpr Scalar kLightRadius = 800 / 600; // Light radius / light height
1099
1100 Paint paint;
1101 paint.style = Paint::Style::kFill;
1102 paint.color = spot_color;
1103 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1104 .style = FilterContents::BlurStyle::kNormal,
1105 .sigma = Radius{kLightRadius * occluder_z /
1106 canvas_.GetCurrentTransform().GetScale().y},
1107 };
1108
1109 canvas_.Save();
1110 canvas_.PreConcat(
1111 Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
1112
1113 SimplifyOrDrawPath(canvas_, path, paint);
1114
1115 canvas_.Restore();
1116 }
1117
1118 Picture DlDispatcher::EndRecordingAsPicture() {
1119 TRACE_EVENT0("impeller", "DisplayListDispatcher::EndRecordingAsPicture");
1120 return canvas_.EndRecordingAsPicture();
1121 }
1122
1123 } // namespace impeller
impeller::DlDispatcher::setBlendMode
void setBlendMode(flutter::DlBlendMode mode) override
Definition: dl_dispatcher.cc:482
impeller::DlDispatcher::drawTextBlob
void drawTextBlob(const sk_sp< SkTextBlob > blob, SkScalar x, SkScalar y) override
Definition: dl_dispatcher.cc:1042
impeller::Paint::stroke_cap
Cap stroke_cap
Definition: paint.h:56
impeller::Matrix::HasPerspective
constexpr bool HasPerspective() const
Definition: matrix.h:318
impeller::Canvas::DrawPoints
void DrawPoints(std::vector< Point > points, Scalar radius, const Paint &paint, PointStyle point_style)
Definition: canvas.cc:563
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
path.h
impeller::Entity::TileMode::kClamp
@ kClamp
impeller::Canvas::EndRecordingAsPicture
Picture EndRecordingAsPicture()
Definition: canvas.cc:657
impeller::Canvas::ClipOval
void ClipOval(const Rect &bounds, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:450
impeller::ColorSource::Type::kScene
@ kScene
impeller::DlDispatcher::save
void save() override
Definition: dl_dispatcher.cc:621
impeller::ColorSource::Type::kLinearGradient
@ kLinearGradient
impeller::DlDispatcher::drawOval
void drawOval(const SkRect &bounds) override
Definition: dl_dispatcher.cc:790
impeller::ToClipOperation
static Entity::ClipOperation ToClipOperation(flutter::DlCanvas::ClipOp clip_op)
Definition: dl_dispatcher.cc:712
impeller::Cap::kRound
@ kRound
impeller::Cap::kSquare
@ kSquare
impeller::BlendMode::kDestinationATop
@ kDestinationATop
impeller::DlDispatcher::DlDispatcher
DlDispatcher()
impeller::Canvas::DrawRRect
void DrawRRect(const Rect &rect, const Size &corner_radii, const Paint &paint)
Definition: canvas.cc:368
impeller::DlDispatcher::drawImageRect
void drawImageRect(const sk_sp< flutter::DlImage > image, const SkRect &src, const SkRect &dst, flutter::DlImageSampling sampling, bool render_with_attributes, SrcRectConstraint constraint) override
Definition: dl_dispatcher.cc:934
impeller::DlDispatcher::scale
void scale(SkScalar sx, SkScalar sy) override
Definition: dl_dispatcher.cc:645
impeller::DlDispatcher::saveLayer
void saveLayer(const SkRect *bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter *backdrop) override
Definition: dl_dispatcher.cc:626
impeller::ImageFilter::MakeDilate
static std::shared_ptr< ImageFilter > MakeDilate(Radius radius_x, Radius radius_y)
Definition: image_filter.cc:29
impeller::skia_conversions::ToPoints
std::vector< Point > ToPoints(const SkPoint points[], int count)
Definition: skia_conversions.cc:31
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Canvas::RestoreToCount
void RestoreToCount(size_t count)
Definition: canvas.cc:242
impeller::Canvas::DrawPath
void DrawPath(Path path, const Paint &paint)
Definition: canvas.cc:250
impeller::ColorSource::Type::kRadialGradient
@ kRadialGradient
impeller::Paint::Style::kStroke
@ kStroke
impeller::skia_conversions::ConvertStops
void ConvertStops(const flutter::DlGradientColorSourceBase *gradient, std::vector< Color > &colors, std::vector< float > &stops)
Convert display list colors + stops into impeller colors and stops, taking care to ensure that the st...
Definition: skia_conversions.cc:198
entity.h
impeller::ColorSource::MakeLinearGradient
static ColorSource MakeLinearGradient(Point start_point, Point end_point, std::vector< Color > colors, std::vector< Scalar > stops, Entity::TileMode tile_mode, Matrix effect_transform)
Definition: color_source.cc:45
impeller::Paint
Definition: paint.h:22
impeller::FillType::kOdd
@ kOdd
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:144
impeller::DlDispatcher::drawRRect
void drawRRect(const SkRRect &rrect) override
Definition: dl_dispatcher.cc:800
impeller::Canvas::Skew
void Skew(Scalar sx, Scalar sy)
Definition: canvas.cc:230
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::FilterContents::BlurStyle
BlurStyle
Definition: filter_contents.h:23
impeller::Color
Definition: color.h:124
impeller::DlDispatcher::clipRRect
void clipRRect(const SkRRect &rrect, ClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:728
impeller::ToImageFilter
static std::shared_ptr< ImageFilter > ToImageFilter(const flutter::DlImageFilter *filter)
Definition: dl_dispatcher.cc:525
impeller::NinePatchConverter::DrawNinePatch
void DrawNinePatch(const std::shared_ptr< Image > &image, Rect center, Rect dst, const SamplerDescriptor &sampler, CanvasType *canvas, Paint *paint)
Definition: nine_patch_converter.cc:60
impeller::BlendMode::kLuminosity
@ kLuminosity
impeller::Paint::color
Color color
Definition: paint.h:51
impeller::Entity::TileMode::kDecal
@ kDecal
impeller::BlendMode::kSource
@ kSource
impeller::DlDispatcher::drawArc
void drawArc(const SkRect &oval_bounds, SkScalar start_degrees, SkScalar sweep_degrees, bool use_center) override
Definition: dl_dispatcher.cc:851
impeller::BlendMode::kColorDodge
@ kColorDodge
impeller::DlDispatcher::EndRecordingAsPicture
Picture EndRecordingAsPicture()
Definition: dl_dispatcher.cc:1118
impeller::Canvas::DrawTextFrame
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition: canvas.cc:702
impeller::BlendMode::kDestination
@ kDestination
impeller::DlDispatcher::drawPaint
void drawPaint() override
Definition: dl_dispatcher.cc:774
dl_dispatcher.h
impeller::DlDispatcher::setStrokeJoin
void setStrokeJoin(flutter::DlStrokeJoin join) override
Definition: dl_dispatcher.cc:236
impeller::Canvas
Definition: canvas.h:48
impeller::BlendMode::kDarken
@ kDarken
impeller::PathBuilder::AddPath
PathBuilder & AddPath(const Path &path)
Definition: path_builder.cc:380
formats.h
impeller::PathBuilder
Definition: path_builder.h:14
impeller::Paint::MaskBlurDescriptor::style
FilterContents::BlurStyle style
Definition: paint.h:39
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::DlDispatcher::setImageFilter
void setImageFilter(const flutter::DlImageFilter *filter) override
Definition: dl_dispatcher.cc:616
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::Canvas::ResetTransform
void ResetTransform()
Definition: canvas.cc:197
impeller::DlDispatcher::transform2DAffine
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt) override
Definition: dl_dispatcher.cc:660
impeller::Canvas::DrawVertices
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:746
impeller::DlDispatcher::transformFullPerspective
void transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override
Definition: dl_dispatcher.cc:677
impeller::BlendMode::kColor
@ kColor
impeller::skia_conversions::ToRects
std::vector< Rect > ToRects(const SkRect tex[], int count)
Definition: skia_conversions.cc:23
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::MakeVertices
std::shared_ptr< impeller::VerticesGeometry > MakeVertices(const flutter::DlVertices *vertices)
Definition: dl_vertices_geometry.cc:31
impeller::ImageFilter::MakeBlur
static std::shared_ptr< ImageFilter > MakeBlur(Sigma sigma_x, Sigma sigma_y, FilterContents::BlurStyle blur_style, Entity::TileMode tile_mode)
Definition: image_filter.cc:20
impeller::BlendMode::kDestinationOver
@ kDestinationOver
impeller::BlendMode::kPlus
@ kPlus
impeller::DlDispatcher::drawRect
void drawRect(const SkRect &rect) override
Definition: dl_dispatcher.cc:785
impeller::Paint::MaskBlurDescriptor
Definition: paint.h:38
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:148
impeller::ColorSource::MakeSweepGradient
static ColorSource MakeSweepGradient(Point center, Degrees start_angle, Degrees end_angle, std::vector< Color > colors, std::vector< Scalar > stops, Entity::TileMode tile_mode, Matrix effect_transform)
Definition: color_source.cc:138
impeller::BlendMode::kOverlay
@ kOverlay
impeller::ColorSource::MakeColor
static ColorSource MakeColor()
Definition: color_source.cc:41
impeller::ColorSource::MakeImage
static ColorSource MakeImage(std::shared_ptr< Texture > texture, Entity::TileMode x_tile_mode, Entity::TileMode y_tile_mode, SamplerDescriptor sampler_descriptor, Matrix effect_transform)
Definition: color_source.cc:163
impeller::FilterContents::BlurStyle::kNormal
@ kNormal
Blurred inside and outside.
impeller::DlDispatcher::drawLine
void drawLine(const SkPoint &p0, const SkPoint &p1) override
Definition: dl_dispatcher.cc:779
impeller::Canvas::SaveLayer
void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const std::shared_ptr< ImageFilter > &backdrop_filter=nullptr)
Definition: canvas.cc:676
impeller::Cap::kButt
@ kButt
impeller::DlDispatcher::drawColor
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override
Definition: dl_dispatcher.cc:765
impeller::Entity::TileMode::kRepeat
@ kRepeat
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::DlDispatcher::drawImage
void drawImage(const sk_sp< flutter::DlImage > image, const SkPoint point, flutter::DlImageSampling sampling, bool render_with_attributes) override
Definition: dl_dispatcher.cc:906
impeller::Canvas::DrawLine
void DrawLine(const Point &p0, const Point &p1, const Paint &paint)
Definition: canvas.cc:310
impeller::DlDispatcher::~DlDispatcher
~DlDispatcher()
impeller::Paint::color_source
ColorSource color_source
Definition: paint.h:52
impeller::Color::green
Scalar green
Definition: color.h:133
impeller::Canvas::DrawRect
void DrawRect(const Rect &rect, const Paint &paint)
Definition: canvas.cc:321
impeller::Canvas::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:205
UNIMPLEMENTED
#define UNIMPLEMENTED
Definition: dl_dispatcher.cc:36
impeller::DlDispatcher::restore
void restore() override
Definition: dl_dispatcher.cc:635
impeller::ToTileMode
static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode)
Definition: dl_dispatcher.cc:111
impeller::BlendMode::kModulate
@ kModulate
impeller::DlDispatcher::drawPath
void drawPath(const SkPath &path) override
Definition: dl_dispatcher.cc:818
impeller::DlDispatcher::clipRect
void clipRect(const SkRect &rect, ClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:723
impeller::Join::kMiter
@ kMiter
runtime_effect_contents.h
impeller::DlDispatcher::drawDisplayList
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, SkScalar opacity) override
Definition: dl_dispatcher.cc:983
impeller::BlendMode::kSourceOut
@ kSourceOut
impeller::ImageFilter::MakeFromColorFilter
static std::shared_ptr< ImageFilter > MakeFromColorFilter(const ColorFilter &color_filter)
Definition: image_filter.cc:52
impeller::BlendMode::kSaturation
@ kSaturation
impeller::Entity::TileMode::kMirror
@ kMirror
impeller::Paint::stroke_miter
Scalar stroke_miter
Definition: paint.h:58
impeller::BlendMode::kDifference
@ kDifference
impeller::DlDispatcher::setStrokeWidth
void setStrokeWidth(SkScalar width) override
Definition: dl_dispatcher.cc:211
impeller::ToMatrix
static Matrix ToMatrix(const SkMatrix &m)
Definition: dl_dispatcher.cc:166
path_builder.h
impeller::ToColors
static std::vector< Color > ToColors(const flutter::DlColor colors[], int count)
Definition: dl_dispatcher.cc:250
impeller::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
impeller::SamplerDescriptor::mag_filter
MinMagFilter mag_filter
Definition: sampler_descriptor.h:17
impeller::skia_conversions::ToRect
Rect ToRect(const SkRect &rect)
Definition: skia_conversions.cc:12
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:15
impeller::kColor
@ kColor
Definition: geometry.h:36
impeller::BlendMode::kLighten
@ kLighten
impeller::Paint::color_filter
std::shared_ptr< ColorFilter > color_filter
Definition: paint.h:64
impeller::DlDispatcher::setColorFilter
void setColorFilter(const flutter::DlColorFilter *filter) override
Definition: dl_dispatcher.cc:472
impeller::Picture
Definition: picture.h:20
impeller::Canvas::DrawImageRect
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={})
Definition: canvas.cc:626
impeller::PointStyle::kSquare
@ kSquare
Points are drawn as circles.
impeller::SamplerDescriptor::min_filter
MinMagFilter min_filter
Definition: sampler_descriptor.h:16
impeller::BlendMode::kSoftLight
@ kSoftLight
filter_contents.h
impeller::BlendMode::kColorBurn
@ kColorBurn
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:177
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:222
scene_contents.h
skia_conversions.h
impeller::DlDispatcher::drawImageNine
void drawImageNine(const sk_sp< flutter::DlImage > image, const SkIRect &center, const SkRect &dst, flutter::DlFilterMode filter, bool render_with_attributes) override
Definition: dl_dispatcher.cc:951
impeller::BlendMode::kHardLight
@ kHardLight
sigma.h
impeller::DlDispatcher::transformReset
void transformReset() override
Definition: dl_dispatcher.cc:707
impeller::Radius
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:48
impeller::FilterContents::BlurStyle::kSolid
@ kSolid
Solid inside, blurred outside.
impeller::Matrix::GetScale
constexpr Vector3 GetScale() const
Definition: matrix.h:303
impeller::ColorSource::MakeConicalGradient
static ColorSource MakeConicalGradient(Point center, Scalar radius, std::vector< Color > colors, std::vector< Scalar > stops, Point focus_center, Scalar focus_radius, Entity::TileMode tile_mode, Matrix effect_transform)
Definition: color_source.cc:74
impeller::ColorFilter::MakeBlend
static std::shared_ptr< ColorFilter > MakeBlend(BlendMode blend_mode, Color color)
Definition: color_filter.cc:23
impeller::Canvas::Save
void Save()
Definition: canvas.cc:132
impeller::ColorSource::Type::kRuntimeEffect
@ kRuntimeEffect
impeller::BlendMode::kClear
@ kClear
impeller::DlDispatcher::drawDRRect
void drawDRRect(const SkRRect &outer, const SkRRect &inner) override
Definition: dl_dispatcher.cc:810
impeller::DlDispatcher::clipPath
void clipPath(const SkPath &path, ClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:744
impeller::MinMagFilter::kLinear
@ kLinear
impeller::Paint::style
Style style
Definition: paint.h:59
impeller::ImageFilter::MakeLocalMatrix
static std::shared_ptr< ImageFilter > MakeLocalMatrix(const Matrix &matrix, const ImageFilter &internal_filter)
Definition: image_filter.cc:57
impeller::Paint::Style::kFill
@ kFill
impeller::ToColorSourceType
static std::optional< ColorSource::Type > ToColorSourceType(flutter::DlColorSourceType type)
Definition: dl_dispatcher.cc:261
impeller::ColorMatrix::array
Scalar array[20]
Definition: color.h:118
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:395
impeller::DlDispatcher::setMaskFilter
void setMaskFilter(const flutter::DlMaskFilter *filter) override
Definition: dl_dispatcher.cc:506
impeller::ToStyle
static Paint::Style ToStyle(flutter::DlDrawStyle style)
Definition: dl_dispatcher.cc:182
impeller::Color::red
Scalar red
Definition: color.h:128
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:168
impeller::ImageFilter::MakeErode
static std::shared_ptr< ImageFilter > MakeErode(Radius radius_x, Radius radius_y)
Definition: image_filter.cc:34
impeller::Canvas::DrawAtlas
void DrawAtlas(const std::shared_ptr< Image > &atlas, std::vector< Matrix > transforms, std::vector< Rect > texture_coordinates, std::vector< Color > colors, BlendMode blend_mode, SamplerDescriptor sampler, std::optional< Rect > cull_rect, const Paint &paint)
Definition: canvas.cc:806
impeller::PathBuilder::TakePath
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:21
impeller::Canvas::DrawPaint
void DrawPaint(const Paint &paint)
Definition: canvas.cc:260
filter_input.h
impeller::NinePatchConverter
Definition: nine_patch_converter.h:18
impeller::ToBlurStyle
static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style)
Definition: dl_dispatcher.cc:492
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:238
impeller::Join::kRound
@ kRound
impeller::DlDispatcher::drawShadow
void drawShadow(const SkPath &path, const flutter::DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
Definition: dl_dispatcher.cc:1060
impeller::Vector3::y
Scalar y
Definition: vector.h:24
impeller::FilterContents::BlurStyle::kInner
@ kInner
Blurred inside, nothing outside.
impeller::DlDispatcher::setAntiAlias
void setAntiAlias(bool aa) override
Definition: dl_dispatcher.cc:178
impeller::DlDispatcher::setInvertColors
void setInvertColors(bool invert) override
Definition: dl_dispatcher.cc:477
impeller::DlDispatcher::drawVertices
void drawVertices(const flutter::DlVertices *vertices, flutter::DlBlendMode dl_mode) override
Definition: dl_dispatcher.cc:900
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:140
impeller::Entity::TileMode
TileMode
Definition: entity.h:40
impeller::SamplerDescriptor::mip_filter
MipFilter mip_filter
Definition: sampler_descriptor.h:18
impeller::DlDispatcher::setColorSource
void setColorSource(const flutter::DlColorSource *source) override
Definition: dl_dispatcher.cc:286
impeller::ColorSource::MakeRadialGradient
static ColorSource MakeRadialGradient(Point center, Scalar radius, std::vector< Color > colors, std::vector< Scalar > stops, Entity::TileMode tile_mode, Matrix effect_transform)
Definition: color_source.cc:108
impeller::ImageFilter::MakeMatrix
static std::shared_ptr< ImageFilter > MakeMatrix(const Matrix &matrix, SamplerDescriptor sampler_descriptor)
Definition: image_filter.cc:39
dl_vertices_geometry.h
impeller::ColorFilter::MakeMatrix
static std::shared_ptr< ColorFilter > MakeMatrix(ColorMatrix color_matrix)
Definition: color_filter.cc:28
impeller::Canvas::ClipRRect
void ClipRRect(const Rect &rect, const Size &corner_radii, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:470
scalar.h
impeller::Canvas::PreConcat
void PreConcat(const Matrix &transform)
Definition: canvas.cc:193
impeller::DlDispatcher::drawTextFrame
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, SkScalar x, SkScalar y) override
Definition: dl_dispatcher.cc:1050
impeller::ImageFilter::MakeCompose
static std::shared_ptr< ImageFilter > MakeCompose(const ImageFilter &inner, const ImageFilter &outer)
Definition: image_filter.cc:46
impeller::BlendMode::kDestinationIn
@ kDestinationIn
impeller::DlDispatcher::skew
void skew(SkScalar sx, SkScalar sy) override
Definition: dl_dispatcher.cc:655
impeller::Join::kBevel
@ kBevel
impeller::ColorSource::Type::kImage
@ kImage
impeller::ColorSource::MakeRuntimeEffect
static ColorSource MakeRuntimeEffect(std::shared_ptr< RuntimeStage > runtime_stage, std::shared_ptr< std::vector< uint8_t >> uniform_data, std::vector< RuntimeEffectContents::TextureInput > texture_inputs)
Definition: color_source.cc:193
impeller::Canvas::DrawOval
void DrawOval(const Rect &rect, const Paint &paint)
Definition: canvas.cc:341
impeller::BlendMode::kExclusion
@ kExclusion
impeller::BlendMode::kDestinationOut
@ kDestinationOut
impeller::FilterContents::BlurStyle::kOuter
@ kOuter
Nothing inside, blurred outside.
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:191
impeller::Canvas::Rotate
void Rotate(Radians radians)
Definition: canvas.cc:234
impeller::ColorSource::Type::kConicalGradient
@ kConicalGradient
impeller::ColorFilter::MakeLinearToSrgb
static std::shared_ptr< ColorFilter > MakeLinearToSrgb()
Definition: color_filter.cc:36
impeller::DlDispatcher::setDrawStyle
void setDrawStyle(flutter::DlDrawStyle style) override
Definition: dl_dispatcher.cc:196
impeller::TPoint< Scalar >
impeller::Canvas::Transform
void Transform(const Matrix &transform)
Definition: canvas.cc:201
impeller::skia_conversions::ToRSXForms
std::vector< Matrix > ToRSXForms(const SkRSXform xform[], int count)
Definition: skia_conversions.cc:157
impeller::Paint::invert_colors
bool invert_colors
Definition: paint.h:61
impeller::DlDispatcher::setColor
void setColor(flutter::DlColor color) override
Definition: dl_dispatcher.cc:201
impeller::MipFilter::kLinear
@ kLinear
impeller::Canvas::GetCurrentLocalCullingBounds
const std::optional< Rect > GetCurrentLocalCullingBounds() const
Definition: canvas.cc:209
impeller::BlendMode::kSourceIn
@ kSourceIn
impeller::BlendMode::kScreen
@ kScreen
impeller::SamplerDescriptor::label
std::string label
Definition: sampler_descriptor.h:24
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:59
impeller::ToBlendMode
static BlendMode ToBlendMode(flutter::DlBlendMode mode)
Definition: dl_dispatcher.cc:47
impeller::DlDispatcher::rotate
void rotate(SkScalar degrees) override
Definition: dl_dispatcher.cc:650
impeller::TRect::GetBottom
constexpr auto GetBottom() const
Definition: rect.h:198
impeller::Degrees
Definition: scalar.h:46
color_filter.h
impeller::Paint::Style
Style
Definition: paint.h:33
impeller::BlendMode::kHue
@ kHue
impeller::Canvas::ClipRect
void ClipRect(const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:429
impeller::ToSamplerDescriptor
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Definition: dl_dispatcher.cc:124
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:27
impeller::ToColorFilter
static std::shared_ptr< ColorFilter > ToColorFilter(const flutter::DlColorFilter *filter)
Definition: dl_dispatcher.cc:445
impeller::ColorFilter::MakeSrgbToLinear
static std::shared_ptr< ColorFilter > MakeSrgbToLinear()
Definition: color_filter.cc:32
nine_patch_converter.h
impeller::BlendMode::kXor
@ kXor
impeller::Canvas::ClipPath
void ClipPath(Path path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:419
impeller::Color::blue
Scalar blue
Definition: color.h:138
impeller::ColorSource::Type::kSweepGradient
@ kSweepGradient
impeller::DlDispatcher::setStrokeMiter
void setStrokeMiter(SkScalar limit) override
Definition: dl_dispatcher.cc:216
impeller::ColorMatrix
Definition: color.h:117
impeller::DlDispatcher::drawPoints
void drawPoints(PointMode mode, uint32_t count, const SkPoint points[]) override
Definition: dl_dispatcher.cc:862
impeller::DlDispatcher::drawAtlas
void drawAtlas(const sk_sp< flutter::DlImage > atlas, const SkRSXform xform[], const SkRect tex[], const flutter::DlColor colors[], int count, flutter::DlBlendMode mode, flutter::DlImageSampling sampling, const SkRect *cull_rect, bool render_with_attributes) override
Definition: dl_dispatcher.cc:965
impeller
Definition: aiks_context.cc:10
impeller::BlendMode::kSourceATop
@ kSourceATop
impeller::Paint::mask_blur_descriptor
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:65
impeller::BlendMode::kMultiply
@ kMultiply
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:184
impeller::Paint::stroke_width
Scalar stroke_width
Definition: paint.h:55
impeller::skia_conversions::ToPath
Path ToPath(const SkPath &path, Point shift)
Definition: skia_conversions.cc:49
impeller::ColorSource::Type::kColor
@ kColor
impeller::DlDispatcher::translate
void translate(SkScalar tx, SkScalar ty) override
Definition: dl_dispatcher.cc:640
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::PathBuilder::AddArc
PathBuilder & AddArc(const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
Definition: path_builder.cc:264
impeller::Vector3
Definition: vector.h:20
impeller::DlDispatcher::setStrokeCap
void setStrokeCap(flutter::DlStrokeCap cap) override
Definition: dl_dispatcher.cc:221
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::Paint::blend_mode
BlendMode blend_mode
Definition: paint.h:60
impeller::DlDispatcher::setPathEffect
void setPathEffect(const flutter::DlPathEffect *effect) override
Definition: dl_dispatcher.cc:487
impeller::DlDispatcher::drawCircle
void drawCircle(const SkPoint &center, SkScalar radius) override
Definition: dl_dispatcher.cc:795
impeller::Paint::image_filter
std::shared_ptr< ImageFilter > image_filter
Definition: paint.h:63
impeller::Paint::stroke_join
Join stroke_join
Definition: paint.h:57
impeller::Canvas::Translate
void Translate(const Vector3 &offset)
Definition: canvas.cc:218