10 #include "flutter/fml/logging.h"
23 return path_.data_->components[component_index_];
26 #define CHECK_COMPONENT(type) \
27 (component_index_ < path_.data_->components.size() && \
28 path_.data_->components[component_index_] == type && \
29 storage_offset_ + VerbToOffset(type) <= path_.data_->points.size())
35 const Point* points = &(path_.data_->points[storage_offset_]);
43 const Point* points = &(path_.data_->points[storage_offset_]);
51 const Point* points = &(path_.data_->points[storage_offset_]);
59 const Point* points = &(path_.data_->points[storage_offset_]);
67 const Point* points = &(path_.data_->points[storage_offset_]);
72 auto components = path_.data_->components;
73 if (component_index_ < components.size()) {
74 storage_offset_ +=
VerbToOffset(path_.data_->components[component_index_]);
81 size_t contour_index)
const {
82 if (contour_index >= contours.size()) {
83 return {points->size(), points->size()};
85 const size_t start_index = contours.at(contour_index).start_index;
86 const size_t end_index = (contour_index >= contours.size() - 1)
88 : contours.at(contour_index + 1).start_index;
89 return std::make_tuple(start_index, end_index);
93 if (!
type.has_value()) {
94 return data_->components.size();
96 auto type_value =
type.value();
98 for (
const auto& component : data_->components) {
99 if (component == type_value) {
107 return data_->points.size();
119 return data_->points.empty() ||
120 (data_->components.size() == 1 &&
125 return data_->single_contour;
133 auto& path_components = data_->components;
134 auto& path_points = data_->points;
136 size_t storage_offset = 0u;
137 for (
size_t component_i = 0; component_i < path_components.size();
139 const auto& path_component = path_components[component_i];
140 switch (path_component) {
148 &path_points[storage_offset]);
155 &path_points[storage_offset]);
162 &path_points[storage_offset]);
171 return std::make_pair(points, contours);
175 auto& path_components = data_->components;
176 auto& path_points = data_->points;
177 bool started_contour =
false;
178 bool first_point =
true;
180 size_t storage_offset = 0u;
181 for (
size_t component_i = 0; component_i < path_components.size();
183 const auto& path_component = path_components[component_i];
184 switch (path_component) {
188 &path_points[storage_offset]);
199 &path_points[storage_offset]);
210 &path_points[storage_offset]);
221 &path_points[storage_offset]);
230 if (component_i == path_components.size() - 1) {
240 if (started_contour) {
243 started_contour =
true;
248 if (started_contour) {
259 data_->points.size());
264 : points(
std::move(point_buffer)), reclaim_points_(
std::move(reclaim)) {
269 points = std::move(other.points);
270 reclaim_points_ = std::move(other.reclaim_points_);
271 contours = std::move(other.contours);
275 if (reclaim_points_) {
277 reclaim_points_(std::move(points));
282 size_t storage_offset,
284 size_t component_index,
285 std::vector<PolylineContour::Component>& poly_components)
const {
286 auto& path_components = data_->components;
287 auto& path_points = data_->points;
290 if (
polyline.contours.empty() || component_index == 0) {
294 auto& contour =
polyline.contours.back();
295 contour.end_direction =
Vector2(0, 1);
296 contour.components = poly_components;
297 poly_components.clear();
299 size_t previous_index = component_index - 1;
300 storage_offset -=
VerbToOffset(path_components[previous_index]);
302 while (previous_index >= 0 && storage_offset >= 0) {
303 const auto& path_component = path_components[previous_index];
304 switch (path_component) {
307 &path_points[storage_offset]);
309 if (maybe_end.has_value()) {
310 contour.end_direction = maybe_end.value();
317 &path_points[storage_offset]);
319 if (maybe_end.has_value()) {
320 contour.end_direction = maybe_end.value();
327 &path_points[storage_offset]);
329 if (maybe_end.has_value()) {
330 contour.end_direction = maybe_end.value();
337 &path_points[storage_offset]);
339 if (maybe_end.has_value()) {
340 contour.end_direction = maybe_end.value();
361 auto& path_components = data_->components;
362 auto& path_points = data_->points;
363 std::optional<Vector2> start_direction;
364 std::vector<PolylineContour::Component> poly_components;
365 size_t storage_offset = 0u;
366 size_t component_i = 0;
368 for (; component_i < path_components.size(); component_i++) {
369 auto path_component = path_components[component_i];
370 switch (path_component) {
372 poly_components.push_back({
373 .component_start_index =
polyline.points->size() - 1,
377 &path_points[storage_offset]);
379 if (!start_direction.has_value()) {
380 start_direction = linear->GetStartDirection();
385 poly_components.push_back({
386 .component_start_index =
polyline.points->size() - 1,
390 &path_points[storage_offset]);
392 if (!start_direction.has_value()) {
393 start_direction = quad->GetStartDirection();
398 poly_components.push_back({
399 .component_start_index =
polyline.points->size() - 1,
403 &path_points[storage_offset]);
405 if (!start_direction.has_value()) {
406 start_direction = conic->GetStartDirection();
411 poly_components.push_back({
412 .component_start_index =
polyline.points->size() - 1,
416 &path_points[storage_offset]);
418 if (!start_direction.has_value()) {
419 start_direction = cubic->GetStartDirection();
424 if (component_i == path_components.size() - 1) {
430 polyline.contours.back().start_direction =
431 start_direction.value_or(
Vector2(0, -1));
432 start_direction = std::nullopt;
437 &path_points[storage_offset]);
440 .is_closed = contour->IsClosed(),
441 .start_direction =
Vector2(0, -1),
442 .components = poly_components
445 polyline.points->push_back(contour->destination);
459 polyline.contours.back().start_direction =
460 start_direction.value_or(
Vector2(0, -1));
467 return data_->bounds;
473 if (!bounds.has_value()) {
476 return bounds->TransformBounds(
transform);
const ContourComponent * contour() const
ComponentIterator & operator++()
const QuadraticPathComponent * quadratic() const
ComponentType type() const
const LinearPathComponent * linear() const
const ConicPathComponent * conic() const
const CubicPathComponent * cubic() const
FillType GetFillType() const
size_t GetComponentCount(std::optional< ComponentType > type={}) const
ComponentIterator begin() const
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
bool IsSingleContour() const
Whether the line contains a single contour.
std::optional< Rect > GetTransformedBoundingBox(const Matrix &transform) const
static constexpr size_t VerbToOffset(Path::ComponentType verb)
ComponentIterator end() const
size_t GetPointCount() const
void WritePolyline(Scalar scale, VertexWriter &writer) const
void EndContour(size_t storage_offset, Polyline &polyline, size_t component_index, std::vector< PolylineContour::Component > &poly_components) const
std::optional< Rect > GetBoundingBox() const
std::pair< size_t, size_t > CountStorage(Scalar scale) const
Determine required storage for points and number of contours.
An interface for generating a multi contour polyline as a triangle strip.
virtual void EndContour()=0
virtual void Write(Point point)=0
#define CHECK_COMPONENT(type)
const Path::Polyline & polyline
std::optional< Vector2 > GetEndDirection() const
size_t CountLinearPathComponents(Scalar scale) const
void ToLinearPathComponents(Scalar scale_factor, const PointProc &proc) const
void AppendPolylinePoints(Scalar scale_factor, std::vector< Point > &points) const
void ToLinearPathComponents(Scalar scale, const PointProc &proc) const
size_t CountLinearPathComponents(Scalar scale) const
void AppendPolylinePoints(Scalar scale, std::vector< Point > &points) const
std::optional< Vector2 > GetEndDirection() const
std::optional< Vector2 > GetEndDirection() const
void AppendPolylinePoints(std::vector< Point > &points) const
A 4x4 matrix using column-major storage.
size_t start_index
Index that denotes the first point of this contour.
Polyline(PointBufferPtr point_buffer, ReclaimPointBufferCallback reclaim)
std::function< void(PointBufferPtr)> ReclaimPointBufferCallback
std::unique_ptr< std::vector< Point > > PointBufferPtr
std::tuple< size_t, size_t > GetContourPointBounds(size_t contour_index) const
size_t CountLinearPathComponents(Scalar scale) const
std::optional< Vector2 > GetEndDirection() const
void AppendPolylinePoints(Scalar scale_factor, std::vector< Point > &points) const
void ToLinearPathComponents(Scalar scale_factor, const PointProc &proc) const
std::shared_ptr< const fml::Mapping > data