diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 191d944952d79..0b1e963571e4c 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -589,6 +589,10 @@ TEST(GeometryTest, SimplePath) { .AddCubicComponent({300, 300}, {400, 400}, {500, 500}, {600, 600}); ASSERT_EQ(path.GetComponentCount(), 4u); + ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u); + ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u); + ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u); + ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 1u); path.EnumerateComponents( [](size_t index, const LinearPathComponent& linear) { diff --git a/impeller/geometry/path.cc b/impeller/geometry/path.cc index b6d97433fe648..5121e8e045cae 100644 --- a/impeller/geometry/path.cc +++ b/impeller/geometry/path.cc @@ -5,9 +5,9 @@ #include "impeller/geometry/path.h" #include +#include #include "impeller/geometry/path_component.h" -#include "path_component.h" namespace impeller { @@ -29,7 +29,19 @@ std::tuple Path::Polyline::GetContourPointBounds( return std::make_tuple(start_index, end_index); } -size_t Path::GetComponentCount() const { +size_t Path::GetComponentCount(std::optional type) const { + if (type.has_value()) { + switch (type.value()) { + case ComponentType::kLinear: + return linears_.size(); + case ComponentType::kQuadratic: + return quads_.size(); + case ComponentType::kCubic: + return cubics_.size(); + case ComponentType::kContour: + return contours_.size(); + } + } return components_.size(); } @@ -243,10 +255,9 @@ Path::Polyline Path::CreatePolyline(Scalar scale) const { } }; - auto get_path_component = - [this](size_t component_i) -> std::optional { + auto get_path_component = [this](size_t component_i) -> PathComponentVariant { if (component_i >= components_.size()) { - return std::nullopt; + return std::monostate{}; } const auto& component = components_[component_i]; switch (component.type) { @@ -257,18 +268,20 @@ Path::Polyline Path::CreatePolyline(Scalar scale) const { case ComponentType::kCubic: return &cubics_[component.index]; case ComponentType::kContour: - return std::nullopt; + return std::monostate{}; } }; auto compute_contour_start_direction = [&get_path_component](size_t current_path_component_index) { size_t next_component_index = current_path_component_index + 1; - while (get_path_component(next_component_index).has_value()) { - auto next_component = - get_path_component(next_component_index).value(); - if (next_component->GetStartDirection().has_value()) { - return next_component->GetStartDirection().value(); + while (!std::holds_alternative( + get_path_component(next_component_index))) { + auto next_component = get_path_component(next_component_index); + auto maybe_vector = + std::visit(PathComponentStartDirectionVisitor(), next_component); + if (maybe_vector.has_value()) { + return maybe_vector.value(); } else { next_component_index++; } @@ -293,11 +306,13 @@ Path::Polyline Path::CreatePolyline(Scalar scale) const { contour.end_direction = Vector2(0, 1); size_t previous_index = previous_path_component_index.value(); - while (get_path_component(previous_index).has_value()) { - auto previous_path_component = get_path_component(previous_index).value(); - if (previous_path_component->GetEndDirection().has_value()) { - contour.end_direction = - previous_path_component->GetEndDirection().value(); + while (!std::holds_alternative( + get_path_component(previous_index))) { + auto previous_component = get_path_component(previous_index); + auto maybe_vector = + std::visit(PathComponentEndDirectionVisitor(), previous_component); + if (maybe_vector.has_value()) { + contour.end_direction = maybe_vector.value(); break; } else { if (previous_index == 0) { diff --git a/impeller/geometry/path.h b/impeller/geometry/path.h index 0c4cf6939950a..1f3c14659b84d 100644 --- a/impeller/geometry/path.h +++ b/impeller/geometry/path.h @@ -77,7 +77,7 @@ class Path { ~Path(); - size_t GetComponentCount() const; + size_t GetComponentCount(std::optional type = {}) const; void SetFillType(FillType fill); diff --git a/impeller/geometry/path_component.cc b/impeller/geometry/path_component.cc index da0a6aae0889e..7414d3ebbca47 100644 --- a/impeller/geometry/path_component.cc +++ b/impeller/geometry/path_component.cc @@ -8,8 +8,6 @@ namespace impeller { -PathComponent::~PathComponent() = default; - /* * Based on: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Specific_cases */ @@ -345,4 +343,52 @@ std::optional CubicPathComponent::GetEndDirection() const { return std::nullopt; } +std::optional PathComponentStartDirectionVisitor::operator()( + const LinearPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetStartDirection(); +} + +std::optional PathComponentStartDirectionVisitor::operator()( + const QuadraticPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetStartDirection(); +} + +std::optional PathComponentStartDirectionVisitor::operator()( + const CubicPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetStartDirection(); +} + +std::optional PathComponentEndDirectionVisitor::operator()( + const LinearPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetEndDirection(); +} + +std::optional PathComponentEndDirectionVisitor::operator()( + const QuadraticPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetEndDirection(); +} + +std::optional PathComponentEndDirectionVisitor::operator()( + const CubicPathComponent* component) { + if (!component) { + return std::nullopt; + } + return component->GetEndDirection(); +} + } // namespace impeller diff --git a/impeller/geometry/path_component.h b/impeller/geometry/path_component.h index 3c339ee013cee..c2a808cf18d2a 100644 --- a/impeller/geometry/path_component.h +++ b/impeller/geometry/path_component.h @@ -4,6 +4,8 @@ #pragma once +#include +#include #include #include "impeller/geometry/point.h" @@ -22,14 +24,7 @@ namespace impeller { // points for the given scale. static constexpr Scalar kDefaultCurveTolerance = .1f; -struct PathComponent { - virtual ~PathComponent(); - - virtual std::optional GetStartDirection() const = 0; - virtual std::optional GetEndDirection() const = 0; -}; - -struct LinearPathComponent : public PathComponent { +struct LinearPathComponent { Point p1; Point p2; @@ -47,12 +42,12 @@ struct LinearPathComponent : public PathComponent { return p1 == other.p1 && p2 == other.p2; } - std::optional GetStartDirection() const override; + std::optional GetStartDirection() const; - std::optional GetEndDirection() const override; + std::optional GetEndDirection() const; }; -struct QuadraticPathComponent : public PathComponent { +struct QuadraticPathComponent { Point p1; Point cp; Point p2; @@ -87,12 +82,12 @@ struct QuadraticPathComponent : public PathComponent { return p1 == other.p1 && cp == other.cp && p2 == other.p2; } - std::optional GetStartDirection() const override; + std::optional GetStartDirection() const; - std::optional GetEndDirection() const override; + std::optional GetEndDirection() const; }; -struct CubicPathComponent : public PathComponent { +struct CubicPathComponent { Point p1; Point cp1; Point cp2; @@ -131,9 +126,9 @@ struct CubicPathComponent : public PathComponent { p2 == other.p2; } - std::optional GetStartDirection() const override; + std::optional GetStartDirection() const; - std::optional GetEndDirection() const override; + std::optional GetEndDirection() const; private: QuadraticPathComponent Lower() const; @@ -153,4 +148,31 @@ struct ContourComponent { } }; +using PathComponentVariant = std::variant; + +struct PathComponentStartDirectionVisitor { + std::optional operator()(const LinearPathComponent* component); + std::optional operator()(const QuadraticPathComponent* component); + std::optional operator()(const CubicPathComponent* component); + std::optional operator()(std::monostate monostate) { + return std::nullopt; + } +}; + +struct PathComponentEndDirectionVisitor { + std::optional operator()(const LinearPathComponent* component); + std::optional operator()(const QuadraticPathComponent* component); + std::optional operator()(const CubicPathComponent* component); + std::optional operator()(std::monostate monostate) { + return std::nullopt; + } +}; + +static_assert(!std::is_polymorphic::value); +static_assert(!std::is_polymorphic::value); +static_assert(!std::is_polymorphic::value); + } // namespace impeller