Title: [268552] trunk/Source/WebCore
- Revision
- 268552
- Author
- wenson_hs...@apple.com
- Date
- 2020-10-15 13:56:03 -0700 (Thu, 15 Oct 2020)
Log Message
Add a fast codepath to compute the bounding rect of an inline arc path
https://bugs.webkit.org/show_bug.cgi?id=217764
Reviewed by Tim Horton.
This is a followup to r268320, which added an implementation of `Path::fastBoundingRect` for the inline
`ArcData` case, but left `Path::boundingRect` as-is. This means that currently, a call to `Path::boundingRect`
in the case of a simple arc path (represented in `ArcData`) will cause a `CGPath` to be allocated and set up,
when we could instead just compute the exact bounds of the path using the center, radius, and start and end
angles.
* platform/graphics/Path.cpp:
(WebCore::computeArcBounds):
Add a helper function to compute the exact bounds of a circular arc. This helper works by first fitting the rect
to the start and end positions, and then extending to the top, left, bottom, or right edges as needed (i.e. if
the start and end angles intersect the top-, left-, bottom- or right-most points in the circle).
(WebCore::Path::boundingRectFromInlineData const):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (268551 => 268552)
--- trunk/Source/WebCore/ChangeLog 2020-10-15 20:40:34 UTC (rev 268551)
+++ trunk/Source/WebCore/ChangeLog 2020-10-15 20:56:03 UTC (rev 268552)
@@ -1,3 +1,25 @@
+2020-10-15 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Add a fast codepath to compute the bounding rect of an inline arc path
+ https://bugs.webkit.org/show_bug.cgi?id=217764
+
+ Reviewed by Tim Horton.
+
+ This is a followup to r268320, which added an implementation of `Path::fastBoundingRect` for the inline
+ `ArcData` case, but left `Path::boundingRect` as-is. This means that currently, a call to `Path::boundingRect`
+ in the case of a simple arc path (represented in `ArcData`) will cause a `CGPath` to be allocated and set up,
+ when we could instead just compute the exact bounds of the path using the center, radius, and start and end
+ angles.
+
+ * platform/graphics/Path.cpp:
+ (WebCore::computeArcBounds):
+
+ Add a helper function to compute the exact bounds of a circular arc. This helper works by first fitting the rect
+ to the start and end positions, and then extending to the top, left, bottom, or right edges as needed (i.e. if
+ the start and end angles intersect the top-, left-, bottom- or right-most points in the circle).
+
+ (WebCore::Path::boundingRectFromInlineData const):
+
2020-10-15 Sam Weinig <wei...@apple.com>
[WebIDL] Bindings do not support two attributes or functions with the same name only differing by case of first character
Modified: trunk/Source/WebCore/platform/graphics/Path.cpp (268551 => 268552)
--- trunk/Source/WebCore/platform/graphics/Path.cpp 2020-10-15 20:40:34 UTC (rev 268551)
+++ trunk/Source/WebCore/platform/graphics/Path.cpp 2020-10-15 20:56:03 UTC (rev 268552)
@@ -431,9 +431,63 @@
return boundingRectFromInlineData();
}
+static FloatRect computeArcBounds(const FloatPoint& center, float radius, float start, float end, bool clockwise)
+{
+ if (clockwise)
+ std::swap(start, end);
+
+ constexpr float fullCircle = 2 * piFloat;
+ if (end - start >= fullCircle) {
+ auto diameter = radius * 2;
+ return { center.x() - radius, center.y() - radius, diameter, diameter };
+ }
+
+ auto normalize = [&] (float radians) {
+ double circles = radians / fullCircle;
+ return fullCircle * (circles - floor(circles));
+ };
+
+ start = normalize(start);
+ end = normalize(end);
+
+ auto lengthInRadians = end - start;
+ if (start > end)
+ lengthInRadians += fullCircle;
+
+ FloatPoint startPoint { center.x() + radius * cos(start), center.y() + radius * sin(start) };
+ FloatPoint endPoint { center.x() + radius * cos(end), center.y() + radius * sin(end) };
+ FloatRect result;
+ result.fitToPoints(startPoint, endPoint);
+
+ auto contains = [&] (float angleToCheck) {
+ return (start < angleToCheck && start + lengthInRadians > angleToCheck)
+ || (start > angleToCheck && start + lengthInRadians > angleToCheck + fullCircle);
+ };
+
+ if (contains(0))
+ result.shiftMaxXEdgeTo(center.x() + radius);
+
+ if (contains(piOverTwoFloat))
+ result.shiftMaxYEdgeTo(center.y() + radius);
+
+ if (contains(piFloat))
+ result.shiftXEdgeTo(center.x() - radius);
+
+ if (contains(3 * piOverTwoFloat))
+ result.shiftYEdgeTo(center.y() - radius);
+
+ return result;
+}
+
Optional<FloatRect> Path::boundingRectFromInlineData() const
{
- // FIXME: Add logic to compute the exact bounding rect for an arc in inline data.
+ if (hasInlineData<ArcData>()) {
+ auto& arc = inlineData<ArcData>();
+ auto bounds = computeArcBounds(arc.center, arc.radius, arc.startAngle, arc.endAngle, arc.clockwise);
+ if (arc.type == ArcData::Type::LineAndArc || arc.type == ArcData::Type::ClosedLineAndArc)
+ bounds.extend(arc.start);
+ return bounds;
+ }
if (hasInlineData<MoveData>())
return FloatRect { };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes