61 {
62 if (stroke_width_ < 0.0) {
63 return {};
64 }
65 Scalar max_basis = entity.GetTransform().GetMaxBasisLengthXY();
66 if (max_basis == 0) {
67 return {};
68 }
69
71 Scalar stroke_width = std::max(stroke_width_, min_size);
72 Scalar half_stroke_width = stroke_width * 0.5f;
73
74 auto& data_host_buffer = renderer.GetTransientsDataBuffer();
75 const Rect& rect = rect_;
76 bool interior_filled = (stroke_width >= rect.GetSize().MinDimension());
77
78 switch (stroke_join_) {
80 Tessellator::Trigs trigs =
81 renderer.GetTessellator().GetTrigsForDeviceRadius(half_stroke_width *
82 max_basis);
83
85
86 auto vertex_count = trigs.size() * 4;
87 if (!interior_filled) {
88
89
90
91 vertex_count += 12;
92 }
93
94 return GeometryResult{
96 .vertex_buffer =
97 {
98 .vertex_buffer = data_host_buffer.Emplace(
100 [hsw = half_stroke_width, &rect, vertex_count, &trigs,
101 interior_filled](uint8_t* buffer) {
103 Scalar top = rect.GetTop();
105 Scalar bottom = rect.GetBottom();
106
108 [[maybe_unused]]
109 auto vertices_end = vertices + vertex_count;
110
111
112
113
114 for (auto trig : trigs) {
115
116
117 *vertices++ =
Point(left - trig.sin * hsw,
118 top - trig.cos * hsw);
119 *vertices++ =
Point(right + trig.sin * hsw,
120 top - trig.cos * hsw);
121 }
122
123
124
125
126
127 if (interior_filled) {
128
129
130
131
132
133
134 } else {
135
136
137
138 *vertices++ =
Point(left - hsw, top + hsw);
139 *vertices++ =
Point(right + hsw, top + hsw);
140
141
142
143
144
145
146
147
148
149
150
151 *vertices++ =
Point(right - hsw, top + hsw);
152 *vertices++ =
Point(right + hsw, bottom - hsw);
153 *vertices++ =
Point(right - hsw, bottom - hsw);
154
155
156
157
158
159 *vertices++ =
Point(right - hsw, bottom - hsw);
160 *vertices++ =
Point(left + hsw, top + hsw);
161
162
163
164
165
166 *vertices++ =
Point(left + hsw, top + hsw);
167 *vertices++ =
Point(left - hsw, top + hsw);
168 *vertices++ =
Point(left + hsw, bottom - hsw);
169 *vertices++ =
Point(left - hsw, bottom - hsw);
170
171
172
173
174
175
176
177
178
179
180
181
182 *vertices++ =
Point(right + hsw, bottom - hsw);
183
184
185
186 }
187
188
189 for (auto trig : trigs) {
190
191
192 *vertices++ =
Point(left - trig.cos * hsw,
193 bottom + trig.sin * hsw);
194 *vertices++ =
Point(right + trig.cos * hsw,
195 bottom + trig.sin * hsw);
196 }
197
198
200 }),
201 .vertex_count = vertex_count,
203 },
204 .transform = entity.GetShaderTransform(pass),
206 };
207 }
208
210 if (interior_filled) {
211 return GeometryResult{
213 .vertex_buffer =
214 {
215 .vertex_buffer = data_host_buffer.Emplace(
217 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
219 Scalar top = rect.GetTop();
221 Scalar bottom = rect.GetBottom();
223 vertices[0] =
Point(left, top - hsw);
224 vertices[1] =
Point(right, top - hsw);
225 vertices[2] =
Point(left - hsw, top);
226 vertices[3] =
Point(right + hsw, top);
227 vertices[4] =
Point(left - hsw, bottom);
228 vertices[5] =
Point(right + hsw, bottom);
229 vertices[6] =
Point(left, bottom + hsw);
230 vertices[7] =
Point(right, bottom + hsw);
231 }),
232 .vertex_count = 8u,
234 },
235 .transform = entity.GetShaderTransform(pass),
237 };
238 }
239 return GeometryResult{
241 .vertex_buffer =
242 {
243 .vertex_buffer = data_host_buffer.Emplace(
245 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
247 Scalar top = rect.GetTop();
249 Scalar bottom = rect.GetBottom();
251 vertices[0] =
Point(left - hsw, top);
252 vertices[1] =
Point(left + hsw, top + hsw);
253 vertices[2] =
Point(left, top - hsw);
254 vertices[3] =
Point(right - hsw, top + hsw);
255 vertices[4] =
Point(right, top - hsw);
256 vertices[5] =
Point(right - hsw, top + hsw);
257 vertices[6] =
Point(right + hsw, top);
258 vertices[7] =
Point(right - hsw, bottom - hsw);
259 vertices[8] =
Point(right + hsw, bottom);
260 vertices[9] =
Point(right - hsw, bottom - hsw);
261 vertices[10] =
Point(right, bottom + hsw);
262 vertices[11] =
Point(left + hsw, bottom - hsw);
263 vertices[12] =
Point(left, bottom + hsw);
264 vertices[13] =
Point(left + hsw, bottom - hsw);
265 vertices[14] =
Point(left - hsw, bottom);
266 vertices[15] =
Point(left + hsw, top + hsw);
267 vertices[16] =
Point(left - hsw, top);
268 }),
269 .vertex_count = 17u,
271 },
272 .transform = entity.GetShaderTransform(pass),
274 };
275 }
276
278 if (interior_filled) {
279 return GeometryResult{
281 .vertex_buffer =
282 {
283 .vertex_buffer = data_host_buffer.Emplace(
285 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
287 Scalar top = rect.GetTop();
289 Scalar bottom = rect.GetBottom();
291
292 vertices[0] =
Point(left - hsw, top - hsw);
293 vertices[1] =
Point(right + hsw, top - hsw);
294 vertices[2] =
Point(left - hsw, bottom + hsw);
295 vertices[3] =
Point(right + hsw, bottom + hsw);
296 }),
297 .vertex_count = 4u,
299 },
300 .transform = entity.GetShaderTransform(pass),
302 };
303 }
304 return GeometryResult{
306 .vertex_buffer =
307 {
308 .vertex_buffer = data_host_buffer.Emplace(
310 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
312 Scalar top = rect.GetTop();
314 Scalar bottom = rect.GetBottom();
316 vertices[0] =
Point(left - hsw, top - hsw);
317 vertices[1] =
Point(left + hsw, top + hsw);
318 vertices[2] =
Point(right + hsw, top - hsw);
319 vertices[3] =
Point(right - hsw, top + hsw);
320 vertices[4] =
Point(right + hsw, bottom + hsw);
321 vertices[5] =
Point(right - hsw, bottom - hsw);
322 vertices[6] =
Point(left - hsw, bottom + hsw);
323 vertices[7] =
Point(left + hsw, bottom - hsw);
324 vertices[8] =
Point(left - hsw, top - hsw);
325 vertices[9] =
Point(left + hsw, top + hsw);
326 }),
327 .vertex_count = 10u,
329 },
330 .transform = entity.GetShaderTransform(pass),
332 };
333 }
334 }
335}
#define FML_DCHECK(condition)
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
@ kNone
Does not use the index buffer.
static constexpr Scalar kMinStrokeSize
@ kNormal
The geometry has no overlapping triangles.