Outline: auto has sharp corners with single line contenteditable.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Mar 2016 17:22:54 +0000 (17:22 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Mar 2016 17:22:54 +0000 (17:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155418

Reviewed by Tim Horton.

Multiple rectangles assumed multiline content and it broke bottomLeft and bottomRight corner check.
This patch adds fast path for polygons with 4 corners.

Source/WebCore:

Test: fast/inline/hidpi-outline-auto-with-one-focusring-rect.html

* platform/graphics/PathUtilities.cpp:
(WebCore::cornerType):
(WebCore::cornerTypeForMultiline):
(WebCore::rectFromPolygon):
(WebCore::PathUtilities::pathWithShrinkWrappedRectsForOutline):

LayoutTests:

* fast/inline/hidpi-outline-auto-with-one-focusring-rect-expected.html: Added.
* fast/inline/hidpi-outline-auto-with-one-focusring-rect.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198138 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect-expected.html [new file with mode: 0644]
LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/PathUtilities.cpp

index a7ad7d1..a00da30 100644 (file)
@@ -1,3 +1,16 @@
+2016-03-14  Zalan Bujtas  <zalan@apple.com>
+
+        Outline: auto has sharp corners with single line contenteditable.
+        https://bugs.webkit.org/show_bug.cgi?id=155418
+
+        Reviewed by Tim Horton.
+
+        Multiple rectangles assumed multiline content and it broke bottomLeft and bottomRight corner check.
+        This patch adds fast path for polygons with 4 corners.
+
+        * fast/inline/hidpi-outline-auto-with-one-focusring-rect-expected.html: Added.
+        * fast/inline/hidpi-outline-auto-with-one-focusring-rect.html: Added.
+
 2016-03-14  Joanmarie Diggs  <jdiggs@igalia.com>
 
         [AX] SVG element with child desc not exposed
diff --git a/LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect-expected.html b/LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect-expected.html
new file mode 100644 (file)
index 0000000..d5a12cd
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests when focusring collects multiple rects but they end up being one final rect.</title>
+</head>
+<body></body>
+</html>
diff --git a/LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect.html b/LayoutTests/fast/inline/hidpi-outline-auto-with-one-focusring-rect.html
new file mode 100644 (file)
index 0000000..23befa3
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests when focusring collects multiple rects but they end up being one final rect.</title>
+<style>
+div {
+    position: absolute;
+}
+
+.border-radius {
+       outline-style: auto;
+    border-radius: 10px 10px 10px 10px;
+    color: white;
+    top: 10px;
+    left: 10px;
+       width: 300px;
+       height: 40px;
+}
+
+.cover {
+    border: 6px solid white;
+    border-radius: 14px 14px 14px 14px;
+    top: 6px;
+    left: 6px;
+    width: 296px;
+    height: 36px;
+}
+</style>
+</head>
+<body>
+<div class=border-radius contentEditable="true">foobar foobar foobar</div>
+<div class=cover></div>
+</body>
+</html>
index f3592cc..c987a46 100644 (file)
@@ -1,3 +1,21 @@
+2016-03-14  Zalan Bujtas  <zalan@apple.com>
+
+        Outline: auto has sharp corners with single line contenteditable.
+        https://bugs.webkit.org/show_bug.cgi?id=155418
+
+        Reviewed by Tim Horton.
+
+        Multiple rectangles assumed multiline content and it broke bottomLeft and bottomRight corner check.
+        This patch adds fast path for polygons with 4 corners.
+
+        Test: fast/inline/hidpi-outline-auto-with-one-focusring-rect.html
+
+        * platform/graphics/PathUtilities.cpp:
+        (WebCore::cornerType):
+        (WebCore::cornerTypeForMultiline):
+        (WebCore::rectFromPolygon):
+        (WebCore::PathUtilities::pathWithShrinkWrappedRectsForOutline):
+
 2016-03-14  Joanmarie Diggs  <jdiggs@igalia.com>
 
         [AX] SVG element with child desc not exposed
index 3a9983c..d7c322c 100644 (file)
@@ -307,7 +307,7 @@ Vector<Path> PathUtilities::pathsWithShrinkWrappedRects(const Vector<FloatRect>&
 
     for (auto& poly : polys) {
         Path path;
-        for (unsigned i = 0; i < poly.size(); i++) {
+        for (unsigned i = 0; i < poly.size(); ++i) {
             FloatPointGraph::Edge& toEdge = poly[i];
             // Connect the first edge to the last.
             FloatPointGraph::Edge& fromEdge = (i > 0) ? poly[i - 1] : poly[poly.size() - 1];
@@ -373,22 +373,36 @@ static std::pair<FloatPoint, FloatPoint> startAndEndPointsForCorner(const FloatP
 }
 
 enum class CornerType { TopLeft, TopRight, BottomRight, BottomLeft, Other };
-static CornerType cornerType(const FloatPointGraph::Edge& fromEdge, const FloatPointGraph::Edge& toEdge, const Vector<FloatPoint>& corners)
+static CornerType cornerType(const FloatPointGraph::Edge& fromEdge, const FloatPointGraph::Edge& toEdge)
 {
     auto fromEdgeVector = *fromEdge.second - *fromEdge.first;
     auto toEdgeVector = *toEdge.second - *toEdge.first;
 
-    if (fromEdgeVector.height() < 0 && toEdgeVector.width() > 0 && corners.at(0) == *fromEdge.second)
+    if (fromEdgeVector.height() < 0 && toEdgeVector.width() > 0)
         return CornerType::TopLeft;
-    if (fromEdgeVector.width() > 0 && toEdgeVector.height() > 0 && corners.at(1) == *fromEdge.second)
+    if (fromEdgeVector.width() > 0 && toEdgeVector.height() > 0)
         return CornerType::TopRight;
-    if (fromEdgeVector.height() > 0 && toEdgeVector.width() < 0 && corners.at(2) == *fromEdge.second)
+    if (fromEdgeVector.height() > 0 && toEdgeVector.width() < 0)
         return CornerType::BottomRight;
-    if (fromEdgeVector.width() < 0 && toEdgeVector.height() < 0 && corners.at(3) == *fromEdge.second)
+    if (fromEdgeVector.width() < 0 && toEdgeVector.height() < 0)
         return CornerType::BottomLeft;
     return CornerType::Other;
 }
 
+static CornerType cornerTypeForMultiline(const FloatPointGraph::Edge& fromEdge, const FloatPointGraph::Edge& toEdge, const Vector<FloatPoint>& corners)
+{
+    auto corner = cornerType(fromEdge, toEdge);
+    if (corner == CornerType::TopLeft && corners.at(0) == *fromEdge.second)
+        return corner;
+    if (corner == CornerType::TopRight && corners.at(1) == *fromEdge.second)
+        return corner;
+    if (corner == CornerType::BottomRight && corners.at(2) == *fromEdge.second)
+        return corner;
+    if (corner == CornerType::BottomLeft && corners.at(3) == *fromEdge.second)
+        return corner;
+    return CornerType::Other;
+}
+
 static std::pair<FloatPoint, FloatPoint> controlPointsForBezierCurve(CornerType cornerType, const FloatPointGraph::Edge& fromEdge,
     const FloatPointGraph::Edge& toEdge, const FloatSize& radius)
 {
@@ -445,6 +459,30 @@ static FloatRoundedRect::Radii adjustedtRadiiForHuggingCurve(const FloatSize& to
     return radii;
 }
     
+static Optional<FloatRect> rectFromPolygon(const FloatPointGraph::Polygon& poly)
+{
+    if (poly.size() != 4)
+        return Optional<FloatRect>();
+
+    Optional<FloatPoint> topLeft;
+    Optional<FloatPoint> bottomRight;
+    for (unsigned i = 0; i < poly.size(); ++i) {
+        const auto& toEdge = poly[i];
+        const auto& fromEdge = (i > 0) ? poly[i - 1] : poly[poly.size() - 1];
+        auto corner = cornerType(fromEdge, toEdge);
+        if (corner == CornerType::TopLeft) {
+            ASSERT(!topLeft);
+            topLeft = *fromEdge.second;
+        } else if (corner == CornerType::BottomRight) {
+            ASSERT(!bottomRight);
+            bottomRight = *fromEdge.second;
+        }
+    }
+    if (!topLeft || !bottomRight)
+        return Optional<FloatRect>();
+    return FloatRect(topLeft.value(), bottomRight.value());
+}
+
 Path PathUtilities::pathWithShrinkWrappedRectsForOutline(const Vector<FloatRect>& rects, const BorderData& borderData, float outlineOffset, TextDirection direction,
     WritingMode writingMode)
 {
@@ -453,21 +491,31 @@ Path PathUtilities::pathWithShrinkWrappedRectsForOutline(const Vector<FloatRect>
     FloatSize topRightRadius = FloatSize(borderData.topRight().width().value(), borderData.topRight().height().value());
     FloatSize bottomRightRadius = FloatSize(borderData.bottomRight().width().value(), borderData.bottomRight().height().value());
     FloatSize bottomLeftRadius = FloatSize(borderData.bottomLeft().width().value(), borderData.bottomLeft().height().value());
-    if (rects.size() == 1) {
-        FloatRect rect = rects.at(0);
+
+    auto roundedRect = [topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, outlineOffset] (const FloatRect& rect)
+    {
         auto radii = adjustedtRadiiForHuggingCurve(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, outlineOffset);
         radii.scale(calcBorderRadiiConstraintScaleFor(rect, radii));
 
         Path path;
         path.addRoundedRect(FloatRoundedRect(rect, radii));
         return path;
-    }
+    };
+
+    if (rects.size() == 1)
+        return roundedRect(rects.at(0));
 
     FloatPointGraph graph;
     const auto polys = polygonsForRect(rects, graph);
     // Fall back to corner painting with no radius for empty and disjoint rectangles.
     if (!polys.size() || polys.size() > 1)
         return Path();
+    const auto& poly = polys.at(0);
+    // Fast path when poly has one rect only.
+    Optional<FloatRect> rect = rectFromPolygon(poly);
+    if (rect)
+        return roundedRect(rect.value());
+
     Path path;
     // Multiline outline needs to match multiline border painting. Only first and last lines are getting rounded borders.
     auto isLeftToRight = isLeftToRightDirection(direction);
@@ -490,8 +538,7 @@ Path PathUtilities::pathWithShrinkWrappedRectsForOutline(const Vector<FloatRect>
     corners.append(lastLineRect.maxXMaxYCorner());
     corners.append(isHorizontal ? firstLineRect.minXMaxYCorner() : lastLineRect.minXMaxYCorner());
 
-    const auto& poly = polys.at(0);
-    for (unsigned i = 0; i < poly.size(); i++) {
+    for (unsigned i = 0; i < poly.size(); ++i) {
         auto moveOrAddLineTo = [i, &path] (const FloatPoint& startPoint)
         {
             if (!i)
@@ -502,7 +549,7 @@ Path PathUtilities::pathWithShrinkWrappedRectsForOutline(const Vector<FloatRect>
         const auto& toEdge = poly[i];
         const auto& fromEdge = (i > 0) ? poly[i - 1] : poly[poly.size() - 1];
         FloatSize radius;
-        auto corner = cornerType(fromEdge, toEdge, corners);
+        auto corner = cornerTypeForMultiline(fromEdge, toEdge, corners);
         switch (corner) {
         case CornerType::TopLeft: {
             radius = topLeftRadius;