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.