Skip to content

Commit

Permalink
PathSegments cannot be used with anything else than PathImpl
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=265247
rdar://118717060

Reviewed by Said Abou-Hallawa.

PathImpl and PathSegment were coupled:
PathImpl::appendSegment would call into PathSegment::addToImpl
PathSegment::addToImpl would call into PathImpl

This would be more complex than needed and also limit the PathSegments
to be only used with PathImpl.

Instead:
  - PathSegment is the data that is being held -- no actions toward any
    class that does actual work on the data.
  - PathImpl knows how to use the path segment types: PathImpl::add()
    for each path segment type.
  - PathImpl knows how to use the PathSegment variant:
    PathImpl::addSegment() for the PathSegment, doing generic add() over
    the variants.
  - Make each member function for adding segments PathImpl::add(). This
    way generic algorithms over the variants are consistent to write.
  - The PathImpl::add() parameters are by-value to avoid introducing
    indirection, the arguments are always used.

Construct PathCG, PathCairo from PathStream without applySegments, as
the PathStream segment list can be just iterated.

This works towards being able to play back a PathSegment list to a
CGContext.

* Source/WebCore/platform/graphics/PathImpl.cpp:
(WebCore::PathImpl::appendSegment): Deleted.
* Source/WebCore/platform/graphics/PathImpl.h:
(WebCore::addPathSegment):
* Source/WebCore/platform/graphics/PathSegment.cpp:
(WebCore::PathSegment::addToImpl const): Deleted.
* Source/WebCore/platform/graphics/PathSegment.h:
(WebCore::PathSegment::addTo const):
* Source/WebCore/platform/graphics/PathSegmentData.cpp:
(WebCore::PathMoveTo::addToImpl const): Deleted.
(WebCore::PathLineTo::addToImpl const): Deleted.
(WebCore::PathQuadCurveTo::addToImpl const): Deleted.
(WebCore::PathBezierCurveTo::addToImpl const): Deleted.
(WebCore::PathArcTo::addToImpl const): Deleted.
(WebCore::PathArc::addToImpl const): Deleted.
(WebCore::PathEllipse::addToImpl const): Deleted.
(WebCore::PathEllipseInRect::addToImpl const): Deleted.
(WebCore::PathRect::addToImpl const): Deleted.
(WebCore::PathRoundedRect::addToImpl const): Deleted.
(WebCore::PathDataLine::addToImpl const): Deleted.
(WebCore::PathDataQuadCurve::addToImpl const): Deleted.
(WebCore::PathDataBezierCurve::addToImpl const): Deleted.
(WebCore::PathDataArc::addToImpl const): Deleted.
(WebCore::PathCloseSubpath::addToImpl const): Deleted.
* Source/WebCore/platform/graphics/PathSegmentData.h:
* Source/WebCore/platform/graphics/cairo/PathCairo.cpp:
(WebCore::PathCairo::create):
* Source/WebCore/platform/graphics/cg/PathCG.cpp:
(WebCore::PathCG::create):

Canonical link: https://commits.webkit.org/271199@main
  • Loading branch information
kkinnunen-apple committed Nov 28, 2023
1 parent 1c1eb7d commit d132cc1
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 312 deletions.
24 changes: 12 additions & 12 deletions Source/WebCore/platform/graphics/Path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void Path::moveTo(const FloatPoint& point)
if (isEmpty())
m_data = PathSegment(PathMoveTo { point });
else
ensureImpl().moveTo(point);
ensureImpl().add(PathMoveTo { point });
}

const PathMoveTo* Path::asSingleMoveTo() const
Expand All @@ -135,7 +135,7 @@ void Path::addLineTo(const FloatPoint& point)
else if (auto moveTo = asSingleMoveTo())
m_data = PathSegment(PathDataLine { moveTo->point, point });
else
ensureImpl().addLineTo(point);
ensureImpl().add(PathLineTo { point });
}

