Title: [224820] trunk/Source/WebCore
Revision
224820
Author
zandober...@gmail.com
Date
2017-11-14 10:02:41 -0800 (Tue, 14 Nov 2017)

Log Message

[Cairo] Move drawLine operation from GraphicsContextCairo to CairoOperations
https://bugs.webkit.org/show_bug.cgi?id=179669

Reviewed by Carlos Garcia Campos.

Move the drawLine operation implementation into the CairoOperations
implementation file, with the Cairo::drawLine() function only expecting
a PlatformContextCairo object, two FloatingPoints, and a const reference
to a GraphicsContextState object.

As with drawLinesForText(), the drawLine() implementation utilized a few
private GraphicsContext methods that we for now reimplement in the
Cairo namespace as static functions, providing necessary state values to
perform the computations. The GraphicsContext methods should be changed
to become static public functions -- after that we'll be able to remove
the new duplicated helper functions.

No new tests -- no change in behavior.

* platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::dashedLineCornerWidthForStrokeWidth):
(WebCore::Cairo::dashedLinePatternWidthForStrokeWidth):
(WebCore::Cairo::dashedLinePatternOffsetForPatternAndStrokeWidth):
(WebCore::Cairo::centerLineAndCutOffCorners):
(WebCore::Cairo::drawLine):
* platform/graphics/cairo/CairoOperations.h:
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::drawLine):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (224819 => 224820)


--- trunk/Source/WebCore/ChangeLog	2017-11-14 17:44:17 UTC (rev 224819)
+++ trunk/Source/WebCore/ChangeLog	2017-11-14 18:02:41 UTC (rev 224820)
@@ -1,3 +1,34 @@
+2017-11-14  Zan Dobersek  <zdober...@igalia.com>
+
+        [Cairo] Move drawLine operation from GraphicsContextCairo to CairoOperations
+        https://bugs.webkit.org/show_bug.cgi?id=179669
+
+        Reviewed by Carlos Garcia Campos.
+
+        Move the drawLine operation implementation into the CairoOperations
+        implementation file, with the Cairo::drawLine() function only expecting
+        a PlatformContextCairo object, two FloatingPoints, and a const reference
+        to a GraphicsContextState object.
+
+        As with drawLinesForText(), the drawLine() implementation utilized a few
+        private GraphicsContext methods that we for now reimplement in the
+        Cairo namespace as static functions, providing necessary state values to
+        perform the computations. The GraphicsContext methods should be changed
+        to become static public functions -- after that we'll be able to remove
+        the new duplicated helper functions.
+
+        No new tests -- no change in behavior.
+
+        * platform/graphics/cairo/CairoOperations.cpp:
+        (WebCore::Cairo::dashedLineCornerWidthForStrokeWidth):
+        (WebCore::Cairo::dashedLinePatternWidthForStrokeWidth):
+        (WebCore::Cairo::dashedLinePatternOffsetForPatternAndStrokeWidth):
+        (WebCore::Cairo::centerLineAndCutOffCorners):
+        (WebCore::Cairo::drawLine):
+        * platform/graphics/cairo/CairoOperations.h:
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::drawLine):
+
 2017-11-14  Tim Horton  <timothy_hor...@apple.com>
 
         Long pressing a phone number with spaces in it results in a link sheet instead of a data detectors sheet

Modified: trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp (224819 => 224820)


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2017-11-14 17:44:17 UTC (rev 224819)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2017-11-14 18:02:41 UTC (rev 224820)
@@ -266,6 +266,65 @@
     return FloatRect(origin, FloatSize(width, thickness));
 };
 
