Flutter Engine
 
Loading...
Searching...
No Matches
dl_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
6
7namespace {
8
9// ShadowBounds code adapted from SkShadowUtils using the Directional flag.
10
16
17static constexpr DlScalar kAmbientHeightFactor = 1.0f / 128.0f;
18static constexpr DlScalar kAmbientGeomFactor = 64.0f;
19// Assuming that we have a light height of 600 for the spot shadow, the spot
20// values will reach their maximum at a height of approximately 292.3077.
21// We'll round up to 300 to keep it simple.
22static constexpr DlScalar kMaxAmbientRadius =
23 300.0f * kAmbientHeightFactor * kAmbientGeomFactor;
24
25inline DlScalar AmbientBlurRadius(DlScalar height) {
26 return std::min(height * kAmbientHeightFactor * kAmbientGeomFactor,
27 kMaxAmbientRadius);
28}
29
30struct DrawShadowRec {
31 DlVector3 light_position;
32 DlScalar light_radius = 0.0f;
33 DlScalar occluder_z = 0.0f;
34};
35
36static inline float DivideAndClamp(float numer,
37 float denom,
38 float min,
39 float max) {
40 float result = std::clamp(numer / denom, min, max);
41 // ensure that clamp handled non-finites correctly
42 FML_DCHECK(result >= min && result <= max);
43 return result;
44}
45
46inline void GetDirectionalParams(DrawShadowRec params,
47 DlScalar* blur_radius,
48 DlScalar* scale,
49 DlVector2* translate) {
50 *blur_radius = params.light_radius * params.occluder_z;
51 *scale = 1.0f;
52 // Max z-ratio is ("max expected elevation" / "min allowable z").
53 constexpr DlScalar kMaxZRatio = 64.0f / flutter::kEhCloseEnough;
54 DlScalar zRatio = DivideAndClamp(params.occluder_z, params.light_position.z,
55 0.0f, kMaxZRatio);
56 *translate = DlVector2(-zRatio * params.light_position.x,
57 -zRatio * params.light_position.y);
58}
59
60DlRect GetLocalBounds(DlRect ambient_bounds,
61 const DlMatrix& matrix,
62 const DrawShadowRec& params) {
63 if (!matrix.IsInvertible() || ambient_bounds.IsEmpty()) {
64 return DlRect();
65 }
66
67 DlScalar ambient_blur;
68 DlScalar spot_blur;
69 DlScalar spot_scale;
70 DlVector2 spot_offset;
71
72 if (matrix.HasPerspective2D()) {
73 // transform ambient and spot bounds into device space
74 ambient_bounds = ambient_bounds.TransformAndClipBounds(matrix);
75
76 // get ambient blur (in device space)
77 ambient_blur = AmbientBlurRadius(params.occluder_z);
78
79 // get spot params (in device space)
80 GetDirectionalParams(params, &spot_blur, &spot_scale, &spot_offset);
81 } else {
82 auto min_scale = matrix.GetMinScale2D();
83 // We've already checked the matrix for perspective elements.
84 FML_DCHECK(min_scale.has_value());
85 DlScalar device_to_local_scale = 1.0f / min_scale.value_or(1.0f);
86
87 // get ambient blur (in local space)
88 DlScalar device_space_ambient_blur = AmbientBlurRadius(params.occluder_z);
89 ambient_blur = device_space_ambient_blur * device_to_local_scale;
90
91 // get spot params (in local space)
92 GetDirectionalParams(params, &spot_blur, &spot_scale, &spot_offset);
93 // light dir is in device space, map spot offset back into local space
94 DlMatrix inverse = matrix.Invert();
95 spot_offset = inverse.TransformDirection(spot_offset);
96
97 // convert spot blur to local space
98 spot_blur *= device_to_local_scale;
99 }
100
101 // in both cases, adjust ambient and spot bounds
102 DlRect spot_bounds = ambient_bounds;
103 ambient_bounds = ambient_bounds.Expand(ambient_blur);
104 spot_bounds = spot_bounds.Scale(spot_scale);
105 spot_bounds = spot_bounds.Shift(spot_offset);
106 spot_bounds = spot_bounds.Expand(spot_blur);
107
108 // merge bounds
109 DlRect result = ambient_bounds.Union(spot_bounds);
110 // outset a bit to account for floating point error
111 result = result.Expand(1.0f, 1.0f);
112
113 // if perspective, transform back to src space
114 if (matrix.HasPerspective2D()) {
115 DlMatrix inverse = matrix.Invert();
116 result = result.TransformAndClipBounds(inverse);
117 }
118 return result;
119}
120
121} // namespace
122
123namespace flutter {
124
126 float elevation,
127 DlScalar dpr,
128 const DlMatrix& ctm) {
129 return GetLocalBounds(
130 path.GetBounds(), ctm,
131 {
132 .light_position = DlVector3(0.0f, -1.0f, 1.0f),
133 .light_radius = kShadowLightRadius / kShadowLightHeight,
134 .occluder_z = dpr * elevation,
135 });
136}
137
138} // namespace flutter
static DlRect ComputeShadowBounds(const DlPath &path, float elevation, DlScalar dpr, const DlMatrix &ctm)
Compute the local coverage for a |DrawShadow| operation using the given parameters (excluding the col...
Definition dl_canvas.cc:125
const EmbeddedViewParams * params
#define FML_DCHECK(condition)
Definition logging.h:122
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
impeller::Scalar DlScalar
impeller::Matrix DlMatrix
impeller::Rect DlRect
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
static constexpr DlScalar kEhCloseEnough
impeller::Vector3 DlVector3
impeller::Vector2 DlVector2
int32_t height
A 4x4 matrix using column-major storage.
Definition matrix.h:37
Matrix Invert() const
Definition matrix.cc:99
constexpr Vector4 TransformDirection(const Vector4 &v) const
Definition matrix.h:607
constexpr TRect Union(const TRect &o) const
Definition rect.h:513
constexpr TRect Scale(Type scale) const
Definition rect.h:202
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition rect.h:618
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602