void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint)
Expand All @@ -145,7 +145,7 @@ void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endP
else if (auto moveTo = asSingleMoveTo())
m_data = PathSegment(PathDataQuadCurve { moveTo->point, controlPoint, endPoint });
else
ensureImpl().addQuadCurveTo(controlPoint, endPoint);
ensureImpl().add(PathQuadCurveTo { controlPoint, endPoint });
}

void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint)
Expand All @@ -155,7 +155,7 @@ void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& c
else if (auto moveTo = asSingleMoveTo())
m_data = PathSegment(PathDataBezierCurve { moveTo->point, controlPoint1, controlPoint2, endPoint });
else
ensureImpl().addBezierCurveTo(controlPoint1, controlPoint2, endPoint);
ensureImpl().add(PathBezierCurveTo { controlPoint1, controlPoint2, endPoint });
}

void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius)
Expand All @@ -165,7 +165,7 @@ void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float ra
else if (auto moveTo = asSingleMoveTo())
m_data = PathSegment(PathDataArc { moveTo->point, point1, point2, radius });
else
ensureImpl().addArcTo(point1, point2, radius);
ensureImpl().add(PathArcTo { point1, point2, radius });
}

void Path::addArc(const FloatPoint& point, float radius, float startAngle, float endAngle, RotationDirection direction)
Expand All @@ -179,31 +179,31 @@ void Path::addArc(const FloatPoint& point, float radius, float startAngle, float
if (isEmpty())
m_data = PathSegment(PathArc { point, radius, startAngle, endAngle, direction });
else
ensureImpl().addArc(point, radius, startAngle, endAngle, direction);
ensureImpl().add(PathArc { point, radius, startAngle, endAngle, direction });
}

void Path::addEllipse(const FloatPoint& point, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, RotationDirection direction)
{
if (isEmpty())
m_data = PathSegment(PathEllipse { point, radiusX, radiusY, rotation, startAngle, endAngle, direction });
else
ensureImpl().addEllipse(point, radiusX, radiusY, rotation, startAngle, endAngle, direction);
ensureImpl().add(PathEllipse { point, radiusX, radiusY, rotation, startAngle, endAngle, direction });
}

void Path::addEllipseInRect(const FloatRect& rect)
{
if (isEmpty())
m_data = PathSegment(PathEllipseInRect { rect });
else
ensureImpl().addEllipseInRect(rect);
ensureImpl().add(PathEllipseInRect { rect });
}

void Path::addRect(const FloatRect& rect)
{
if (isEmpty())
m_data = PathSegment(PathRect { rect });
else
ensureImpl().addRect(rect);
ensureImpl().add(PathRect { rect });
}

static FloatRoundedRect calculateEvenRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii)
Expand Down Expand Up @@ -245,7 +245,7 @@ void Path::addRoundedRect(const FloatRoundedRect& roundedRect, PathRoundedRect::
if (isEmpty())
m_data = PathSegment(PathRoundedRect { roundedRect, strategy });
else
ensureImpl().addRoundedRect(roundedRect, strategy);
ensureImpl().add(PathRoundedRect { roundedRect, strategy });
}

void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii, PathRoundedRect::Strategy strategy)
Expand All @@ -256,7 +256,7 @@ void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii,
if (isEmpty())
m_data = PathSegment(PathRoundedRect { calculateEvenRoundedRect(rect, roundingRadii), strategy });
else
ensureImpl().addRoundedRect(calculateEvenRoundedRect(rect, roundingRadii), strategy);
ensureImpl().add(PathRoundedRect { calculateEvenRoundedRect(rect, roundingRadii), strategy });
}

void Path::addRoundedRect(const RoundedRect& rect)
Expand All @@ -269,7 +269,7 @@ void Path::closeSubpath()
if (isEmpty() || isClosed())
return;

ensureImpl().closeSubpath();
ensureImpl().add(PathCloseSubpath { });
}

void Path::addPath(const Path& path, const AffineTransform& transform)
Expand Down
43 changes: 19 additions & 24 deletions Source/WebCore/platform/graphics/PathImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,13 @@