+// FIXME: Replace once GraphicsContext::dashedLineCornerWidthForStrokeWidth()
+// is refactored as a static public function.
+static float dashedLineCornerWidthForStrokeWidth(float strokeWidth, const GraphicsContextState& state)
+{
+    float thickness = state.strokeThickness;
+    return state.strokeStyle == DottedStroke ? thickness : std::min(2.0f * thickness, std::max(thickness, strokeWidth / 3.0f));
+}
+
+// FIXME: Replace once GraphicsContext::dashedLinePatternWidthForStrokeWidth()
+// is refactored as a static public function.
+static float dashedLinePatternWidthForStrokeWidth(float strokeWidth, const GraphicsContextState& state)
+{
+    float thickness = state.strokeThickness;
+    return state.strokeStyle == DottedStroke ? thickness : std::min(3.0f * thickness, std::max(thickness, strokeWidth / 3.0f));
+}
+
+// FIXME: Replace once GraphicsContext::dashedLinePatternOffsetForPatternAndStrokeWidth()
+// is refactored as a static public function.
+static float dashedLinePatternOffsetForPatternAndStrokeWidth(float patternWidth, float strokeWidth)
+{
+    // Pattern starts with full fill and ends with the empty fill.
+    // 1. Let's start with the empty phase after the corner.
+    // 2. Check if we've got odd or even number of patterns and whether they fully cover the line.
+    // 3. In case of even number of patterns and/or remainder, move the pattern start position
+    // so that the pattern is balanced between the corners.
+    float patternOffset = patternWidth;
+    int numberOfSegments = std::floor(strokeWidth / patternWidth);
+    bool oddNumberOfSegments = numberOfSegments % 2;
+    float remainder = strokeWidth - (numberOfSegments * patternWidth);
+    if (oddNumberOfSegments && remainder)
+        patternOffset -= remainder / 2.0f;
+    else if (!oddNumberOfSegments) {
+        if (remainder)
+            patternOffset += patternOffset - (patternWidth + remainder) / 2.0f;
+        else
+            patternOffset += patternWidth / 2.0f;
+    }
+
+    return patternOffset;
+}
+
+// FIXME: Replace once GraphicsContext::centerLineAndCutOffCorners()
+// is refactored as a static public function.
+static Vector<FloatPoint> centerLineAndCutOffCorners(bool isVerticalLine, float cornerWidth, FloatPoint point1, FloatPoint point2)
+{
+    // Center line and cut off corners for pattern painting.
+    if (isVerticalLine) {
+        float centerOffset = (point2.x() - point1.x()) / 2.0f;
+        point1.move(centerOffset, cornerWidth);
+        point2.move(-centerOffset, -cornerWidth);
+    } else {
+        float centerOffset = (point2.y() - point1.y()) / 2.0f;
+        point1.move(cornerWidth, centerOffset);
+        point2.move(-cornerWidth, -centerOffset);
+    }
+
+    return { point1, point2 };
+}
+
 namespace State {
 
 void setStrokeThickness(PlatformContextCairo& platformContext, float strokeThickness)
@@ -656,6 +715,64 @@
     cairo_restore(cr);
 }
 
+void drawLine(PlatformContextCairo& platformContext, const FloatPoint& point1, const FloatPoint& point2, const GraphicsContextState& state)
+{
+    bool isVerticalLine = (point1.x() + state.strokeThickness == point2.x());
+    float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
+    if (!state.strokeThickness || !strokeWidth)
+        return;
+
+    cairo_t* cairoContext = platformContext.cr();
+    float cornerWidth = 0;
+    bool drawsDashedLine = state.strokeStyle == DottedStroke || state.strokeStyle == DashedStroke;
+
+    if (drawsDashedLine) {
+        cairo_save(cairoContext);
+        // Figure out end points to ensure we always paint corners.
+        cornerWidth = dashedLineCornerWidthForStrokeWidth(strokeWidth, state);
+        if (isVerticalLine) {
+            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), state.strokeThickness, cornerWidth), state.strokeColor);
+            fillRectWithColor(cairoContext, FloatRect(point1.x(), point2.y() - cornerWidth, state.strokeThickness, cornerWidth), state.strokeColor);
+        } else {
+            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), cornerWidth, state.strokeThickness), state.strokeColor);
+            fillRectWithColor(cairoContext, FloatRect(point2.x() - cornerWidth, point1.y(), cornerWidth, state.strokeThickness), state.strokeColor);
+        }
+        strokeWidth -= 2 * cornerWidth;
+        float patternWidth = dashedLinePatternWidthForStrokeWidth(strokeWidth, state);
+        // Check if corner drawing sufficiently covers the line.
+        if (strokeWidth <= patternWidth + 1) {
+            cairo_restore(cairoContext);
+            return;
+        }
+
+        float patternOffset = dashedLinePatternOffsetForPatternAndStrokeWidth(patternWidth, strokeWidth);
+        const double dashedLine[2] = { static_cast<double>(patternWidth), static_cast<double>(patternWidth) };
+        cairo_set_dash(cairoContext, dashedLine, 2, patternOffset);
+    } else {
+        setSourceRGBAFromColor(cairoContext, state.strokeColor);
+        if (state.strokeThickness < 1)
+            cairo_set_line_width(cairoContext, 1);
+    }
+
+
+    auto centeredPoints = centerLineAndCutOffCorners(isVerticalLine, cornerWidth, point1, point2);
+    auto p1 = centeredPoints[0];
+    auto p2 = centeredPoints[1];
+
+    if (state.shouldAntialias)
+        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_NONE);
+
+    cairo_new_path(cairoContext);
+    cairo_move_to(cairoContext, p1.x(), p1.y());
+    cairo_line_to(cairoContext, p2.x(), p2.y());
+    cairo_stroke(cairoContext);
+    if (drawsDashedLine)
+        cairo_restore(cairoContext);
+
+    if (state.shouldAntialias)
+        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_DEFAULT);
+}
+
 void drawLinesForText(PlatformContextCairo& platformContext, const FloatPoint& point, const DashArray& widths, bool printing, bool doubleUnderlines, const Color& color, float strokeThickness)
 {
     Color modifiedColor = color;

Modified: trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h (224819 => 224820)


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2017-11-14 17:44:17 UTC (rev 224819)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2017-11-14 18:02:41 UTC (rev 224820)
@@ -99,6 +99,7 @@
 void drawPattern(PlatformContextCairo&, Image&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, CompositeOperator, BlendMode);
 
 void drawRect(PlatformContextCairo&, const FloatRect&, float, const GraphicsContextState&);
+void drawLine(PlatformContextCairo&, const FloatPoint&, const FloatPoint&, const GraphicsContextState&);
 void drawLinesForText(PlatformContextCairo&, const FloatPoint&, const DashArray&, bool, bool, const Color&, float);
 void drawLineForDocumentMarker(PlatformContextCairo&, const FloatPoint&, float, GraphicsContext::DocumentMarkerLineStyle);
 void drawEllipse(PlatformContextCairo&, const FloatRect&, const GraphicsContextState&);

Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp (224819 => 224820)


--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2017-11-14 17:44:17 UTC (rev 224819)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2017-11-14 18:02:41 UTC (rev 224820)
@@ -272,62 +272,8 @@
         return;
     }
 
