Flutter Engine
The Flutter Engine
Functions | Variables
SkDrawShadowMetrics Namespace Reference

Functions

static SkScalar compute_z (SkScalar x, SkScalar y, const SkPoint3 &params)
 
bool GetSpotShadowTransform (const SkPoint3 &lightPos, SkScalar lightRadius, const SkMatrix &ctm, const SkPoint3 &zPlaneParams, const SkRect &pathBounds, bool directional, SkMatrix *shadowTransform, SkScalar *radius)
 
void GetLocalBounds (const SkPath &path, const SkDrawShadowRec &rec, const SkMatrix &ctm, SkRect *bounds)
 
static float divide_and_pin (float numer, float denom, float min, float max)
 
SkScalar AmbientBlurRadius (SkScalar height)
 
SkScalar AmbientRecipAlpha (SkScalar height)
 
SkScalar SpotBlurRadius (SkScalar occluderZ, SkScalar lightZ, SkScalar lightRadius)
 
void GetSpotParams (SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
 
void GetDirectionalParams (SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
 

Variables

static constexpr auto kAmbientHeightFactor = 1.0f / 128.0f
 
static constexpr auto kAmbientGeomFactor = 64.0f
 
static constexpr auto kMaxAmbientRadius = 300*kAmbientHeightFactor*kAmbientGeomFactor
 

Function Documentation

◆ AmbientBlurRadius()

SkScalar SkDrawShadowMetrics::AmbientBlurRadius ( SkScalar  height)
inline

Definition at line 51 of file SkDrawShadowInfo.h.

51 {
53}
static float min(float r, float g, float b)
Definition: hsl.cpp:48
static constexpr auto kMaxAmbientRadius
static constexpr auto kAmbientHeightFactor
static constexpr auto kAmbientGeomFactor
int32_t height

◆ AmbientRecipAlpha()

SkScalar SkDrawShadowMetrics::AmbientRecipAlpha ( SkScalar  height)
inline

Definition at line 55 of file SkDrawShadowInfo.h.

55 {
56 return 1.0f + std::max(height*kAmbientHeightFactor, 0.0f);
57}
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ compute_z()

static SkScalar SkDrawShadowMetrics::compute_z ( SkScalar  x,
SkScalar  y,
const SkPoint3 params 
)
static

Definition at line 18 of file SkDrawShadowInfo.cpp.

18 {
19 return x*params.fX + y*params.fY + params.fZ;
20}
const EmbeddedViewParams * params
double y
double x

◆ divide_and_pin()

static float SkDrawShadowMetrics::divide_and_pin ( float  numer,
float  denom,
float  min,
float  max 
)
inlinestatic

Definition at line 44 of file SkDrawShadowInfo.h.

44 {
45 float result = SkTPin(sk_ieee_float_divide(numer, denom), min, max);
46 // ensure that SkTPin handled non-finites correctly
47 SkASSERT(result >= min && result <= max);
48 return result;
49}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static constexpr float sk_ieee_float_divide(float numer, float denom)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
GAsyncResult * result

◆ GetDirectionalParams()

void SkDrawShadowMetrics::GetDirectionalParams ( SkScalar  occluderZ,
SkScalar  lightX,
SkScalar  lightY,
SkScalar  lightZ,
SkScalar  lightRadius,
SkScalar blurRadius,
SkScalar scale,
SkVector translate 
)
inline

Definition at line 72 of file SkDrawShadowInfo.h.

74 {
75 *blurRadius = lightRadius*occluderZ;
76 *scale = 1;
77 // Max z-ratio is "max expected elevation"/"min allowable z"
78 constexpr SkScalar kMaxZRatio = 64/SK_ScalarNearlyZero;
79 SkScalar zRatio = divide_and_pin(occluderZ, lightZ, 0.0f, kMaxZRatio);
80 *translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
81}
#define SK_ScalarNearlyZero
Definition: SkScalar.h:99
float SkScalar
Definition: extension.cpp:12
static float divide_and_pin(float numer, float denom, float min, float max)
const Scalar scale
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173

◆ GetLocalBounds()

void SkDrawShadowMetrics::GetLocalBounds ( const SkPath path,
const SkDrawShadowRec rec,
const SkMatrix ctm,
SkRect bounds 
)

Definition at line 124 of file SkDrawShadowInfo.cpp.

125 {
126 SkRect ambientBounds = path.getBounds();
127 SkScalar occluderZ;
129 occluderZ = rec.fZPlaneParams.fZ;
130 } else {
131 occluderZ = compute_z(ambientBounds.fLeft, ambientBounds.fTop, rec.fZPlaneParams);
132 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fTop,
133 rec.fZPlaneParams));
134 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fLeft, ambientBounds.fBottom,
135 rec.fZPlaneParams));
136 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fBottom,
137 rec.fZPlaneParams));
138 }
139 SkScalar ambientBlur;
140 SkScalar spotBlur;
141 SkScalar spotScale;
142 SkPoint spotOffset;
143 if (ctm.hasPerspective()) {
144 // transform ambient and spot bounds into device space
145 ctm.mapRect(&ambientBounds);
146
147 // get ambient blur (in device space)
148 ambientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
149
150 // get spot params (in device space)
153 rec.fLightPos.fZ, rec.fLightRadius,
154 &spotBlur, &spotScale, &spotOffset);
155 } else {
156 SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
157 ctm.mapPoints(&devLightPos, 1);
158 SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
159 rec.fLightPos.fZ, rec.fLightRadius,
160 &spotBlur, &spotScale, &spotOffset);
161 }
162 } else {
163 SkScalar devToSrcScale = SkScalarInvert(ctm.getMinScale());
164
165 // get ambient blur (in local space)
166 SkScalar devSpaceAmbientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
167 ambientBlur = devSpaceAmbientBlur*devToSrcScale;
168
169 // get spot params (in local space)
172 rec.fLightPos.fZ, rec.fLightRadius,
173 &spotBlur, &spotScale, &spotOffset);
174 // light dir is in device space, so need to map spot offset back into local space
175 SkMatrix inverse;
176 if (ctm.invert(&inverse)) {
177 inverse.mapVectors(&spotOffset, 1);
178 }
179 } else {
181 rec.fLightPos.fZ, rec.fLightRadius,
182 &spotBlur, &spotScale, &spotOffset);
183 }
184
185 // convert spot blur to local space
186 spotBlur *= devToSrcScale;
187 }
188
189 // in both cases, adjust ambient and spot bounds
190 SkRect spotBounds = ambientBounds;
191 ambientBounds.outset(ambientBlur, ambientBlur);
192 spotBounds.fLeft *= spotScale;
193 spotBounds.fTop *= spotScale;
194 spotBounds.fRight *= spotScale;
195 spotBounds.fBottom *= spotScale;
196 spotBounds.offset(spotOffset.fX, spotOffset.fY);
197 spotBounds.outset(spotBlur, spotBlur);
198
199 // merge bounds
200 *bounds = ambientBounds;
201 bounds->join(spotBounds);
202 // outset a bit to account for floating point error
203 bounds->outset(1, 1);
204
205 // if perspective, transform back to src space
206 if (ctm.hasPerspective()) {
207 // TODO: create tighter mapping from dev rect back to src rect
208 SkMatrix inverse;
209 if (ctm.invert(&inverse)) {
210 inverse.mapRect(bounds);
211 }
212 }
213}
#define SkScalarInvert(x)
Definition: SkScalar.h:73
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
@ kDirectionalLight_ShadowFlag
Definition: SkShadowUtils.h:31
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
void mapVectors(SkVector dst[], const SkVector src[], int count) const
Definition: SkMatrix.cpp:1097
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
SkScalar getMinScale() const
Definition: SkMatrix.cpp:1522
bool hasPerspective() const
Definition: SkMatrix.h:312
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
static SkScalar compute_z(SkScalar x, SkScalar y, const SkPoint3 &params)
void GetDirectionalParams(SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
SkScalar AmbientBlurRadius(SkScalar height)
void GetSpotParams(SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
Optional< SkRect > bounds
Definition: SkRecords.h:189
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: switches.h:57
SkPoint3 fZPlaneParams
SkScalar fX
Definition: SkPoint3.h:16
SkScalar fZ
Definition: SkPoint3.h:16
SkScalar fY
Definition: SkPoint3.h:16
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
void outset(float dx, float dy)
Definition: SkRect.h:1077
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
void offset(float dx, float dy)
Definition: SkRect.h:1016
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15

◆ GetSpotParams()

void SkDrawShadowMetrics::GetSpotParams ( SkScalar  occluderZ,
SkScalar  lightX,
SkScalar  lightY,
SkScalar  lightZ,
SkScalar  lightRadius,
SkScalar blurRadius,
SkScalar scale,
SkVector translate 
)
inline

Definition at line 63 of file SkDrawShadowInfo.h.

65 {
66 SkScalar zRatio = divide_and_pin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);
67 *blurRadius = lightRadius*zRatio;
68 *scale = divide_and_pin(lightZ, lightZ - occluderZ, 1.0f, 1.95f);
69 *translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
70}

◆ GetSpotShadowTransform()

bool SkDrawShadowMetrics::GetSpotShadowTransform ( const SkPoint3 lightPos,
SkScalar  lightRadius,
const SkMatrix ctm,
const SkPoint3 zPlaneParams,
const SkRect pathBounds,
bool  directional,
SkMatrix shadowTransform,
SkScalar radius 
)

Definition at line 22 of file SkDrawShadowInfo.cpp.

25 {
26 auto heightFunc = [zPlaneParams] (SkScalar x, SkScalar y) {
27 return zPlaneParams.fX*x + zPlaneParams.fY*y + zPlaneParams.fZ;
28 };
29 SkScalar occluderHeight = heightFunc(pathBounds.centerX(), pathBounds.centerY());
30
31 // TODO: have directional lights support tilt via the zPlaneParams
32 if (!ctm.hasPerspective() || directional) {
34 SkVector translate;
35 if (directional) {
36 SkDrawShadowMetrics::GetDirectionalParams(occluderHeight, lightPos.fX, lightPos.fY,
37 lightPos.fZ, lightRadius, radius,
38 &scale, &translate);
39 } else {
40 SkDrawShadowMetrics::GetSpotParams(occluderHeight, lightPos.fX, lightPos.fY,
41 lightPos.fZ, lightRadius, radius,
42 &scale, &translate);
43 }
44 shadowTransform->setScaleTranslate(scale, scale, translate.fX, translate.fY);
45 shadowTransform->preConcat(ctm);
46 } else {
47 if (SkScalarNearlyZero(pathBounds.width()) || SkScalarNearlyZero(pathBounds.height())) {
48 return false;
49 }
50
51 // get rotated quad in 3D
52 SkPoint pts[4];
53 ctm.mapRectToQuad(pts, pathBounds);
54
55 SkPoint3 pts3D[4];
56 SkScalar z = heightFunc(pathBounds.fLeft, pathBounds.fTop);
57 pts3D[0].set(pts[0].fX, pts[0].fY, z);
58 z = heightFunc(pathBounds.fRight, pathBounds.fTop);
59 pts3D[1].set(pts[1].fX, pts[1].fY, z);
60 z = heightFunc(pathBounds.fRight, pathBounds.fBottom);
61 pts3D[2].set(pts[2].fX, pts[2].fY, z);
62 z = heightFunc(pathBounds.fLeft, pathBounds.fBottom);
63 pts3D[3].set(pts[3].fX, pts[3].fY, z);
64
65 // project from light through corners to z=0 plane
66 for (int i = 0; i < 4; ++i) {
67 SkScalar dz = lightPos.fZ - pts3D[i].fZ;
68 // light shouldn't be below or at a corner's z-location
69 if (dz <= SK_ScalarNearlyZero) {
70 return false;
71 }
72 SkScalar zRatio = pts3D[i].fZ / dz;
73 pts3D[i].fX -= (lightPos.fX - pts3D[i].fX)*zRatio;
74 pts3D[i].fY -= (lightPos.fY - pts3D[i].fY)*zRatio;
75 pts3D[i].fZ = SK_Scalar1;
76 }
77
78 // Generate matrix that projects from [-1,1]x[-1,1] square to projected quad
79 SkPoint3 h0, h1, h2;
80 // Compute homogenous crossing point between top and bottom edges (gives new x-axis).
81 h0 = (pts3D[1].cross(pts3D[0])).cross(pts3D[2].cross(pts3D[3]));
82 // Compute homogenous crossing point between left and right edges (gives new y-axis).
83 h1 = (pts3D[0].cross(pts3D[3])).cross(pts3D[1].cross(pts3D[2]));
84 // Compute homogenous crossing point between diagonals (gives new origin).
85 h2 = (pts3D[0].cross(pts3D[2])).cross(pts3D[1].cross(pts3D[3]));
86 // If h2 is a vector (z=0 in 2D homogeneous space), that means that at least
87 // two of the quad corners are coincident and we don't have a realistic projection
88 if (SkScalarNearlyZero(h2.fZ)) {
89 return false;
90 }
91 // In some cases the crossing points are in the wrong direction
92 // to map (-1,-1) to pts3D[0], so we need to correct for that.
93 // Want h0 to be to the right of the left edge.
94 SkVector3 v = pts3D[3] - pts3D[0];
95 SkVector3 w = h0 - pts3D[0];
96 SkScalar perpDot = v.fX*w.fY - v.fY*w.fX;
97 if (perpDot > 0) {
98 h0 = -h0;
99 }
100 // Want h1 to be above the bottom edge.
101 v = pts3D[1] - pts3D[0];
102 perpDot = v.fX*w.fY - v.fY*w.fX;
103 if (perpDot < 0) {
104 h1 = -h1;
105 }
106 shadowTransform->setAll(h0.fX / h2.fZ, h1.fX / h2.fZ, h2.fX / h2.fZ,
107 h0.fY / h2.fZ, h1.fY / h2.fZ, h2.fY / h2.fZ,
108 h0.fZ / h2.fZ, h1.fZ / h2.fZ, 1);
109 // generate matrix that transforms from bounds to [-1,1]x[-1,1] square
110 SkMatrix toHomogeneous;
111 SkScalar xScale = 2/(pathBounds.fRight - pathBounds.fLeft);
112 SkScalar yScale = 2/(pathBounds.fBottom - pathBounds.fTop);
113 toHomogeneous.setAll(xScale, 0, -xScale*pathBounds.fLeft - 1,
114 0, yScale, -yScale*pathBounds.fTop - 1,
115 0, 0, 1);
116 shadowTransform->preConcat(toHomogeneous);
117
118 *radius = SkDrawShadowMetrics::SpotBlurRadius(occluderHeight, lightPos.fZ, lightRadius);
119 }
120
121 return true;
122}
#define SK_Scalar1
Definition: SkScalar.h:18
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition: SkMatrix.h:562
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
Definition: SkMatrix.h:1803
SkMatrix & preConcat(const SkMatrix &other)
Definition: SkMatrix.cpp:674
void mapRectToQuad(SkPoint dst[4], const SkRect &rect) const
Definition: SkMatrix.h:1620
SkScalar SpotBlurRadius(SkScalar occluderZ, SkScalar lightZ, SkScalar lightRadius)
int64_t cross(Point d0, Point d1)
Definition: Myers.cpp:55
SkScalar w
SkPoint3 cross(const SkPoint3 &vec) const
Definition: SkPoint3.h:141
void set(SkScalar x, SkScalar y, SkScalar z)
Definition: SkPoint3.h:28
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float height() const
Definition: SkRect.h:769
constexpr float centerY() const
Definition: SkRect.h:785
constexpr float width() const
Definition: SkRect.h:762

◆ SpotBlurRadius()

SkScalar SkDrawShadowMetrics::SpotBlurRadius ( SkScalar  occluderZ,
SkScalar  lightZ,
SkScalar  lightRadius 
)
inline

Definition at line 59 of file SkDrawShadowInfo.h.

59 {
60 return lightRadius*divide_and_pin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);
61}

Variable Documentation

◆ kAmbientGeomFactor

constexpr auto SkDrawShadowMetrics::kAmbientGeomFactor = 64.0f
staticconstexpr

Definition at line 38 of file SkDrawShadowInfo.h.

◆ kAmbientHeightFactor

constexpr auto SkDrawShadowMetrics::kAmbientHeightFactor = 1.0f / 128.0f
staticconstexpr

Definition at line 37 of file SkDrawShadowInfo.h.

◆ kMaxAmbientRadius

constexpr auto SkDrawShadowMetrics::kMaxAmbientRadius = 300*kAmbientHeightFactor*kAmbientGeomFactor
staticconstexpr

Definition at line 42 of file SkDrawShadowInfo.h.