namespace WebCore {

void PathImpl::appendSegment(const PathSegment& segment)
{
segment.addToImpl(*this);
}

void PathImpl::addLinesForRect(const FloatRect& rect)
{
moveTo(rect.minXMinYCorner());
addLineTo(rect.maxXMinYCorner());
addLineTo(rect.maxXMaxYCorner());
addLineTo(rect.minXMaxYCorner());
closeSubpath();
add(PathMoveTo { rect.minXMinYCorner() });
add(PathLineTo { rect.maxXMinYCorner() });
add(PathLineTo { rect.maxXMaxYCorner() });
add(PathLineTo { rect.minXMaxYCorner() });
add(PathCloseSubpath { });
}

void PathImpl::addBeziersForRoundedRect(const FloatRoundedRect& roundedRect)
Expand All @@ -52,37 +47,37 @@ void PathImpl::addBeziersForRoundedRect(const FloatRoundedRect& roundedRect)
const auto& bottomLeftRadius = radii.bottomLeft();
const auto& bottomRightRadius = radii.bottomRight();

moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
add(PathMoveTo { FloatPoint(rect.x() + topLeftRadius.width(), rect.y()) });

addLineTo(FloatPoint(rect.maxX() - topRightRadius.width(), rect.y()));
add(PathLineTo { FloatPoint(rect.maxX() - topRightRadius.width(), rect.y()) });
if (topRightRadius.width() > 0 || topRightRadius.height() > 0) {
addBezierCurveTo(FloatPoint(rect.maxX() - topRightRadius.width() * circleControlPoint(), rect.y()),
add(PathBezierCurveTo { FloatPoint(rect.maxX() - topRightRadius.width() * circleControlPoint(), rect.y()),
FloatPoint(rect.maxX(), rect.y() + topRightRadius.height() * circleControlPoint()),
FloatPoint(rect.maxX(), rect.y() + topRightRadius.height()));
FloatPoint(rect.maxX(), rect.y() + topRightRadius.height()) });
}

addLineTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height()));
add(PathLineTo { FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height()) });
if (bottomRightRadius.width() > 0 || bottomRightRadius.height() > 0) {
addBezierCurveTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * circleControlPoint()),
add(PathBezierCurveTo { FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * circleControlPoint()),
FloatPoint(rect.maxX() - bottomRightRadius.width() * circleControlPoint(), rect.maxY()),
FloatPoint(rect.maxX() - bottomRightRadius.width(), rect.maxY()));
FloatPoint(rect.maxX() - bottomRightRadius.width(), rect.maxY()) });
}

addLineTo(FloatPoint(rect.x() + bottomLeftRadius.width(), rect.maxY()));
add(PathLineTo { FloatPoint(rect.x() + bottomLeftRadius.width(), rect.maxY()) });
if (bottomLeftRadius.width() > 0 || bottomLeftRadius.height() > 0) {
addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * circleControlPoint(), rect.maxY()),
add(PathBezierCurveTo { FloatPoint(rect.x() + bottomLeftRadius.width() * circleControlPoint(), rect.maxY()),
FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height() * circleControlPoint()),
FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height()));
FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height()) });
}

addLineTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height()));
add(PathLineTo { FloatPoint(rect.x(), rect.y() + topLeftRadius.height()) });
if (topLeftRadius.width() > 0 || topLeftRadius.height() > 0) {
addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * circleControlPoint()),
add(PathBezierCurveTo { FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * circleControlPoint()),
FloatPoint(rect.x() + topLeftRadius.width() * circleControlPoint(), rect.y()),
FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
FloatPoint(rect.x() + topLeftRadius.width(), rect.y()) });
}

closeSubpath();
add(PathCloseSubpath { });
}

bool PathImpl::isClosed() const
Expand Down
52 changes: 36 additions & 16 deletions Source/WebCore/platform/graphics/PathImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,18 @@ class PathImpl : public ThreadSafeRefCounted<PathImpl> {

virtual Ref<PathImpl> copy() const = 0;

virtual void moveTo(const FloatPoint&) = 0;

virtual void addLineTo(const FloatPoint&) = 0;
virtual void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint) = 0;
virtual void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint) = 0;
virtual void addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius) = 0;