-    const Color& strokeColor = this->strokeColor();
-    float thickness = strokeThickness();
-    bool isVerticalLine = (point1.x() + thickness == point2.x());
-    float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
-    if (!thickness || !strokeWidth)
-        return;
-
-    cairo_t* cairoContext = platformContext()->cr();
-    StrokeStyle strokeStyle = this->strokeStyle();
-    float cornerWidth = 0;
-    bool drawsDashedLine = strokeStyle == DottedStroke || strokeStyle == DashedStroke;
-
-    if (drawsDashedLine) {
-        cairo_save(cairoContext);
-        // Figure out end points to ensure we always paint corners.
-        cornerWidth = dashedLineCornerWidthForStrokeWidth(strokeWidth);
-        if (isVerticalLine) {
-            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), thickness, cornerWidth), strokeColor);
-            fillRectWithColor(cairoContext, FloatRect(point1.x(), point2.y() - cornerWidth, thickness, cornerWidth), strokeColor);
-        } else {
-            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), cornerWidth, thickness), strokeColor);
-            fillRectWithColor(cairoContext, FloatRect(point2.x() - cornerWidth, point1.y(), cornerWidth, thickness), strokeColor);
-        }
-        strokeWidth -= 2 * cornerWidth;
-        float patternWidth = dashedLinePatternWidthForStrokeWidth(strokeWidth);
-        // Check if corner drawing sufficiently covers the line.
-        if (strokeWidth <= patternWidth + 1) {
-            cairo_restore(cairoContext);
-            return;
-        }
-
-        float patternOffset = dashedLinePatternOffsetForPatternAndStrokeWidth(patternWidth, strokeWidth);
-        const double dashedLine[2] = { static_cast<double>(patternWidth), static_cast<double>(patternWidth) };
-        cairo_set_dash(cairoContext, dashedLine, 2, patternOffset);
-    } else {
-        setSourceRGBAFromColor(cairoContext, strokeColor);
-        if (thickness < 1)
-            cairo_set_line_width(cairoContext, 1);
-    }
-
-
-    auto centeredPoints = centerLineAndCutOffCorners(isVerticalLine, cornerWidth, point1, point2);
-    auto p1 = centeredPoints[0];
-    auto p2 = centeredPoints[1];
-
-    if (shouldAntialias())
-        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_NONE);
-
-    cairo_new_path(cairoContext);
-    cairo_move_to(cairoContext, p1.x(), p1.y());
-    cairo_line_to(cairoContext, p2.x(), p2.y());
-    cairo_stroke(cairoContext);
-    if (drawsDashedLine)
-        cairo_restore(cairoContext);
-    if (shouldAntialias())
-        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_DEFAULT);
+    ASSERT(hasPlatformContext());
+    Cairo::drawLine(*platformContext(), point1, point2, state());
 }
 
 // This method is only used to draw the little circles used in lists.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to