10 #include "flutter/fml/logging.h"
23 size_t contour_index)
const {
24 if (contour_index >=
contours.size()) {
27 const size_t start_index =
contours.at(contour_index).start_index;
28 const size_t end_index = (contour_index >=
contours.size() - 1)
30 :
contours.at(contour_index + 1).start_index;
31 return std::make_tuple(start_index, end_index);
35 if (!
type.has_value()) {
36 return data_->components.size();
38 auto type_value =
type.value();
40 for (
const auto& component : data_->components) {
41 if (component == type_value) {
57 return data_->points.empty() ||
58 (data_->components.size() == 1 &&
63 return data_->single_countour;
71 auto& path_components = data_->components;
72 auto& path_points = data_->points;
74 size_t storage_offset = 0u;
75 for (
size_t component_i = 0; component_i < path_components.size();
77 const auto& path_component = path_components[component_i];
78 switch (path_component) {
86 &path_points[storage_offset]);
93 &path_points[storage_offset]);
102 return std::make_pair(points, contours);
106 auto& path_components = data_->components;
107 auto& path_points = data_->points;
108 bool started_contour =
false;
109 bool first_point =
true;
111 size_t storage_offset = 0u;
112 for (
size_t component_i = 0; component_i < path_components.size();
114 const auto& path_component = path_components[component_i];
115 switch (path_component) {
119 &path_points[storage_offset]);
130 &path_points[storage_offset]);
141 &path_points[storage_offset]);
150 if (component_i == path_components.size() - 1) {
160 if (started_contour) {
163 started_contour =
true;
168 if (started_contour) {
174 auto& components = data_->components;
175 return components[index];
180 auto& components = data_->components;
181 if (index >= components.size() ||
186 size_t storage_offset = 0u;
187 for (
auto i = 0u; i < index; i++) {
190 auto& points = data_->points;
199 auto& components = data_->components;
200 if (index >= components.size() ||
205 size_t storage_offset = 0u;
206 for (
auto i = 0u; i < index; i++) {
209 auto& points = data_->points;
213 points[storage_offset + 2]);
219 auto& components = data_->components;
220 if (index >= components.size() ||
225 size_t storage_offset = 0u;
226 for (
auto i = 0u; i < index; i++) {
229 auto& points = data_->points;
232 points[storage_offset + 2],
233 points[storage_offset + 3]);
239 auto& components = data_->components;
240 if (index >= components.size() ||
245 size_t storage_offset = 0u;
246 for (
auto i = 0u; i < index; i++) {
249 auto& points = data_->points;
251 move =
ContourComponent(points[storage_offset], points[storage_offset + 1]);
257 : points(
std::move(point_buffer)), reclaim_points_(
std::move(reclaim)) {
262 points = std::move(other.points);
263 reclaim_points_ = std::move(other.reclaim_points_);
264 contours = std::move(other.contours);
268 if (reclaim_points_) {
270 reclaim_points_(std::move(points));
275 size_t storage_offset,
277 size_t component_index,
278 std::vector<PolylineContour::Component>& poly_components)
const {
279 auto& path_components = data_->components;
280 auto& path_points = data_->points;
283 if (
polyline.contours.empty() || component_index == 0) {
287 auto& contour =
polyline.contours.back();
288 contour.end_direction =
Vector2(0, 1);
289 contour.components = poly_components;
290 poly_components.clear();
292 size_t previous_index = component_index - 1;
293 storage_offset -=
VerbToOffset(path_components[previous_index]);
295 while (previous_index >= 0 && storage_offset >= 0) {
296 const auto& path_component = path_components[previous_index];
297 switch (path_component) {
300 &path_points[storage_offset]);
302 if (maybe_end.has_value()) {
303 contour.end_direction = maybe_end.value();
310 &path_points[storage_offset]);
312 if (maybe_end.has_value()) {
313 contour.end_direction = maybe_end.value();
320 &path_points[storage_offset]);
322 if (maybe_end.has_value()) {
323 contour.end_direction = maybe_end.value();
344 auto& path_components = data_->components;
345 auto& path_points = data_->points;
346 std::optional<Vector2> start_direction;
347 std::vector<PolylineContour::Component> poly_components;
348 size_t storage_offset = 0u;
349 size_t component_i = 0;
351 for (; component_i < path_components.size(); component_i++) {
352 auto path_component = path_components[component_i];
353 switch (path_component) {
355 poly_components.push_back({
356 .component_start_index =
polyline.points->size() - 1,
360 &path_points[storage_offset]);
362 if (!start_direction.has_value()) {
363 start_direction = linear->GetStartDirection();
368 poly_components.push_back({
369 .component_start_index =
polyline.points->size() - 1,
373 &path_points[storage_offset]);
375 if (!start_direction.has_value()) {
376 start_direction = quad->GetStartDirection();
381 poly_components.push_back({
382 .component_start_index =
polyline.points->size() - 1,
386 &path_points[storage_offset]);
388 if (!start_direction.has_value()) {
389 start_direction = cubic->GetStartDirection();
394 if (component_i == path_components.size() - 1) {
400 polyline.contours.back().start_direction =
401 start_direction.value_or(
Vector2(0, -1));
402 start_direction = std::nullopt;
407 &path_points[storage_offset]);
410 .is_closed = contour->IsClosed(),
411 .start_direction =
Vector2(0, -1),
412 .components = poly_components
415 polyline.points->push_back(contour->destination);
429 polyline.contours.back().start_direction =
430 start_direction.value_or(
Vector2(0, -1));
437 return data_->bounds;
443 if (!bounds.has_value()) {
446 return bounds->TransformBounds(
transform);
FillType GetFillType() const
size_t GetComponentCount(std::optional< ComponentType > type={}) const
bool GetContourComponentAtIndex(size_t index, ContourComponent &contour) const
ComponentType GetComponentTypeAtIndex(size_t index) 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)
bool GetLinearComponentAtIndex(size_t index, LinearPathComponent &linear) const
void WritePolyline(Scalar scale, VertexWriter &writer) const
bool GetQuadraticComponentAtIndex(size_t index, QuadraticPathComponent &quadratic) const
void EndContour(size_t storage_offset, Polyline &polyline, size_t component_index, std::vector< PolylineContour::Component > &poly_components) const
bool GetCubicComponentAtIndex(size_t index, CubicPathComponent &cubic) 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
const Path::Polyline & polyline
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::vector< PolylineContour > contours
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