virtual void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, RotationDirection) = 0;
virtual void addEllipse(const FloatPoint&, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, RotationDirection) = 0;
virtual void addEllipseInRect(const FloatRect&) = 0;
virtual void addRect(const FloatRect&) = 0;
virtual void addRoundedRect(const FloatRoundedRect&, PathRoundedRect::Strategy) = 0;

virtual void closeSubpath() = 0;
void addSegment(PathSegment);
virtual void add(PathMoveTo) = 0;
virtual void add(PathLineTo) = 0;
virtual void add(PathQuadCurveTo) = 0;
virtual void add(PathBezierCurveTo) = 0;
virtual void add(PathArcTo) = 0;
virtual void add(PathArc) = 0;
virtual void add(PathEllipse) = 0;
virtual void add(PathEllipseInRect) = 0;
virtual void add(PathRect) = 0;
virtual void add(PathRoundedRect) = 0;
virtual void add(PathCloseSubpath) = 0;

void addLinesForRect(const FloatRect&);
void addBeziersForRoundedRect(const FloatRoundedRect&);
Expand Down Expand Up @@ -92,8 +90,30 @@ class PathImpl : public ThreadSafeRefCounted<PathImpl> {

protected:
PathImpl() = default;

void appendSegment(const PathSegment&);
};

inline void PathImpl::addSegment(PathSegment segment)
{
WTF::switchOn(WTFMove(segment).data(),
[&](auto&& segment) {
add(WTFMove(segment));
},
[&](PathDataLine segment) {
add(PathMoveTo { segment.start });
add(PathLineTo { segment.end });
},
[&](PathDataQuadCurve segment) {
add(PathMoveTo { segment.start });
add(PathQuadCurveTo { segment.controlPoint, segment.endPoint });
},
[&](PathDataBezierCurve segment) {
add(PathMoveTo { segment.start });
add(PathBezierCurveTo { segment.controlPoint1, segment.controlPoint2, segment.endPoint });
},
[&](PathDataArc segment) {
add(PathMoveTo { segment.start });
add(PathArcTo { segment.controlPoint1, segment.controlPoint2, segment.radius });
});
}

} // namespace WebCore
7 changes: 0 additions & 7 deletions Source/WebCore/platform/graphics/PathSegment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ void PathSegment::extendBoundingRect(const FloatPoint& currentPoint, const Float
});
}

void PathSegment::addToImpl(PathImpl& impl) const
{
WTF::switchOn(m_data, [&](auto& data) {
data.addToImpl(impl);
});
}

bool PathSegment::canApplyElements() const
{
return WTF::switchOn(m_data, [&](auto& data) {
Expand Down
5 changes: 2 additions & 3 deletions Source/WebCore/platform/graphics/PathSegment.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,15 @@ class PathSegment {

bool operator==(const PathSegment&) const = default;

const Data& data() const { return m_data; }
const Data& data() const & { return m_data; }
Data&& data() && { return WTFMove(m_data); }
bool isCloseSubPath() const { return std::holds_alternative<PathCloseSubpath>(m_data); }

FloatPoint calculateEndPoint(const FloatPoint& currentPoint, FloatPoint& lastMoveToPoint) const;
std::optional<FloatPoint> tryGetEndPointWithoutContext() const;
void extendFastBoundingRect(const FloatPoint& currentPoint, const FloatPoint& lastMoveToPoint, FloatRect& boundingRect) const;
void extendBoundingRect(const FloatPoint& currentPoint, const FloatPoint& lastMoveToPoint, FloatRect& boundingRect) const;

void addToImpl(PathImpl&) const;

bool canApplyElements() const;
bool applyElements(const PathElementApplier&) const;

Expand Down
Loading

0 comments on commit d132cc1

Please sign in to comment.