| Flutter Impeller |

path_component.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 "path_component.h"
6
7 #include <cmath>
8 #include <utility>
9
10 #include "flutter/fml/logging.h"
11 #include "flutter/impeller/geometry/scalar.h"
12 #include "flutter/impeller/geometry/wangs_formula.h"
13
14 namespace impeller {
15
16 /////////// FanVertexWriter ///////////
17
18 FanVertexWriter::FanVertexWriter(Point* point_buffer, uint16_t* index_buffer)
19 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
20
21 FanVertexWriter::~FanVertexWriter() = default;
22
23 size_t FanVertexWriter::GetIndexCount() const {
24 return index_count_;
25 }
26
27 void FanVertexWriter::EndContour() {
28 if (count_ == 0) {
29 return;
30 }
31 index_buffer_[index_count_++] = 0xFFFF;
32 }
33
34 void FanVertexWriter::Write(Point point) {
35 index_buffer_[index_count_++] = count_;
36 point_buffer_[count_++] = point;
37 }
38
39 /////////// StripVertexWriter ///////////
40
41 StripVertexWriter::StripVertexWriter(Point* point_buffer,
42 uint16_t* index_buffer)
43 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
44
45 StripVertexWriter::~StripVertexWriter() = default;
46
47 size_t StripVertexWriter::GetIndexCount() const {
48 return index_count_;
49 }
50
51 void StripVertexWriter::EndContour() {
52 if (count_ == 0u || contour_start_ == count_ - 1) {
53 // Empty or first contour.
54 return;
55 }
56
57 size_t start = contour_start_;
58 size_t end = count_ - 1;
59
60 index_buffer_[index_count_++] = start;
61
62 size_t a = start + 1;
63 size_t b = end;
64 while (a < b) {
65 index_buffer_[index_count_++] = a;
66 index_buffer_[index_count_++] = b;
67 a++;
68 b--;
69 }
70 if (a == b) {
71 index_buffer_[index_count_++] = a;
72 }
73
74 contour_start_ = count_;
75 index_buffer_[index_count_++] = 0xFFFF;
76 }
77
78 void StripVertexWriter::Write(Point point) {
79 point_buffer_[count_++] = point;
80 }
81
82 /////////// LineStripVertexWriter ////////
83
84 LineStripVertexWriter::LineStripVertexWriter(std::vector<Point>& points)
85 : points_(points) {}
86
87 void LineStripVertexWriter::EndContour() {}
88
89 void LineStripVertexWriter::Write(Point point) {
90 if (offset_ >= points_.size()) {
91 overflow_.push_back(point);
92 } else {
93 points_[offset_++] = point;
94 }
95 }
96
97 const std::vector<Point>& LineStripVertexWriter::GetOversizedBuffer() const {
98 return overflow_;
99 }
100
101 std::pair<size_t, size_t> LineStripVertexWriter::GetVertexCount() const {
102 return std::make_pair(offset_, overflow_.size());
103 }
104
105 /////////// GLESVertexWriter ///////////
106
107 GLESVertexWriter::GLESVertexWriter(std::vector<Point>& points,
108 std::vector<uint16_t>& indices)
109 : points_(points), indices_(indices) {}
110
111 void GLESVertexWriter::EndContour() {
112 if (points_.size() == 0u || contour_start_ == points_.size() - 1) {
113 // Empty or first contour.
114 return;
115 }
116
117 auto start = contour_start_;
118 auto end = points_.size() - 1;
119 // All filled paths are drawn as if they are closed, but if
120 // there is an explicit close then a lineTo to the origin
121 // is inserted. This point isn't strictly necesary to
122 // correctly render the shape and can be dropped.
123 if (points_[end] == points_[start]) {
124 end--;
125 }
126
127 // Triangle strip break for subsequent contours
128 if (contour_start_ != 0) {
129 auto back = indices_.back();
130 indices_.push_back(back);
131 indices_.push_back(start);
132 indices_.push_back(start);
133
134 // If the contour has an odd number of points, insert an extra point when
135 // bridging to the next contour to preserve the correct triangle winding
136 // order.
137 if (previous_contour_odd_points_) {
138 indices_.push_back(start);
139 }
140 } else {
141 indices_.push_back(start);
142 }
143
144 size_t a = start + 1;
145 size_t b = end;
146 while (a < b) {
147 indices_.push_back(a);
148 indices_.push_back(b);
149 a++;
150 b--;
151 }
152 if (a == b) {
153 indices_.push_back(a);
154 previous_contour_odd_points_ = false;
155 } else {
156 previous_contour_odd_points_ = true;
157 }
158 contour_start_ = points_.size();
159 }
160
161 void GLESVertexWriter::Write(Point point) {
162 points_.push_back(point);
163 }
164
165 /*
166 * Based on: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Specific_cases
167 */
168
169 static inline Scalar LinearSolve(Scalar t, Scalar p0, Scalar p1) {
170 return p0 + t * (p1 - p0);
171 }
172
173 static inline Scalar QuadraticSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2) {
174 return (1 - t) * (1 - t) * p0 + //
175 2 * (1 - t) * t * p1 + //
176 t * t * p2;
177 }
178
179 static inline Scalar QuadraticSolveDerivative(Scalar t,
180 Scalar p0,
181 Scalar p1,
182 Scalar p2) {
183 return 2 * (1 - t) * (p1 - p0) + //
184 2 * t * (p2 - p1);
185 }
186
187 static inline Scalar ConicSolve(Scalar t,
188 Scalar p0,
189 Scalar p1,
190 Scalar p2,
191 Scalar w) {
192 auto u = (1 - t);
193 auto coefficient_p0 = u * u;
194 auto coefficient_p1 = 2 * t * u * w;
195 auto coefficient_p2 = t * t;
196
197 return ((p0 * coefficient_p0 + p1 * coefficient_p1 + p2 * coefficient_p2) /
198 (coefficient_p0 + coefficient_p1 + coefficient_p2));
199 }
200
201 static inline Scalar CubicSolve(Scalar t,
202 Scalar p0,
203 Scalar p1,
204 Scalar p2,
205 Scalar p3) {
206 return (1 - t) * (1 - t) * (1 - t) * p0 + //
207 3 * (1 - t) * (1 - t) * t * p1 + //
208 3 * (1 - t) * t * t * p2 + //
209 t * t * t * p3;
210 }
211
212 static inline Scalar CubicSolveDerivative(Scalar t,
213 Scalar p0,
214 Scalar p1,
215 Scalar p2,
216 Scalar p3) {
217 return -3 * p0 * (1 - t) * (1 - t) + //
218 p1 * (3 * (1 - t) * (1 - t) - 6 * (1 - t) * t) +
219 p2 * (6 * (1 - t) * t - 3 * t * t) + //
220 3 * p3 * t * t;
221 }
222
223 Point LinearPathComponent::Solve(Scalar time) const {
224 return {
225 LinearSolve(time, p1.x, p2.x), // x
226 LinearSolve(time, p1.y, p2.y), // y
227 };
228 }
229
230 void LinearPathComponent::AppendPolylinePoints(
231 std::vector<Point>& points) const {
232 if (points.size() == 0 || points.back() != p2) {
233 points.push_back(p2);
234 }
235 }
236
237 std::vector<Point> LinearPathComponent::Extrema() const {
238 return {p1, p2};
239 }
240
241 std::optional<Vector2> LinearPathComponent::GetStartDirection() const {
242 if (p1 == p2) {
243 return std::nullopt;
244 }
245 return (p1 - p2).Normalize();
246 }
247
248 std::optional<Vector2> LinearPathComponent::GetEndDirection() const {
249 if (p1 == p2) {
250 return std::nullopt;
251 }
252 return (p2 - p1).Normalize();
253 }
254
255 Point QuadraticPathComponent::Solve(Scalar time) const {
256 return {
257 QuadraticSolve(time, p1.x, cp.x, p2.x), // x
258 QuadraticSolve(time, p1.y, cp.y, p2.y), // y
259 };
260 }
261
262 Point QuadraticPathComponent::SolveDerivative(Scalar time) const {
263 return {
264 QuadraticSolveDerivative(time, p1.x, cp.x, p2.x), // x
265 QuadraticSolveDerivative(time, p1.y, cp.y, p2.y), // y
266 };
267 }
268
269 void QuadraticPathComponent::ToLinearPathComponents(
270 Scalar scale,
271 VertexWriter& writer) const {
272 Scalar line_count = std::ceilf(ComputeQuadradicSubdivisions(scale, *this));
273 for (size_t i = 1; i < line_count; i += 1) {
274 writer.Write(Solve(i / line_count));
275 }
276 writer.Write(p2);
277 }
278
279 void QuadraticPathComponent::AppendPolylinePoints(
280 Scalar scale_factor,
281 std::vector<Point>& points) const {
282 ToLinearPathComponents(scale_factor, [&points](const Point& point) {
283 points.emplace_back(point);
284 });
285 }
286
287 void QuadraticPathComponent::ToLinearPathComponents(
288 Scalar scale_factor,
289 const PointProc& proc) const {
290 Scalar line_count =
291 std::ceilf(ComputeQuadradicSubdivisions(scale_factor, *this));
292 for (size_t i = 1; i < line_count; i += 1) {
293 proc(Solve(i / line_count));
294 }
295 proc(p2);
296 }
297
298 size_t QuadraticPathComponent::CountLinearPathComponents(Scalar scale) const {
299 return std::ceilf(ComputeQuadradicSubdivisions(scale, *this)) + 2;
300 }
301
302 std::vector<Point> QuadraticPathComponent::Extrema() const {
303 CubicPathComponent elevated(*this);
304 return elevated.Extrema();
305 }
306
307 std::optional<Vector2> QuadraticPathComponent::GetStartDirection() const {
308 if (p1 != cp) {
309 return (p1 - cp).Normalize();
310 }
311 if (p1 != p2) {
312 return (p1 - p2).Normalize();
313 }
314 return std::nullopt;
315 }
316
317 std::optional<Vector2> QuadraticPathComponent::GetEndDirection() const {
318 if (p2 != cp) {
319 return (p2 - cp).Normalize();
320 }
321 if (p2 != p1) {
322 return (p2 - p1).Normalize();
323 }
324 return std::nullopt;
325 }
326
327 Point ConicPathComponent::Solve(Scalar time) const {
328 return {
329 ConicSolve(time, p1.x, cp.x, p2.x, weight.x), // x
330 ConicSolve(time, p1.y, cp.y, p2.y, weight.y), // y
331 };
332 }
333
334 void ConicPathComponent::ToLinearPathComponents(Scalar scale_factor,
335 const PointProc& proc) const {
336 Scalar line_count = std::ceilf(ComputeConicSubdivisions(scale_factor, *this));
337 for (size_t i = 1; i < line_count; i += 1) {
338 proc(Solve(i / line_count));
339 }
340 proc(p2);
341 }
342
343 void ConicPathComponent::AppendPolylinePoints(
344 Scalar scale_factor,
345 std::vector<Point>& points) const {
346 ToLinearPathComponents(scale_factor, [&points](const Point& point) {
347 if (point != points.back()) {
348 points.emplace_back(point);
349 }
350 });
351 }
352
353 void ConicPathComponent::ToLinearPathComponents(Scalar scale,
354 VertexWriter& writer) const {
355 Scalar line_count = std::ceilf(ComputeConicSubdivisions(scale, *this));
356 for (size_t i = 1; i < line_count; i += 1) {
357 writer.Write(Solve(i / line_count));
358 }
359 writer.Write(p2);
360 }
361
362 size_t ConicPathComponent::CountLinearPathComponents(Scalar scale) const {
363 return std::ceilf(ComputeConicSubdivisions(scale, *this)) + 2;
364 }
365
366 std::vector<Point> ConicPathComponent::Extrema() const {
367 std::vector<Point> points;
368 for (auto quad : ToQuadraticPathComponents()) {
369 auto quad_extrema = quad.Extrema();
370 points.insert(points.end(), quad_extrema.begin(), quad_extrema.end());
371 }
372 return points;
373 }
374
375 std::optional<Vector2> ConicPathComponent::GetStartDirection() const {
376 if (p1 != cp) {
377 return (p1 - cp).Normalize();
378 }
379 if (p1 != p2) {
380 return (p1 - p2).Normalize();
381 }
382 return std::nullopt;
383 }
384
385 std::optional<Vector2> ConicPathComponent::GetEndDirection() const {
386 if (p2 != cp) {
387 return (p2 - cp).Normalize();
388 }
389 if (p2 != p1) {
390 return (p2 - p1).Normalize();
391 }
392 return std::nullopt;
393 }
394
395 void ConicPathComponent::SubdivideToQuadraticPoints(
396 std::array<Point, 5>& points) const {
397 FML_DCHECK(weight.IsFinite() && weight.x > 0 && weight.y > 0);
398
399 // Observe that scale will always be smaller than 1 because weight > 0.
400 const Scalar scale = 1.0f / (1.0f + weight.x);
401
402 // The subdivided control points below are the sums of the following three
403 // terms. Because the terms are multiplied by something <1, and the resulting
404 // control points lie within the control points of the original then the
405 // terms and the sums below will not overflow. Note that weight * scale
406 // approaches 1 as weight becomes very large.
407 Point tp1 = p1 * scale;
408 Point tcp = cp * (weight.x * scale);
409 Point tp2 = p2 * scale;
410
411 // Calculate the subdivided control points
412 Point sub_cp1 = tp1 + tcp;
413 Point sub_cp2 = tcp + tp2;
414
415 // The middle point shared by the 2 sub-divisions, the interpolation of
416 // the original curve at its halfway point.
417 Point sub_mid = (tp1 + tcp + tcp + tp2) * 0.5f;
418
419 FML_DCHECK(sub_cp1.IsFinite() && sub_mid.IsFinite() && sub_cp2.IsFinite());
420
421 points[0] = p1;
422 points[1] = sub_cp1;
423 points[2] = sub_mid;
424 points[3] = sub_cp2;
425 points[4] = p2;
426
427 // Update w.
428 // Currently this method only subdivides a single time directly to 2
429 // quadratics, but if we eventually want to keep the weights for further
430 // subdivision, this was the code that did it in Skia:
431 // sub_w1 = sub_w2 = SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf)
432 }
433
434 std::array<QuadraticPathComponent, 2>
435 ConicPathComponent::ToQuadraticPathComponents() const {
436 std::array<Point, 5> points;
437 SubdivideToQuadraticPoints(points);
438
439 return {
440 QuadraticPathComponent(points[0], points[1], points[2]),
441 QuadraticPathComponent(points[2], points[3], points[4]),
442 };
443 }
444
445 Point CubicPathComponent::Solve(Scalar time) const {
446 return {
447 CubicSolve(time, p1.x, cp1.x, cp2.x, p2.x), // x
448 CubicSolve(time, p1.y, cp1.y, cp2.y, p2.y), // y
449 };
450 }
451
452 Point CubicPathComponent::SolveDerivative(Scalar time) const {
453 return {
454 CubicSolveDerivative(time, p1.x, cp1.x, cp2.x, p2.x), // x
455 CubicSolveDerivative(time, p1.y, cp1.y, cp2.y, p2.y), // y
456 };
457 }
458
459 void CubicPathComponent::AppendPolylinePoints(
460 Scalar scale,
461 std::vector<Point>& points) const {
462 ToLinearPathComponents(
463 scale, [&points](const Point& point) { points.emplace_back(point); });
464 }
465
466 void CubicPathComponent::ToLinearPathComponents(Scalar scale,
467 VertexWriter& writer) const {
468 Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, *this));
469 for (size_t i = 1; i < line_count; i++) {
470 writer.Write(Solve(i / line_count));
471 }
472 writer.Write(p2);
473 }
474
475 size_t CubicPathComponent::CountLinearPathComponents(Scalar scale) const {
476 return std::ceilf(ComputeCubicSubdivisions(scale, *this)) + 2;
477 }
478
479 inline QuadraticPathComponent CubicPathComponent::Lower() const {
480 return QuadraticPathComponent(3.0 * (cp1 - p1), 3.0 * (cp2 - cp1),
481 3.0 * (p2 - cp2));
482 }
483
484 CubicPathComponent CubicPathComponent::Subsegment(Scalar t0, Scalar t1) const {
485 auto p0 = Solve(t0);
486 auto p3 = Solve(t1);
487 auto d = Lower();
488 auto scale = (t1 - t0) * (1.0 / 3.0);
489 auto p1 = p0 + scale * d.Solve(t0);
490 auto p2 = p3 - scale * d.Solve(t1);
491 return CubicPathComponent(p0, p1, p2, p3);
492 }
493
494 void CubicPathComponent::ToLinearPathComponents(Scalar scale,
495 const PointProc& proc) const {
496 Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, *this));
497 for (size_t i = 1; i < line_count; i++) {
498 proc(Solve(i / line_count));
499 }
500 proc(p2);
501 }
502
503 static inline bool NearEqual(Scalar a, Scalar b, Scalar epsilon) {
504 return (a > (b - epsilon)) && (a < (b + epsilon));
505 }
506
507 static inline bool NearZero(Scalar a) {
508 return NearEqual(a, 0.0, 1e-12);
509 }
510
511 static void CubicPathBoundingPopulateValues(std::vector<Scalar>& values,
512 Scalar p1,
513 Scalar p2,
514 Scalar p3,
515 Scalar p4) {
516 const Scalar a = 3.0 * (-p1 + 3.0 * p2 - 3.0 * p3 + p4);
517 const Scalar b = 6.0 * (p1 - 2.0 * p2 + p3);
518 const Scalar c = 3.0 * (p2 - p1);
519
520 /*
521 * Boundary conditions.
522 */
523 if (NearZero(a)) {
524 if (NearZero(b)) {
525 return;
526 }
527
528 Scalar t = -c / b;
529 if (t >= 0.0 && t <= 1.0) {
530 values.emplace_back(t);
531 }
532 return;
533 }
534
535 Scalar b2Minus4AC = (b * b) - (4.0 * a * c);
536
537 if (b2Minus4AC < 0.0) {
538 return;
539 }
540
541 Scalar rootB2Minus4AC = ::sqrt(b2Minus4AC);
542
543 /* From Numerical Recipes in C.
544 *
545 * q = -1/2 (b + sign(b) sqrt[b^2 - 4ac])
546 * x1 = q / a
547 * x2 = c / q
548 */
549 Scalar q = (b < 0) ? -(b - rootB2Minus4AC) / 2 : -(b + rootB2Minus4AC) / 2;
550
551 {
552 Scalar t = q / a;
553 if (t >= 0.0 && t <= 1.0) {
554 values.emplace_back(t);
555 }
556 }
557
558 {
559 Scalar t = c / q;
560 if (t >= 0.0 && t <= 1.0) {
561 values.emplace_back(t);
562 }
563 }
564 }
565
566 std::vector<Point> CubicPathComponent::Extrema() const {
567 /*
568 * As described in: https://pomax.github.io/bezierinfo/#extremities
569 */
570 std::vector<Scalar> values;
571
572 CubicPathBoundingPopulateValues(values, p1.x, cp1.x, cp2.x, p2.x);
573 CubicPathBoundingPopulateValues(values, p1.y, cp1.y, cp2.y, p2.y);
574
575 std::vector<Point> points = {p1, p2};
576
577 for (const auto& value : values) {
578 points.emplace_back(Solve(value));
579 }
580
581 return points;
582 }
583
584 std::optional<Vector2> CubicPathComponent::GetStartDirection() const {
585 if (p1 != cp1) {
586 return (p1 - cp1).Normalize();
587 }
588 if (p1 != cp2) {
589 return (p1 - cp2).Normalize();
590 }
591 if (p1 != p2) {
592 return (p1 - p2).Normalize();
593 }
594 return std::nullopt;
595 }
596
597 std::optional<Vector2> CubicPathComponent::GetEndDirection() const {
598 if (p2 != cp2) {
599 return (p2 - cp2).Normalize();
600 }
601 if (p2 != cp1) {
602 return (p2 - cp1).Normalize();
603 }
604 if (p2 != p1) {
605 return (p2 - p1).Normalize();
606 }
607 return std::nullopt;
608 }
609
610 } // namespace impeller
impeller::FanVertexWriter::EndContour
void EndContour() override
Definition: path_component.cc:27
impeller::FanVertexWriter::GetIndexCount
size_t GetIndexCount() const
Definition: path_component.cc:23
impeller::FanVertexWriter::Write
void Write(Point point) override
Definition: path_component.cc:34
impeller::FanVertexWriter::~FanVertexWriter
~FanVertexWriter()
impeller::FanVertexWriter::FanVertexWriter
FanVertexWriter(Point *point_buffer, uint16_t *index_buffer)
Definition: path_component.cc:18
impeller::GLESVertexWriter::GLESVertexWriter
GLESVertexWriter(std::vector< Point > &points, std::vector< uint16_t > &indices)
Definition: path_component.cc:107
impeller::GLESVertexWriter::Write
void Write(Point point) override
Definition: path_component.cc:161
impeller::GLESVertexWriter::EndContour
void EndContour() override
Definition: path_component.cc:111
impeller::LineStripVertexWriter::GetVertexCount
std::pair< size_t, size_t > GetVertexCount() const
Definition: path_component.cc:101
impeller::LineStripVertexWriter::LineStripVertexWriter
LineStripVertexWriter(std::vector< Point > &points)
Definition: path_component.cc:84
impeller::LineStripVertexWriter::Write
void Write(Point point) override
Definition: path_component.cc:89
impeller::LineStripVertexWriter::EndContour
void EndContour() override
Definition: path_component.cc:87
impeller::LineStripVertexWriter::GetOversizedBuffer
const std::vector< Point > & GetOversizedBuffer() const
Definition: path_component.cc:97
impeller::StripVertexWriter::Write
void Write(Point point) override
Definition: path_component.cc:78
impeller::StripVertexWriter::~StripVertexWriter
~StripVertexWriter()
impeller::StripVertexWriter::GetIndexCount
size_t GetIndexCount() const
Definition: path_component.cc:47
impeller::StripVertexWriter::StripVertexWriter
StripVertexWriter(Point *point_buffer, uint16_t *index_buffer)
Definition: path_component.cc:41
impeller::StripVertexWriter::EndContour
void EndContour() override
Definition: path_component.cc:51
impeller::VertexWriter
An interface for generating a multi contour polyline as a triangle strip.
Definition: path_component.h:21
impeller::VertexWriter::Write
virtual void Write(Point point)=0
value
int32_t value
Definition: dl_golden_unittests.cc:459
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller
Definition: allocation.cc:12
impeller::CubicPathBoundingPopulateValues
static void CubicPathBoundingPopulateValues(std::vector< Scalar > &values, Scalar p1, Scalar p2, Scalar p3, Scalar p4)
Definition: path_component.cc:511
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::NearZero
static bool NearZero(Scalar a)
Definition: path_component.cc:507
impeller::ComputeConicSubdivisions
Scalar ComputeConicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Scalar w)
Definition: wangs_formula.cc:48
impeller::LinearSolve
static Scalar LinearSolve(Scalar t, Scalar p0, Scalar p1)
Definition: path_component.cc:169
impeller::CubicSolve
static Scalar CubicSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2, Scalar p3)
Definition: path_component.cc:201
impeller::CubicSolveDerivative
static Scalar CubicSolveDerivative(Scalar t, Scalar p0, Scalar p1, Scalar p2, Scalar p3)
Definition: path_component.cc:212
impeller::ConicSolve
static Scalar ConicSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2, Scalar w)
Definition: path_component.cc:187
impeller::QuadraticSolve
static Scalar QuadraticSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2)
Definition: path_component.cc:173
impeller::QuadraticSolveDerivative
static Scalar QuadraticSolveDerivative(Scalar t, Scalar p0, Scalar p1, Scalar p2)
Definition: path_component.cc:179
impeller::ComputeQuadradicSubdivisions
Scalar ComputeQuadradicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2)
Definition: wangs_formula.cc:34
impeller::ComputeCubicSubdivisions
Scalar ComputeCubicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Point p3)
Definition: wangs_formula.cc:23
impeller::NearEqual
static bool NearEqual(Scalar a, Scalar b, Scalar epsilon)
Definition: path_component.cc:503
path_component.h
scalar.h
scale
const Scalar scale
Definition: stroke_path_geometry.cc:319
impeller::ConicPathComponent::GetEndDirection
std::optional< Vector2 > GetEndDirection() const
Definition: path_component.cc:385
impeller::ConicPathComponent::cp
Point cp
Definition: path_component.h:230
impeller::ConicPathComponent::ToQuadraticPathComponents
std::array< QuadraticPathComponent, 2 > ToQuadraticPathComponents() const
Definition: path_component.cc:435
impeller::ConicPathComponent::CountLinearPathComponents
size_t CountLinearPathComponents(Scalar scale) const
Definition: path_component.cc:362
impeller::ConicPathComponent::Solve
Point Solve(Scalar time) const
Definition: path_component.cc:327
impeller::ConicPathComponent::ToLinearPathComponents
void ToLinearPathComponents(Scalar scale_factor, const PointProc &proc) const
Definition: path_component.cc:334
impeller::ConicPathComponent::Extrema
std::vector< Point > Extrema() const
Definition: path_component.cc:366
impeller::ConicPathComponent::GetStartDirection
std::optional< Vector2 > GetStartDirection() const
Definition: path_component.cc:375
impeller::ConicPathComponent::weight
Point weight
Definition: path_component.h:243
impeller::ConicPathComponent::SubdivideToQuadraticPoints
void SubdivideToQuadraticPoints(std::array< Point, 5 > &points) const
Definition: path_component.cc:395
impeller::ConicPathComponent::p1
Point p1
Definition: path_component.h:228
impeller::ConicPathComponent::p2
Point p2
Definition: path_component.h:232
impeller::ConicPathComponent::PointProc
std::function< void(const Point &point)> PointProc
Definition: path_component.h:255
impeller::ConicPathComponent::AppendPolylinePoints
void AppendPolylinePoints(Scalar scale_factor, std::vector< Point > &points) const
Definition: path_component.cc:343
impeller::CubicPathComponent
Definition: path_component.h:280
impeller::CubicPathComponent::ToLinearPathComponents
void ToLinearPathComponents(Scalar scale, const PointProc &proc) const
Definition: path_component.cc:494
impeller::CubicPathComponent::CountLinearPathComponents
size_t CountLinearPathComponents(Scalar scale) const
Definition: path_component.cc:475
impeller::CubicPathComponent::p1
Point p1
Definition: path_component.h:282
impeller::CubicPathComponent::AppendPolylinePoints
void AppendPolylinePoints(Scalar scale, std::vector< Point > &points) const
Definition: path_component.cc:459
impeller::CubicPathComponent::cp1
Point cp1
Definition: path_component.h:284
impeller::CubicPathComponent::cp2
Point cp2
Definition: path_component.h:286
impeller::CubicPathComponent::PointProc
std::function< void(const Point &point)> PointProc
Definition: path_component.h:309
impeller::CubicPathComponent::Subsegment
CubicPathComponent Subsegment(Scalar t0, Scalar t1) const
Definition: path_component.cc:484
impeller::CubicPathComponent::Solve
Point Solve(Scalar time) const
Definition: path_component.cc:445
impeller::CubicPathComponent::GetStartDirection
std::optional< Vector2 > GetStartDirection() const
Definition: path_component.cc:584
impeller::CubicPathComponent::Extrema
std::vector< Point > Extrema() const
Definition: path_component.cc:566
impeller::CubicPathComponent::p2
Point p2
Definition: path_component.h:288
impeller::CubicPathComponent::GetEndDirection
std::optional< Vector2 > GetEndDirection() const
Definition: path_component.cc:597
impeller::CubicPathComponent::SolveDerivative
Point SolveDerivative(Scalar time) const
Definition: path_component.cc:452
impeller::CubicPathComponent::CubicPathComponent
CubicPathComponent()
Definition: path_component.h:290
impeller::LinearPathComponent::GetEndDirection
std::optional< Vector2 > GetEndDirection() const
Definition: path_component.cc:248
impeller::LinearPathComponent::GetStartDirection
std::optional< Vector2 > GetStartDirection() const
Definition: path_component.cc:241
impeller::LinearPathComponent::Extrema
std::vector< Point > Extrema() const
Definition: path_component.cc:237
impeller::LinearPathComponent::p2
Point p2
Definition: path_component.h:113
impeller::LinearPathComponent::p1
Point p1
Definition: path_component.h:112
impeller::LinearPathComponent::Solve
Point Solve(Scalar time) const
Definition: path_component.cc:223
impeller::LinearPathComponent::AppendPolylinePoints
void AppendPolylinePoints(std::vector< Point > &points) const
Definition: path_component.cc:230
impeller::QuadraticPathComponent
Definition: path_component.h:135
impeller::QuadraticPathComponent::CountLinearPathComponents
size_t CountLinearPathComponents(Scalar scale) const
Definition: path_component.cc:298
impeller::QuadraticPathComponent::GetEndDirection
std::optional< Vector2 > GetEndDirection() const
Definition: path_component.cc:317
impeller::QuadraticPathComponent::p2
Point p2
Definition: path_component.h:141
impeller::QuadraticPathComponent::AppendPolylinePoints
void AppendPolylinePoints(Scalar scale_factor, std::vector< Point > &points) const
Definition: path_component.cc:279
impeller::QuadraticPathComponent::PointProc
std::function< void(const Point &point)> PointProc
Definition: path_component.h:155
impeller::QuadraticPathComponent::Extrema
std::vector< Point > Extrema() const
Definition: path_component.cc:302
impeller::QuadraticPathComponent::SolveDerivative
Point SolveDerivative(Scalar time) const
Definition: path_component.cc:262
impeller::QuadraticPathComponent::cp
Point cp
Definition: path_component.h:139
impeller::QuadraticPathComponent::p1
Point p1
Definition: path_component.h:137
impeller::QuadraticPathComponent::GetStartDirection
std::optional< Vector2 > GetStartDirection() const
Definition: path_component.cc:307
impeller::QuadraticPathComponent::ToLinearPathComponents
void ToLinearPathComponents(Scalar scale_factor, const PointProc &proc) const
Definition: path_component.cc:287
impeller::QuadraticPathComponent::Solve
Point Solve(Scalar time) const
Definition: path_component.cc:255
impeller::TPoint< Scalar >
impeller::TPoint::IsFinite
IsFinite() const
Definition: point.h:243
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::TPoint::x
Type x
Definition: point.h:30
wangs_formula.h