Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] Pack impeller:Path into 2 vecs instead of 3. #55028

Merged
merged 16 commits into from
Sep 24, 2024
329 changes: 151 additions & 178 deletions impeller/geometry/path.cc

Large diffs are not rendered by default.

45 changes: 23 additions & 22 deletions impeller/geometry/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ class Path {
kContour,
};

static constexpr size_t VerbToOffset(Path::ComponentType verb) {
switch (verb) {
case Path::ComponentType::kLinear:
return 2u;
case Path::ComponentType::kQuadratic:
return 3u;
case Path::ComponentType::kCubic:
return 4u;
case Path::ComponentType::kContour:
return 2u;
break;
}
FML_UNREACHABLE();
}

struct PolylineContour {
struct Component {
size_t component_start_index;
Expand Down Expand Up @@ -138,14 +153,6 @@ class Path {

bool IsEmpty() const;

template <class T>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was only used in a single test so I removed it.

using Applier = std::function<void(size_t index, const T& component)>;
void EnumerateComponents(
const Applier<LinearPathComponent>& linear_applier,
const Applier<QuadraticPathComponent>& quad_applier,
const Applier<CubicPathComponent>& cubic_applier,
const Applier<ContourComponent>& contour_applier) const;

bool GetLinearComponentAtIndex(size_t index,
LinearPathComponent& linear) const;

Expand All @@ -169,6 +176,12 @@ class Path {
std::make_unique<std::vector<Point>>(),
Polyline::ReclaimPointBufferCallback reclaim = nullptr) const;

void EndContour(
size_t storage_offset,
Polyline& polyline,
std::optional<size_t> previous_path_component_index,
std::vector<PolylineContour::Component>& poly_components) const;

std::optional<Rect> GetBoundingBox() const;

std::optional<Rect> GetTransformedBoundingBox(const Matrix& transform) const;
Expand All @@ -183,16 +196,6 @@ class Path {
private:
friend class PathBuilder;

struct ComponentIndexPair {
ComponentType type = ComponentType::kLinear;
size_t index = 0;

ComponentIndexPair() {}

ComponentIndexPair(ComponentType a_type, size_t a_index)
: type(a_type), index(a_index) {}
};

// All of the data for the path is stored in this structure which is
// held by a shared_ptr. Since they all share the structure, the
// copy constructor for Path is very cheap and we don't need to deal
Expand All @@ -213,11 +216,9 @@ class Path {

FillType fill = FillType::kNonZero;
Convexity convexity = Convexity::kUnknown;
std::vector<ComponentIndexPair> components;
std::vector<Point> points;
std::vector<ContourComponent> contours;

std::optional<Rect> bounds;
std::vector<Point> points;
std::vector<ComponentType> components;
};

explicit Path(Data data);
Expand Down
124 changes: 81 additions & 43 deletions impeller/geometry/path_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <cmath>

#include "impeller/geometry/path_component.h"

namespace impeller {

PathBuilder::PathBuilder() {
Expand All @@ -22,6 +24,7 @@ Path PathBuilder::CopyPath(FillType fill) {
Path PathBuilder::TakePath(FillType fill) {
prototype_.fill = fill;
UpdateBounds();
current_contour_location_ = 0u;
return Path(std::move(prototype_));
}

Expand Down Expand Up @@ -264,36 +267,38 @@ PathBuilder& PathBuilder::AddRoundedRectBottomLeft(Rect rect,
void PathBuilder::AddContourComponent(const Point& destination,
bool is_closed) {
auto& components = prototype_.components;
auto& contours = prototype_.contours;
auto& points = prototype_.points;
auto closed = is_closed ? Point{0, 0} : Point{1, 1};
if (components.size() > 0 &&
components.back().type == Path::ComponentType::kContour) {
components.back() == Path::ComponentType::kContour) {
// Never insert contiguous contours.
contours.back() = ContourComponent(destination, is_closed);
points[current_contour_location_] = destination;
points[current_contour_location_ + 1] = closed;
} else {
contours.emplace_back(ContourComponent(destination, is_closed));
components.emplace_back(Path::ComponentType::kContour, contours.size() - 1);
current_contour_location_ = points.size();
points.push_back(destination);
points.push_back(closed);
components.push_back(Path::ComponentType::kContour);
}
prototype_.bounds.reset();
}

void PathBuilder::AddLinearComponent(const Point& p1, const Point& p2) {
auto& points = prototype_.points;
auto index = points.size();
points.emplace_back(p1);
points.emplace_back(p2);
prototype_.components.emplace_back(Path::ComponentType::kLinear, index);
points.push_back(p1);
points.push_back(p2);
prototype_.components.push_back(Path::ComponentType::kLinear);
prototype_.bounds.reset();
}

void PathBuilder::AddQuadraticComponent(const Point& p1,
const Point& cp,
const Point& p2) {
auto& points = prototype_.points;
auto index = points.size();
points.emplace_back(p1);
points.emplace_back(cp);
points.emplace_back(p2);
prototype_.components.emplace_back(Path::ComponentType::kQuadratic, index);
points.push_back(p1);
points.push_back(cp);
points.push_back(p2);
prototype_.components.push_back(Path::ComponentType::kQuadratic);
prototype_.bounds.reset();
}

Expand All @@ -302,17 +307,17 @@ void PathBuilder::AddCubicComponent(const Point& p1,
const Point& cp2,
const Point& p2) {
auto& points = prototype_.points;
auto index = points.size();
points.emplace_back(p1);
points.emplace_back(cp1);
points.emplace_back(cp2);
points.emplace_back(p2);
prototype_.components.emplace_back(Path::ComponentType::kCubic, index);
points.push_back(p1);
points.push_back(cp1);
points.push_back(cp2);
points.push_back(p2);
prototype_.components.push_back(Path::ComponentType::kCubic);
prototype_.bounds.reset();
}

void PathBuilder::SetContourClosed(bool is_closed) {
prototype_.contours.back().is_closed = is_closed;
prototype_.points[current_contour_location_ + 1] =
is_closed ? Point{0, 0} : Point{1, 1};
}

PathBuilder& PathBuilder::AddArc(const Rect& oval_bounds,
Expand Down Expand Up @@ -428,29 +433,60 @@ PathBuilder& PathBuilder::AddLine(const Point& p1, const Point& p2) {
}

PathBuilder& PathBuilder::AddPath(const Path& path) {
auto linear = [&](size_t index, const LinearPathComponent& l) {
AddLinearComponent(l.p1, l.p2);
};
auto quadratic = [&](size_t index, const QuadraticPathComponent& q) {
AddQuadraticComponent(q.p1, q.cp, q.p2);
};
auto cubic = [&](size_t index, const CubicPathComponent& c) {
AddCubicComponent(c.p1, c.cp1, c.cp2, c.p2);
};
auto move = [&](size_t index, const ContourComponent& m) {
AddContourComponent(m.destination);
};
path.EnumerateComponents(linear, quadratic, cubic, move);
auto& points = prototype_.points;
auto& components = prototype_.components;

points.insert(points.end(), path.data_->points.begin(),
path.data_->points.end());
components.insert(components.end(), path.data_->components.begin(),
path.data_->components.end());

size_t source_offset = points.size();
for (auto component : path.data_->components) {
if (component == Path::ComponentType::kContour) {
current_contour_location_ = source_offset;
}
source_offset += Path::VerbToOffset(component);
}
return *this;
}

PathBuilder& PathBuilder::Shift(Point offset) {
for (auto& point : prototype_.points) {
point += offset;
}
for (auto& contour : prototype_.contours) {
contour.destination += offset;
auto& points = prototype_.points;
size_t storage_offset = 0u;
for (const auto& component : prototype_.components) {
switch (component) {
case Path::ComponentType::kLinear: {
auto* linear =
reinterpret_cast<LinearPathComponent*>(&points[storage_offset]);
linear->p1 += offset;
linear->p2 += offset;
break;
}
case Path::ComponentType::kQuadratic: {
auto* quad =
reinterpret_cast<QuadraticPathComponent*>(&points[storage_offset]);
quad->p1 += offset;
quad->p2 += offset;
quad->cp += offset;
} break;
case Path::ComponentType::kCubic: {
auto* cubic =
reinterpret_cast<CubicPathComponent*>(&points[storage_offset]);
cubic->p1 += offset;
cubic->p2 += offset;
cubic->cp1 += offset;
cubic->cp2 += offset;
} break;
case Path::ComponentType::kContour:
auto* contour =
reinterpret_cast<ContourComponent*>(&points[storage_offset]);
contour->destination += offset;
break;
}
storage_offset += Path::VerbToOffset(component);
}

prototype_.bounds.reset();
return *this;
}
Expand Down Expand Up @@ -499,33 +535,35 @@ std::optional<std::pair<Point, Point>> PathBuilder::GetMinMaxCoveragePoints()
}
};

size_t storage_offset = 0u;
for (const auto& component : prototype_.components) {
switch (component.type) {
switch (component) {
case Path::ComponentType::kLinear: {
auto* linear = reinterpret_cast<const LinearPathComponent*>(
&points[component.index]);
&points[storage_offset]);
clamp(linear->p1);
clamp(linear->p2);
break;
}
case Path::ComponentType::kQuadratic:
for (const auto& extrema :
reinterpret_cast<const QuadraticPathComponent*>(
&points[component.index])
&points[storage_offset])
->Extrema()) {
clamp(extrema);
}
break;
case Path::ComponentType::kCubic:
for (const auto& extrema : reinterpret_cast<const CubicPathComponent*>(
&points[component.index])
&points[storage_offset])
->Extrema()) {
clamp(extrema);
}
break;
case Path::ComponentType::kContour:
break;
}
storage_offset += Path::VerbToOffset(component);
}

if (!min.has_value() || !max.has_value()) {
Expand Down
1 change: 1 addition & 0 deletions impeller/geometry/path_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class PathBuilder {
private:
Point subpath_start_;
Point current_;
size_t current_contour_location_ = 0u;
Path::Data prototype_;

PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii);
Expand Down
48 changes: 0 additions & 48 deletions impeller/geometry/path_component.cc
Original file line number Diff line number Diff line change
Expand Up @@ -373,52 +373,4 @@ std::optional<Vector2> CubicPathComponent::GetEndDirection() const {
return std::nullopt;
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
const LinearPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetStartDirection();
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
const QuadraticPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetStartDirection();
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
const CubicPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetStartDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
const LinearPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetEndDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
const QuadraticPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetEndDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
const CubicPathComponent* component) {
if (!component) {
return std::nullopt;
}
return component->GetEndDirection();
}

} // namespace impeller
Loading