- Revision
- 258151
- Author
- wenson_hs...@apple.com
- Date
- 2020-03-09 12:55:54 -0700 (Mon, 09 Mar 2020)
Log Message
Creating paths that are single-segment bezier or quad curves should not require a CGPath allocation
https://bugs.webkit.org/show_bug.cgi?id=208812
Reviewed by Tim Horton.
Extend the inline path data mechanism introduced in r258118 to encompass two more cases of simple path objects:
single-segment quad and bezier curves. In these scenarios, we can simply store the start point, end point, and
one or two control points (respectively). See below for more details; there should be no change in behavior.
* platform/graphics/InlinePathData.h:
Add the new inline path data types to the variant. Note that does not increase the size of the InlinePathData
variant, nor does it increase the size of Path, since the variant is already 32 bytes large due to ArcData.
(WebCore::QuadCurveData::encode const):
(WebCore::QuadCurveData::decode):
(WebCore::BezierCurveData::encode const):
(WebCore::BezierCurveData::decode):
Add encoders and decoders for QuadCurveData and BezierCurveData.
* platform/graphics/Path.cpp:
(WebCore::Path::apply const):
In the cases where we have quad and bezier curves, we can apply the path without having to fall back to
allocating a platform path object.
(WebCore::Path::currentPoint const):
Return endPoint in both of the new inline curve cases.
(WebCore::Path::elementCount const):
Return 2 in both of the new cases.
(WebCore::Path::addQuadCurveTo):
(WebCore::Path::addBezierCurveTo):
If the path is null (we haven't modified anything yet) or the path was only moved to some location, stuff
information about the quad or bezier curve into inline data on Path and avoid creating a CGPath on CoreGraphics
platforms (and other types of platform paths elsewhere).
* platform/graphics/Path.h:
* platform/graphics/cairo/PathCairo.cpp:
(WebCore::Path::addQuadCurveToSlowCase):
(WebCore::Path::addBezierCurveToSlowCase):
(WebCore::Path::addQuadCurveTo): Deleted.
(WebCore::Path::addBezierCurveTo): Deleted.
* platform/graphics/cg/PathCG.cpp:
(WebCore::Path::createCGPath const):
(WebCore::Path::addQuadCurveToSlowCase):
(WebCore::Path::addBezierCurveToSlowCase):
Add -SlowCase suffixes to these methods, and move the main implementation of addQuadCurve and addBezierCurve
into platform-agnostic code in Path.cpp where we update the inline path data and bail early if appropriate, and
otherwise fall back to addQuadCurveToSlowCase or addBezierCurveToSlowCase.
(WebCore::Path::addQuadCurveTo): Deleted.
(WebCore::Path::addBezierCurveTo): Deleted.
* platform/graphics/win/PathDirect2D.cpp:
(WebCore::Path::addQuadCurveToSlowCase):
(WebCore::Path::addBezierCurveToSlowCase):
(WebCore::Path::addQuadCurveTo): Deleted.
(WebCore::Path::addBezierCurveTo): Deleted.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (258150 => 258151)
--- trunk/Source/WebCore/ChangeLog 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/ChangeLog 2020-03-09 19:55:54 UTC (rev 258151)
@@ -1,3 +1,70 @@
+2020-03-09 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Creating paths that are single-segment bezier or quad curves should not require a CGPath allocation
+ https://bugs.webkit.org/show_bug.cgi?id=208812
+
+ Reviewed by Tim Horton.
+
+ Extend the inline path data mechanism introduced in r258118 to encompass two more cases of simple path objects:
+ single-segment quad and bezier curves. In these scenarios, we can simply store the start point, end point, and
+ one or two control points (respectively). See below for more details; there should be no change in behavior.
+
+ * platform/graphics/InlinePathData.h:
+
+ Add the new inline path data types to the variant. Note that does not increase the size of the InlinePathData
+ variant, nor does it increase the size of Path, since the variant is already 32 bytes large due to ArcData.
+
+ (WebCore::QuadCurveData::encode const):
+ (WebCore::QuadCurveData::decode):
+ (WebCore::BezierCurveData::encode const):
+ (WebCore::BezierCurveData::decode):
+
+ Add encoders and decoders for QuadCurveData and BezierCurveData.
+
+ * platform/graphics/Path.cpp:
+ (WebCore::Path::apply const):
+
+ In the cases where we have quad and bezier curves, we can apply the path without having to fall back to
+ allocating a platform path object.
+
+ (WebCore::Path::currentPoint const):
+
+ Return endPoint in both of the new inline curve cases.
+
+ (WebCore::Path::elementCount const):
+
+ Return 2 in both of the new cases.
+
+ (WebCore::Path::addQuadCurveTo):
+ (WebCore::Path::addBezierCurveTo):
+
+ If the path is null (we haven't modified anything yet) or the path was only moved to some location, stuff
+ information about the quad or bezier curve into inline data on Path and avoid creating a CGPath on CoreGraphics
+ platforms (and other types of platform paths elsewhere).
+
+ * platform/graphics/Path.h:
+ * platform/graphics/cairo/PathCairo.cpp:
+ (WebCore::Path::addQuadCurveToSlowCase):
+ (WebCore::Path::addBezierCurveToSlowCase):
+ (WebCore::Path::addQuadCurveTo): Deleted.
+ (WebCore::Path::addBezierCurveTo): Deleted.
+ * platform/graphics/cg/PathCG.cpp:
+ (WebCore::Path::createCGPath const):
+ (WebCore::Path::addQuadCurveToSlowCase):
+ (WebCore::Path::addBezierCurveToSlowCase):
+
+ Add -SlowCase suffixes to these methods, and move the main implementation of addQuadCurve and addBezierCurve
+ into platform-agnostic code in Path.cpp where we update the inline path data and bail early if appropriate, and
+ otherwise fall back to addQuadCurveToSlowCase or addBezierCurveToSlowCase.
+
+ (WebCore::Path::addQuadCurveTo): Deleted.
+ (WebCore::Path::addBezierCurveTo): Deleted.
+ * platform/graphics/win/PathDirect2D.cpp:
+ (WebCore::Path::addQuadCurveToSlowCase):
+ (WebCore::Path::addBezierCurveToSlowCase):
+ (WebCore::Path::addQuadCurveTo): Deleted.
+ (WebCore::Path::addBezierCurveTo): Deleted.
+
2020-03-09 Antoine Quint <grao...@apple.com>
Remove the compile-time flag for Pointer Events
Modified: trunk/Source/WebCore/platform/graphics/InlinePathData.h (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/InlinePathData.h 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/InlinePathData.h 2020-03-09 19:55:54 UTC (rev 258151)
@@ -61,6 +61,25 @@
template<class Decoder> static Optional<MoveData> decode(Decoder&);
};
+struct QuadCurveData {
+ FloatPoint startPoint;
+ FloatPoint controlPoint;
+ FloatPoint endPoint;
+
+ template<class Encoder> void encode(Encoder&) const;
+ template<class Decoder> static Optional<QuadCurveData> decode(Decoder&);
+};
+
+struct BezierCurveData {
+ FloatPoint startPoint;
+ FloatPoint controlPoint1;
+ FloatPoint controlPoint2;
+ FloatPoint endPoint;
+
+ template<class Encoder> void encode(Encoder&) const;
+ template<class Decoder> static Optional<BezierCurveData> decode(Decoder&);
+};
+
template<class Encoder> void MoveData::encode(Encoder& encoder) const
{
encoder << location;
@@ -130,8 +149,56 @@
return data;
}
-using InlinePathData = Variant<Monostate, MoveData, LineData, ArcData>;
+template<class Encoder> void QuadCurveData::encode(Encoder& encoder) const
+{
+ encoder << startPoint;
+ encoder << controlPoint;
+ encoder << endPoint;
+}
+template<class Decoder> Optional<QuadCurveData> QuadCurveData::decode(Decoder& decoder)
+{
+ QuadCurveData data;
+ if (!decoder.decode(data.startPoint))
+ return WTF::nullopt;
+
+ if (!decoder.decode(data.controlPoint))
+ return WTF::nullopt;
+
+ if (!decoder.decode(data.endPoint))
+ return WTF::nullopt;
+
+ return data;
+}
+
+template<class Encoder> void BezierCurveData::encode(Encoder& encoder) const
+{
+ encoder << startPoint;
+ encoder << controlPoint1;
+ encoder << controlPoint2;
+ encoder << endPoint;
+}
+
+template<class Decoder> Optional<BezierCurveData> BezierCurveData::decode(Decoder& decoder)
+{
+ BezierCurveData data;
+ if (!decoder.decode(data.startPoint))
+ return WTF::nullopt;
+
+ if (!decoder.decode(data.controlPoint1))
+ return WTF::nullopt;
+
+ if (!decoder.decode(data.controlPoint2))
+ return WTF::nullopt;
+
+ if (!decoder.decode(data.endPoint))
+ return WTF::nullopt;
+
+ return data;
+}
+
+using InlinePathData = Variant<Monostate, MoveData, LineData, ArcData, QuadCurveData, BezierCurveData>;
+
} // namespace WebCore
#endif // ENABLE(INLINE_PATH_DATA)
Modified: trunk/Source/WebCore/platform/graphics/Path.cpp (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/Path.cpp 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/Path.cpp 2020-03-09 19:55:54 UTC (rev 258151)
@@ -192,6 +192,33 @@
function(element);
return;
}
+
+ if (hasInlineData<BezierCurveData>()) {
+ auto& curve = WTF::get<BezierCurveData>(m_inlineData);
+ PathElement element;
+ element.type = PathElement::Type::MoveToPoint;
+ element.points[0] = curve.startPoint;
+ function(element);
+ element.type = PathElement::Type::AddCurveToPoint;
+ element.points[0] = curve.controlPoint1;
+ element.points[1] = curve.controlPoint2;
+ element.points[2] = curve.endPoint;
+ function(element);
+ return;
+ }
+
+ if (hasInlineData<QuadCurveData>()) {
+ auto& curve = WTF::get<QuadCurveData>(m_inlineData);
+ PathElement element;
+ element.type = PathElement::Type::MoveToPoint;
+ element.points[0] = curve.startPoint;
+ function(element);
+ element.type = PathElement::Type::AddQuadCurveToPoint;
+ element.points[0] = curve.controlPoint;
+ element.points[1] = curve.endPoint;
+ function(element);
+ return;
+ }
#endif
applySlowCase(function);
@@ -226,6 +253,12 @@
if (hasInlineData<LineData>())
return WTF::get<LineData>(m_inlineData).end;
+
+ if (hasInlineData<BezierCurveData>())
+ return WTF::get<BezierCurveData>(m_inlineData).endPoint;
+
+ if (hasInlineData<QuadCurveData>())
+ return WTF::get<QuadCurveData>(m_inlineData).endPoint;
#endif
return currentPointSlowCase();
@@ -237,7 +270,7 @@
if (hasInlineData<MoveData>())
return 1;
- if (hasInlineData<LineData>())
+ if (hasInlineData<LineData>() || hasInlineData<BezierCurveData>() || hasInlineData<QuadCurveData>())
return 2;
#endif
@@ -289,6 +322,39 @@
addLineToSlowCase(point);
}
+void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint)
+{
+#if ENABLE(INLINE_PATH_DATA)
+ if (isNull() || hasInlineData<MoveData>()) {
+ QuadCurveData curve;
+ curve.startPoint = hasAnyInlineData() ? WTF::get<MoveData>(m_inlineData).location : FloatPoint();
+ curve.controlPoint = controlPoint;
+ curve.endPoint = endPoint;
+ m_inlineData = { WTFMove(curve) };
+ return;
+ }
+#endif
+
+ addQuadCurveToSlowCase(controlPoint, endPoint);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint)
+{
+#if ENABLE(INLINE_PATH_DATA)
+ if (isNull() || hasInlineData<MoveData>()) {
+ BezierCurveData curve;
+ curve.startPoint = hasAnyInlineData() ? WTF::get<MoveData>(m_inlineData).location : FloatPoint();
+ curve.controlPoint1 = controlPoint1;
+ curve.controlPoint2 = controlPoint2;
+ curve.endPoint = endPoint;
+ m_inlineData = { WTFMove(curve) };
+ return;
+ }
+#endif
+
+ addBezierCurveToSlowCase(controlPoint1, controlPoint2, endPoint);
+}
+
void Path::moveTo(const FloatPoint& point)
{
#if ENABLE(INLINE_PATH_DATA)
Modified: trunk/Source/WebCore/platform/graphics/Path.h (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/Path.h 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/Path.h 2020-03-09 19:55:54 UTC (rev 258151)
@@ -236,6 +236,8 @@
void moveToSlowCase(const FloatPoint&);
void addLineToSlowCase(const FloatPoint&);
void addArcSlowCase(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
+ void addQuadCurveToSlowCase(const FloatPoint& controlPoint, const FloatPoint& endPoint);
+ void addBezierCurveToSlowCase(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint);
FloatRect boundingRectSlowCase() const;
FloatRect fastBoundingRectSlowCase() const;
Modified: trunk/Source/WebCore/platform/graphics/cairo/PathCairo.cpp (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/cairo/PathCairo.cpp 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/cairo/PathCairo.cpp 2020-03-09 19:55:54 UTC (rev 258151)
@@ -158,7 +158,7 @@
/*
* inspired by libsvg-cairo
*/
-void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& point)
+void Path::addQuadCurveToSlowCase(const FloatPoint& controlPoint, const FloatPoint& point)
{
cairo_t* cr = ensurePlatformPath()->context();
double x, y;
@@ -173,7 +173,7 @@
x2, y2);
}
-void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& controlPoint3)
+void Path::addBezierCurveToSlowCase(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& controlPoint3)
{
cairo_t* cr = ensurePlatformPath()->context();
cairo_curve_to(cr, controlPoint1.x(), controlPoint1.y(),
Modified: trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp 2020-03-09 19:55:54 UTC (rev 258151)
@@ -101,6 +101,14 @@
if (arc.hasOffset)
CGPathMoveToPoint(m_path.get(), nullptr, arc.offset.x(), arc.offset.y());
CGPathAddArc(m_path.get(), nullptr, arc.center.x(), arc.center.y(), arc.radius, arc.startAngle, arc.endAngle, arc.clockwise);
+ },
+ [&](const QuadCurveData& curve) {
+ CGPathMoveToPoint(m_path.get(), nullptr, curve.startPoint.x(), curve.startPoint.y());
+ CGPathAddQuadCurveToPoint(m_path.get(), nullptr, curve.controlPoint.x(), curve.controlPoint.y(), curve.endPoint.x(), curve.endPoint.y());
+ },
+ [&](const BezierCurveData& curve) {
+ CGPathMoveToPoint(m_path.get(), nullptr, curve.startPoint.x(), curve.startPoint.y());
+ CGPathAddCurveToPoint(m_path.get(), nullptr, curve.controlPoint1.x(), curve.controlPoint1.y(), curve.controlPoint2.x(), curve.controlPoint2.y(), curve.endPoint.x(), curve.endPoint.y());
}
);
}
@@ -316,12 +324,12 @@
CGPathAddLineToPoint(ensurePlatformPath(), nullptr, p.x(), p.y());
}
-void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+void Path::addQuadCurveToSlowCase(const FloatPoint& cp, const FloatPoint& p)
{
CGPathAddQuadCurveToPoint(ensurePlatformPath(), nullptr, cp.x(), cp.y(), p.x(), p.y());
}
-void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+void Path::addBezierCurveToSlowCase(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
{
CGPathAddCurveToPoint(ensurePlatformPath(), nullptr, cp1.x(), cp1.y(), cp2.x(), cp2.y(), p.x(), p.y());
}
Modified: trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp (258150 => 258151)
--- trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp 2020-03-09 19:53:50 UTC (rev 258150)
+++ trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp 2020-03-09 19:55:54 UTC (rev 258151)
@@ -394,13 +394,13 @@
m_activePath->AddLine(point);
}
-void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+void Path::addQuadCurveToSlowCase(const FloatPoint& cp, const FloatPoint& p)
{
openFigureAtCurrentPointIfNecessary();
m_activePath->AddQuadraticBezier(D2D1::QuadraticBezierSegment(cp, p));
}
-void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+void Path::addBezierCurveToSlowCase(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
{
openFigureAtCurrentPointIfNecessary();
m_activePath->AddBezier(D2D1::BezierSegment(cp1, cp2, p));