38 explicit PathPruner(SegmentReceiver& receiver,
bool is_stroking =
false)
39 : receiver_(receiver), is_stroking_(is_stroking) {}
41 void MoveTo(
const Point& p2,
bool will_be_closed)
override {
43 if (contour_has_segments_ && !contour_has_points_) {
47 receiver_.RecordLine(contour_origin_, contour_origin_);
50 if (current_point_ != contour_origin_) {
57 receiver_.RecordLine(current_point_, contour_origin_);
60 if (contour_has_segments_) {
63 receiver_.EndContour(contour_origin_,
false);
65 contour_origin_ = current_point_ = p2;
66 contour_has_segments_ = contour_has_points_ =
false;
67 contour_will_be_closed_ = will_be_closed;
73 void LineTo(
const Point& p2)
override {
75 if (p2 != current_point_) {
76 receiver_.RecordLine(current_point_, p2);
78 contour_has_points_ =
true;
82 void QuadTo(
const Point& cp,
const Point& p2)
override {
83 if (cp == current_point_ || p2 == cp) {
88 receiver_.RecordQuad(current_point_, cp, p2);
90 contour_has_points_ =
true;
94 bool ConicTo(
const Point& cp,
const Point& p2, Scalar weight)
override {
97 }
else if (cp == current_point_ || p2 == cp || weight == 0.0f) {
100 SegmentEncountered();
101 receiver_.RecordConic(current_point_, cp, p2, weight);
103 contour_has_points_ =
true;
108 void CubicTo(
const Point& cp1,
const Point& cp2,
const Point& p2)
override {
109 SegmentEncountered();
110 if (cp1 != current_point_ ||
111 cp2 != current_point_ ||
112 p2 != current_point_) {
118 receiver_.RecordCubic(current_point_, cp1, cp2, p2);
120 contour_has_points_ =
true;
124 void Close()
override {
128 SegmentEncountered();
130 if (!contour_has_points_) {
132 receiver_.RecordLine(current_point_, contour_origin_);
133 contour_has_points_ =
true;
136 if (current_point_ != contour_origin_) {
139 receiver_.RecordLine(current_point_, contour_origin_);
142 receiver_.EndContour(contour_origin_,
true);
146 current_point_ = contour_origin_;
147 contour_has_segments_ = contour_has_points_ =
false;
154 if (!is_stroking_ && current_point_ != contour_origin_) {
157 receiver_.RecordLine(current_point_, contour_origin_);
159 if (contour_has_segments_) {
160 receiver_.EndContour(contour_origin_,
false);
165 SegmentReceiver& receiver_;
166 const bool is_stroking_;
168 void SegmentEncountered() {
169 if (!contour_has_segments_) {
170 receiver_.BeginContour(contour_origin_, contour_will_be_closed_);
171 contour_has_segments_ =
true;
175 bool contour_has_segments_ =
false;
176 bool contour_has_points_ =
false;
177 bool contour_will_be_closed_ =
false;
178 Point contour_origin_;
179 Point current_point_;
182class StorageCounter :
public SegmentReceiver {
186 void BeginContour(Point origin,
bool will_be_closed)
override {
195 void RecordLine(Point p1, Point p2)
override { point_count_++; }
197 void RecordQuad(Point p1, Point cp, Point p2)
override {
200 point_count_ += std::max<size_t>(count, 1);
203 void RecordConic(Point p1, Point cp, Point p2, Scalar weight)
override {
206 point_count_ += std::max<size_t>(count, 1);
209 void RecordCubic(Point p1, Point cp1, Point cp2, Point p2)
override {
212 point_count_ += std::max<size_t>(count, 1);
215 void EndContour(Point origin,
bool with_close)
override {
221 size_t GetPointCount()
const {
return point_count_; }
222 size_t GetContourCount()
const {
return contour_count_; }
225 size_t point_count_ = 0u;
226 size_t contour_count_ = 0u;
231class PathFillWriter :
public SegmentReceiver {
233 PathFillWriter(VertexWriter& writer, Scalar scale)
234 : writer_(writer), scale_(scale) {}
236 void BeginContour(Point origin,
bool will_be_closed)
override {
237 writer_.Write(origin);
240 void RecordLine(Point p1, Point p2)
override { writer_.Write(p2); }
242 void RecordQuad(Point p1, Point cp, Point p2)
override {
243 Quad quad{p1, cp, p2};
245 for (
size_t i = 1;
i < count;
i++) {
246 writer_.Write(quad.Solve(
i / count));
251 void RecordConic(Point p1, Point cp, Point p2, Scalar weight)
override {
252 Conic conic{p1, cp, p2, weight};
255 for (
size_t i = 1;
i < count;
i++) {
256 writer_.Write(conic.Solve(
i / count));
261 void RecordCubic(Point p1, Point cp1, Point cp2, Point p2)
override {
262 Cubic cubic{p1, cp1, cp2, p2};
265 for (
size_t i = 1;
i < count;
i++) {
266 writer_.Write(cubic.Solve(
i / count));
271 void EndContour(Point origin,
bool with_close)
override {
272 writer_.EndContour();
276 VertexWriter& writer_;
286 PathPruner pruner(receiver,
false);
293 PathPruner pruner(receiver,
true);
301 StorageCounter counter(scale);
302 PathPruner pruner(counter,
false);
305 return {counter.GetPointCount(), counter.GetContourCount()};
311 PathFillWriter path_writer(writer, scale);
312 PathPruner pruner(path_writer,
false);
321 PathPruner pruner(path_writer,
false);
Collection of functions to receive path segments from the underlying path representation via the DlPa...
virtual void CubicTo(const Point &cp1, const Point &cp2, const Point &p2)=0
virtual void LineTo(const Point &p2)=0
virtual void QuadTo(const Point &cp, const Point &p2)=0
virtual void MoveTo(const Point &p2, bool will_be_closed)=0
virtual bool ConicTo(const Point &cp, const Point &p2, Scalar weight)
virtual void Dispatch(PathReceiver &receiver) const =0
An interface for receiving pruned path segments.
An interface for generating a multi contour polyline as a triangle strip.
static void PathToFilledSegments(const PathSource &source, SegmentReceiver &receiver)
static void PathToTransformedFilledVertices(const PathSource &source, VertexWriter &writer, const Matrix &matrix)
static void PathToStrokedSegments(const PathSource &source, SegmentReceiver &receiver)
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
static std::pair< size_t, size_t > CountFillStorage(const PathSource &source, Scalar scale)
#define FML_DCHECK(condition)
Scalar ComputeConicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Scalar w)
std::array< Point, 4 > Quad
Scalar ComputeQuadradicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2)
Scalar ComputeCubicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Point p3)
A 4x4 matrix using column-major storage.
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...