Flutter Engine
The Flutter Engine
Public Member Functions | Public Attributes | List of all members
LocalCornerVert Struct Reference

Public Member Functions

SkV3 transform (const SkM44 &m, const SkV4 &cornerMapping, const SkV2 &cornerPt, const SkV2 &cornerRadii, const SkV4 &devCenter, float centerWeight, float strokeRadius, float joinScale, float localAARadius) const
 

Public Attributes

SkV2 fPosition
 
SkV2 fNormal
 
float fStrokeScale
 
float fMirrorScale
 
float fCenterWeight
 

Detailed Description

Definition at line 107 of file GraphitePrimitivesSlide.cpp.

Member Function Documentation

◆ transform()

SkV3 LocalCornerVert::transform ( const SkM44 m,
const SkV4 cornerMapping,
const SkV2 cornerPt,
const SkV2 cornerRadii,
const SkV4 devCenter,
float  centerWeight,
float  strokeRadius,
float  joinScale,
float  localAARadius 
) const
inline

Definition at line 117 of file GraphitePrimitivesSlide.cpp.

119 {
120 const bool snapToCenter = centerWeight + fCenterWeight > 0.f;
121 if (snapToCenter) {
122 return {devCenter.x, devCenter.y, devCenter.w};
123 } else {
124 // Normalized position before any additional AA offsets
125 SkV2 normalizedPos = fPosition + joinScale*fMirrorScale*SkV2{fPosition.y, fPosition.x};
126 // scales the normalized unit corner to the actual radii of the corner, before any AA
127 // offsets are added.
128 SkV2 scale = cornerRadii + SkV2{fStrokeScale*strokeRadius, fStrokeScale*strokeRadius};
129 normalizedPos = scale*normalizedPos - cornerRadii;
130
131 if (fStrokeScale < 0.f) {
132 // An inset, which means it might cross over or might be forced to the center
133 SkV2 maxInset = scale - SkV2{localAARadius, localAARadius};
134 if (maxInset.x < 0.f || maxInset.y < 0.f) {
135 normalizedPos =
136 SkV2{std::min(maxInset.x, 0.f), std::min(maxInset.y, 0.f)}
137 - cornerRadii;
138 } else {
139 normalizedPos += localAARadius * fNormal;
140 }
141 } // else no normal offsetting, or device-space offsetting
142
143 SkV2 localPos =
144 {cornerMapping.x*normalizedPos.x + cornerMapping.y*normalizedPos.y + cornerPt.x,
145 cornerMapping.z*normalizedPos.x + cornerMapping.w*normalizedPos.y + cornerPt.y};
146 SkV4 devPos = m.map(localPos.x, localPos.y, 0.f, 1.f);
147
148 const bool deviceSpaceNormal =
149 fStrokeScale > 0.f && (fNormal.x > 0.f || fNormal.y > 0.f);
150 if (deviceSpaceNormal) {
151 SkV2 devNorm;
152 {
153 // To calculate a device-space normal, we use the normal matrix (A^-1)^T where
154 // A is CTM * T(cornerPt) * cornerMapping * scale. We inline the calculation
155 // of (T(cornerPt)*cornerMapping*scale)^-1^T * [nx, ny, 0, 0] = N', which means
156 // that CTM^-1^T * N' is equivalent to N'^T*CTM^-1, which can be calculated with
157 // two dot products if the CTM inverse is uploaded to the GPU.
158
159 // We add epsilon so that rectangular corners are not degenerate, and circular
160 // corners remain unmodified. This only slightly increases inaccuracy for
161 // elliptical corners.
162 float sx = (scale.y + SK_ScalarNearlyZero) / (scale.x + SK_ScalarNearlyZero);
163 // Needed to calculate intermediate W of transformed normal.
164 float px = cornerMapping.y*cornerPt.y - cornerMapping.w*cornerPt.x;
165 float py = cornerMapping.z*cornerPt.x - cornerMapping.x*cornerPt.y;
166 // Inverse CTM, presumably calculated once as a uniform
167 SkM44 inv;
168 SkAssertResult(m.invert(&inv));
169
170 SkV4 normX4 = { sx*cornerMapping.w*fNormal.x,
171 -sx*cornerMapping.y*fNormal.x,
172 0.f,
173 sx*px*fNormal.x};
174 SkV4 normY4 = {-cornerMapping.z*fNormal.y,
175 cornerMapping.x*fNormal.y,
176 0.f,
177 py*fNormal.y};
178
179 SkV2 normX = {inv.col(0).dot(normX4), inv.col(1).dot(normX4)};
180 SkV2 normY = {inv.col(0).dot(normY4), inv.col(1).dot(normY4)};
181
182 if (joinScale == kMiterScale && fNormal.x > 0.f && fNormal.y > 0.f) {
183 // normX and normY represent adjacent edges' normals, so if we normalize
184 // them before adding together, we'll have a vector that bisects the edge
185 // normals instead of a vector matching fNormal, which is what we want when
186 // we're at a miter corner.
187 normX = normX.normalize();
188 normY = normY.normalize();
189 if (normX.dot(normY) < -0.8) {
190 // Nearly opposite directions, so the sum could have cancellation, so
191 // instead bisect orthogonal vectors and flip to keep consistent
192 float sign = normX.cross(normY) >= 0.f ? 1.f : -1.f;
193 normX = sign*SkV2{-normX.y, normX.x};
194 normY = sign*SkV2{normY.y, -normY.x};
195 }
196 }
197
198 devNorm = (normX + normY).normalize();
199 }
200
201 // The local coordinates for a device-space AA outset are clamped to the non-outset
202 // point, which means we don't care about remaining in the same pre-homogenous
203 // divide plane. This makes it very easy to determine a homogenous coordinate that
204 // projects to the correct device-space position.
205 devPos.x += devPos.w * kAARadius * devNorm.x;
206 devPos.y += devPos.w * kAARadius * devNorm.y;
207 }
208
209 return SkV3{devPos.x, devPos.y, devPos.w};
210 }
211 }
static SkM44 inv(const SkM44 &m)
Definition: 3d.cpp:26
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static constexpr float kMiterScale
static constexpr float kAARadius
static int sign(SkScalar x)
Definition: SkPath.cpp:2205
#define SK_ScalarNearlyZero
Definition: SkScalar.h:99
Definition: SkM44.h:150
SkV4 col(int i) const
Definition: SkM44.h:276
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SIN Vec< N, float > normalize(const Vec< N, float > &v)
Definition: SkVx.h:995
const Scalar scale
Definition: SkM44.h:19
SkV2 normalize() const
Definition: SkM44.h:50
SkScalar dot(SkV2 v) const
Definition: SkM44.h:48
float x
Definition: SkM44.h:20
float y
Definition: SkM44.h:20
SkScalar cross(SkV2 v) const
Definition: SkM44.h:49
Definition: SkM44.h:56
Definition: SkM44.h:98
float w
Definition: SkM44.h:99
SkScalar dot(const SkV4 &v) const
Definition: SkM44.h:126
float y
Definition: SkM44.h:99
float x
Definition: SkM44.h:99
float z
Definition: SkM44.h:99

Member Data Documentation

◆ fCenterWeight

float LocalCornerVert::fCenterWeight

Definition at line 113 of file GraphitePrimitivesSlide.cpp.

◆ fMirrorScale

float LocalCornerVert::fMirrorScale

Definition at line 112 of file GraphitePrimitivesSlide.cpp.

◆ fNormal

SkV2 LocalCornerVert::fNormal

Definition at line 109 of file GraphitePrimitivesSlide.cpp.

◆ fPosition

SkV2 LocalCornerVert::fPosition

Definition at line 108 of file GraphitePrimitivesSlide.cpp.

◆ fStrokeScale

float LocalCornerVert::fStrokeScale

Definition at line 111 of file GraphitePrimitivesSlide.cpp.


The documentation for this struct was generated from the following file: