Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
dl_sk_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 <cstdint>
6
8
17
18#include "third_party/skia/include/effects/SkDashPathEffect.h"
19#include "third_party/skia/include/utils/SkShadowUtils.h"
20
21namespace flutter {
22
23const SkPaint* DlSkCanvasDispatcher::safe_paint(bool use_attributes) {
24 if (use_attributes) {
25 // The accumulated SkPaint object will already have incorporated
26 // any attribute overrides.
27 // Any rendering operation that uses an optional paint will ignore
28 // the shader in the paint so we inform that |paint()| method so
29 // that it can set the dither flag appropriately.
30 return &paint(false);
31 } else if (has_opacity()) {
32 temp_paint_.setAlphaf(opacity());
33 return &temp_paint_;
34 } else {
35 return nullptr;
36 }
37}
38
40 canvas_->save();
41 // save has no impact on attributes, but it needs to register a record
42 // on the restore stack so that the eventual call to restore() will
43 // know what to do at that time. We could annotate the restore record
44 // with a flag that the record came from a save call, but it is simpler
45 // to just pass in the current opacity value as the value to be used by
46 // the children and let the utility calls notice that it didn't change.
48}
50 canvas_->restore();
52}
54 const SaveLayerOptions options,
55 const DlImageFilter* backdrop,
56 std::optional<int64_t> backdrop_id) {
57 if (!options.content_is_clipped() && options.can_distribute_opacity() &&
58 backdrop == nullptr) {
59 // We know that:
60 // - no bounds is needed for clipping here
61 // - no backdrop filter is used to initialize the layer
62 // - the current attributes only have an alpha
63 // - the children are compatible with individually rendering with
64 // an inherited opacity
65 // Therefore we can just use a save instead of a saveLayer and pass the
66 // intended opacity to the children.
67 canvas_->save();
68 // If the saveLayer does not use attributes, the children should continue
69 // to render with the inherited opacity unmodified. If attributes are to
70 // be applied, the children should render with the combination of the
71 // inherited opacity combined with the alpha from the current color.
73 : opacity());
74 } else {
75 TRACE_EVENT0("flutter", "Canvas::saveLayer");
76 const SkPaint* paint = safe_paint(options.renders_with_attributes());
77 const sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
78 const SkRect* sl_bounds =
79 options.bounds_from_caller() ? &ToSkRect(bounds) : nullptr;
80 SkCanvas::SaveLayerRec params(sl_bounds, paint, sk_backdrop.get(), 0);
81 if (sk_backdrop && backdrop->asBlur()) {
82 params.fBackdropTileMode = ToSk(backdrop->asBlur()->tile_mode());
83 }
84 canvas_->saveLayer(params);
85 // saveLayer will apply the current opacity on behalf of the children
86 // so they will inherit an opaque opacity.
87 save_opacity(SK_Scalar1);
88 }
89}
90
92 canvas_->translate(tx, ty);
93}
95 canvas_->scale(sx, sy);
96}
98 canvas_->rotate(degrees);
99}
101 canvas_->skew(sx, sy);
102}
103// clang-format off
104// 2x3 2D affine subset of a 4x4 transform in row major order
106 DlScalar mxx, DlScalar mxy, DlScalar mxt,
107 DlScalar myx, DlScalar myy, DlScalar myt) {
108 // Internally concat(SkMatrix) gets redirected to concat(SkM44)
109 // so we just jump directly to the SkM44 version
110 canvas_->concat(SkM44(mxx, mxy, 0, mxt,
111 myx, myy, 0, myt,
112 0, 0, 1, 0,
113 0, 0, 0, 1));
114}
115// full 4x4 transform in row major order
117 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
118 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
119 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
120 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
121 canvas_->concat(SkM44(mxx, mxy, mxz, mxt,
122 myx, myy, myz, myt,
123 mzx, mzy, mzz, mzt,
124 mwx, mwy, mwz, mwt));
125}
126// clang-format on
128 canvas_->setMatrix(original_transform_);
129}
130
132 DlClipOp clip_op,
133 bool is_aa) {
134 canvas_->clipRect(ToSkRect(rect), ToSk(clip_op), is_aa);
135}
137 DlClipOp clip_op,
138 bool is_aa) {
139 canvas_->clipRRect(SkRRect::MakeOval(ToSkRect(bounds)), ToSk(clip_op), is_aa);
140}
142 DlClipOp clip_op,
143 bool is_aa) {
144 canvas_->clipRRect(ToSkRRect(rrect), ToSk(clip_op), is_aa);
145}
147 DlClipOp clip_op,
148 bool is_aa) {
149 // Skia doesn't support round superellipse, thus fall back to round rectangle.
150 canvas_->clipRRect(ToApproximateSkRRect(rse), ToSk(clip_op), is_aa);
151}
153 DlClipOp clip_op,
154 bool is_aa) {
155 path.WillRenderSkPath();
156 canvas_->clipPath(path.GetSkPath(), ToSk(clip_op), is_aa);
157}
158
160 const SkPaint& sk_paint = paint();
161 SkImageFilter* filter = sk_paint.getImageFilter();
162 if (filter && !filter->asColorFilter(nullptr)) {
163 // drawPaint does an implicit saveLayer if an SkImageFilter is
164 // present that cannot be replaced by an SkColorFilter.
165 TRACE_EVENT0("flutter", "Canvas::saveLayer");
166 }
167 canvas_->drawPaint(sk_paint);
168}
170 // SkCanvas::drawColor(SkColor) does the following conversion anyway
171 // We do it here manually to increase precision on applying opacity
172 SkColor4f color4f = ToSkColor4f(color);
173 color4f.fA *= opacity();
174 canvas_->drawColor(color4f, ToSk(mode));
175}
177 canvas_->drawLine(ToSkPoint(p0), ToSkPoint(p1), paint());
178}
180 const DlPoint& p1,
181 DlScalar on_length,
182 DlScalar off_length) {
183 SkPaint dash_paint = paint();
184 SkScalar intervals[] = {on_length, off_length};
185 dash_paint.setPathEffect(SkDashPathEffect::Make({intervals, 2}, 0.0f));
186 canvas_->drawLine(ToSkPoint(p0), ToSkPoint(p1), dash_paint);
187}
189 canvas_->drawRect(ToSkRect(rect), paint());
190}
192 canvas_->drawOval(ToSkRect(bounds), paint());
193}
195 canvas_->drawCircle(ToSkPoint(center), radius, paint());
196}
198 canvas_->drawRRect(ToSkRRect(rrect), paint());
199}
201 const DlRoundRect& inner) {
202 canvas_->drawDRRect(ToSkRRect(outer), ToSkRRect(inner), paint());
203}
205 const DlRoundSuperellipse& rse) {
206 // Skia doesn't support round superellipse, thus fall back to round rectangle.
207 canvas_->drawRRect(ToApproximateSkRRect(rse), paint());
208}
210 path.WillRenderSkPath();
211 canvas_->drawPath(path.GetSkPath(), paint());
212}
214 DlScalar start,
215 DlScalar sweep,
216 bool useCenter) {
217 canvas_->drawArc(ToSkRect(bounds), start, sweep, useCenter, paint());
218}
220 uint32_t count,
221 const DlPoint pts[]) {
222 canvas_->drawPoints(ToSk(mode), {ToSkPoints(pts), count}, paint());
223}
225 const std::shared_ptr<DlVertices>& vertices,
226 DlBlendMode mode) {
227 canvas_->drawVertices(ToSk(vertices), ToSk(mode), paint());
228}
229void DlSkCanvasDispatcher::drawImage(const sk_sp<DlImage> image,
230 const DlPoint& point,
231 DlImageSampling sampling,
232 bool render_with_attributes) {
234 auto skia_image = image->asSkiaImage();
235 FML_DCHECK(skia_image);
236 canvas_->drawImage(skia_image->skia_image().get(), point.x, point.y,
237 ToSk(sampling), safe_paint(render_with_attributes));
238}
240 const DlRect& src,
241 const DlRect& dst,
242 DlImageSampling sampling,
243 bool render_with_attributes,
244 DlSrcRectConstraint constraint) {
246 auto skia_image = image->asSkiaImage();
247 FML_DCHECK(skia_image);
248 canvas_->drawImageRect(skia_image->skia_image().get(), ToSkRect(src),
249 ToSkRect(dst), ToSk(sampling),
250 safe_paint(render_with_attributes), ToSk(constraint));
251}
253 const DlIRect& center,
254 const DlRect& dst,
255 DlFilterMode filter,
256 bool render_with_attributes) {
258 auto skia_image = image->asSkiaImage();
259 FML_DCHECK(skia_image);
260 canvas_->drawImageNine(skia_image->skia_image().get(), ToSkIRect(center),
261 ToSkRect(dst), ToSk(filter),
262 safe_paint(render_with_attributes));
263}
264void DlSkCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
265 const DlRSTransform xform[],
266 const DlRect tex[],
267 const DlColor colors[],
268 int count,
269 DlBlendMode mode,
270 DlImageSampling sampling,
271 const DlRect* cullRect,
272 bool render_with_attributes) {
273 FML_DCHECK(atlas);
274 auto skia_atlas = atlas->asSkiaImage();
275 FML_DCHECK(skia_atlas);
276 std::vector<SkColor> sk_colors;
277 if (colors != nullptr) {
278 sk_colors.reserve(count);
279 for (int i = 0; i < count; ++i) {
280 sk_colors.push_back(colors[i].argb());
281 }
282 }
283 SkSpan<const SkColor> colorSpan;
284 if (!colors) {
285 colorSpan = {nullptr, 0};
286 } else {
287 colorSpan = {sk_colors.data(), count};
288 }
289 canvas_->drawAtlas(skia_atlas->skia_image().get(), {ToSk(xform), count},
290 {ToSkRects(tex), count}, colorSpan, ToSk(mode),
291 ToSk(sampling), ToSkRect(cullRect),
292 safe_paint(render_with_attributes));
293}
295 const sk_sp<DisplayList> display_list,
296 DlScalar opacity) {
297 const int restore_count = canvas_->getSaveCount();
298
299 // Compute combined opacity and figure out whether we can apply it
300 // during dispatch or if we need a saveLayer.
301 SkScalar combined_opacity = opacity * this->opacity();
302 if (combined_opacity < SK_Scalar1 &&
303 !display_list->can_apply_group_opacity()) {
304 TRACE_EVENT0("flutter", "Canvas::saveLayer");
305 canvas_->saveLayerAlphaf(ToSkRect(&display_list->GetBounds()),
307 combined_opacity = SK_Scalar1;
308 } else {
309 canvas_->save();
310 }
311
312 // Create a new CanvasDispatcher to isolate the actions of the
313 // display_list from the current environment.
314 DlSkCanvasDispatcher dispatcher(canvas_, combined_opacity);
315 if (display_list->rtree()) {
316 display_list->Dispatch(dispatcher, ToDlRect(canvas_->getLocalClipBounds()));
317 } else {
318 display_list->Dispatch(dispatcher);
319 }
320
321 // Restore canvas state to what it was before dispatching.
322 canvas_->restoreToCount(restore_count);
323}
324void DlSkCanvasDispatcher::drawText(const std::shared_ptr<DlText>& text,
325 DlScalar x,
326 DlScalar y) {
327 auto blob = text->GetTextBlob();
328 FML_CHECK(blob) << "Impeller DlText cannot be drawn to a Skia canvas.";
329 canvas_->drawTextBlob(blob, x, y, paint());
330}
331
333 const SkPath& path,
334 DlColor color,
335 float elevation,
336 bool transparentOccluder,
337 DlScalar dpr) {
338 const SkScalar kAmbientAlpha = 0.039f;
339 const SkScalar kSpotAlpha = 0.25f;
340
341 uint32_t flags = transparentOccluder
342 ? SkShadowFlags::kTransparentOccluder_ShadowFlag
343 : SkShadowFlags::kNone_ShadowFlag;
344 flags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
345 SkColor in_ambient =
346 SkColorSetA(ToSkColor(color), kAmbientAlpha * color.getAlpha());
347 SkColor in_spot =
348 SkColorSetA(ToSkColor(color), kSpotAlpha * color.getAlpha());
349 SkColor ambient_color, spot_color;
350 SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color,
351 &spot_color);
352 SkShadowUtils::DrawShadow(
353 canvas, path, SkPoint3::Make(0, 0, dpr * elevation),
354 SkPoint3::Make(0, -1, 1),
356 ambient_color, spot_color, flags);
357}
358
360 const DlColor color,
361 const DlScalar elevation,
362 bool transparent_occluder,
363 DlScalar dpr) {
364 path.WillRenderSkPath();
365 DrawShadow(canvas_, path.GetSkPath(), color, elevation, transparent_occluder,
366 dpr);
367}
368
369} // namespace flutter
static constexpr DlScalar kShadowLightHeight
Definition dl_canvas.h:215
static constexpr DlScalar kShadowLightRadius
Definition dl_canvas.h:216
virtual const DlBlurImageFilter * asBlur() const
Backend implementation of |DlOpReceiver| for |SkCanvas|.
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void drawImage(const sk_sp< DlImage > image, const DlPoint &point, DlImageSampling sampling, bool render_with_attributes) override
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void drawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter) override
void drawImageRect(const sk_sp< DlImage > image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, bool render_with_attributes, DlSrcRectConstraint constraint) override
void drawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length) override
void drawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode) override
const SkPaint * safe_paint(bool use_attributes)
void saveLayer(const DlRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void drawRect(const DlRect &rect) override
void clipRect(const DlRect &rect, DlClipOp clip_op, bool is_aa) override
void rotate(DlScalar degrees) override
void drawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y) override
void drawCircle(const DlPoint &center, DlScalar radius) override
void drawAtlas(const sk_sp< DlImage > atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cullRect, bool render_with_attributes) override
void drawLine(const DlPoint &p0, const DlPoint &p1) override
void drawImageNine(const sk_sp< DlImage > image, const DlIRect &center, const DlRect &dst, DlFilterMode filter, bool render_with_attributes) override
void drawColor(DlColor color, DlBlendMode mode) override
void drawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[]) override
void skew(DlScalar sx, DlScalar sy) override
void drawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
static void DrawShadow(SkCanvas *canvas, const SkPath &path, DlColor color, float elevation, bool transparentOccluder, DlScalar dpr)
void drawRoundSuperellipse(const DlRoundSuperellipse &rse) override
void clipOval(const DlRect &bounds, DlClipOp clip_op, bool is_aa) override
void drawRoundRect(const DlRoundRect &rrect) override
void drawPath(const DlPath &path) override
void drawOval(const DlRect &bounds) override
void drawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity) override
void clipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op, bool is_aa) override
void scale(DlScalar sx, DlScalar sy) override
void clipPath(const DlPath &path, DlClipOp clip_op, bool is_aa) override
void clipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op, bool is_aa) override
void translate(DlScalar tx, DlScalar ty) override
void drawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner) override
const SkPaint & paint(bool uses_shader=true)
void save_opacity(SkScalar opacity_for_children)
bool content_is_clipped() const
bool renders_with_attributes() const
bool bounds_from_caller() const
bool can_distribute_opacity() const
int32_t x
const EmbeddedViewParams * params
FlutterVulkanImage * image
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
std::u16string text
double y
impeller::Scalar DlScalar
SkPaint ToSk(const DlPaint &paint)
const SkPoint & ToSkPoint(const DlPoint &point)
const SkIRect & ToSkIRect(const DlIRect &rect)
SkColor ToSkColor(DlColor color)
const SkRRect ToApproximateSkRRect(const DlRoundSuperellipse &rse)
DlPointMode
Definition dl_types.h:15
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
SkColor4f ToSkColor4f(DlColor color)
const SkPoint * ToSkPoints(const DlPoint *points)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
const SkRRect ToSkRRect(const DlRoundRect &round_rect)
const DlRect & ToDlRect(const SkRect &rect)
const SkRect & ToSkRect(const DlRect &rect)
DlSrcRectConstraint
Definition dl_types.h:21
BlendMode
Definition color.h:58
int getAlpha() const
Definition dl_color.h:102
const size_t start
#define TRACE_EVENT0(category_group, name)