Title: [258151] trunk/Source/WebCore
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));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to