Space between double underlines does not scale with font size
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Mar 2014 23:49:27 +0000 (23:49 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Mar 2014 23:49:27 +0000 (23:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=129521

Reviewed by Simon Fraser.

Source/WebCore:

This patch moves the logic about how far to draw the second underline (when text-decoration-style: double
is specified) from InlineTextBox to GraphicsContext, because GraphicsContext is the authoritative source
about how thick underlines should be. The space between the two underlines is set to the thickness of
each of the underlines.

This patch also deletes some unused code in InlineTextBox that was never getting triggered, in addition
to unifying drawLineForText with drawLinesForText. This didn't have any performance impact in my testing.

Test: fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html

* platform/graphics/GraphicsContext.h: drawLineForText takes a boolean for if we should draw double
underlines.
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContext::drawLineForText):
(WebCore::GraphicsContext::drawLinesForText):
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::drawLineForText):
* platform/graphics/wince/GraphicsContextWinCE.cpp:
(WebCore::GraphicsContext::drawLineForText):
* rendering/InlineTextBox.cpp: Use new boolean argument
(WebCore::drawSkipInkUnderline):
(WebCore::InlineTextBox::paintDecoration):

LayoutTests:

This test renders large text with a double underline, but then barely clips off the bottom underline
using overflow: hidden. It makes sure that this is exactly the same as a single underline. If the
space between the two underlines does not scale with font size, it will appear as though there is a
single thick underline (because they will be drawn on top of each other) and will thus fail this test.

* fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales-expected.html: Added.
* fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales-expected.html [new file with mode: 0644]
LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsContext.h
Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
Source/WebCore/rendering/InlineTextBox.cpp

index cbcf66827d6f72bcff8d6bd37c69681ce59bf6fd..bac652183355bc9bbe4a2fd02b7ffb85400b8018 100644 (file)
@@ -1,3 +1,18 @@
+2014-03-03  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        Space between double underlines does not scale with font size
+        https://bugs.webkit.org/show_bug.cgi?id=129521
+
+        Reviewed by Simon Fraser.
+
+        This test renders large text with a double underline, but then barely clips off the bottom underline
+        using overflow: hidden. It makes sure that this is exactly the same as a single underline. If the
+        space between the two underlines does not scale with font size, it will appear as though there is a
+        single thick underline (because they will be drawn on top of each other) and will thus fail this test.
+
+        * fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales-expected.html: Added.
+        * fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html: Added.
+
 2014-03-03  Mark Lam  <mark.lam@apple.com>
 
         Web Inspector: debugger statements do not break.
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales-expected.html b/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales-expected.html
new file mode 100644 (file)
index 0000000..6b8da7d
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+This test renders large text with a double underline, but then barely clips off the bottom underline
+using overflow: hidden. It makes sure that this is exactly the same as a single underline. If the
+space between the two underlines does not scale with font size, it will appear as though there is a
+single thick underline (because they will be drawn on top of each other) and will thus fail this test.
+<div style="text-decoration: underline; font-size: 100px; font-family: Ahem;">&nbsp;</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html b/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html
new file mode 100644 (file)
index 0000000..06d3ecf
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+This test renders large text with a double underline, but then barely clips off the bottom underline
+using overflow: hidden. It makes sure that this is exactly the same as a single underline. If the
+space between the two underlines does not scale with font size, it will appear as though there is a
+single thick underline (because they will be drawn on top of each other) and will thus fail this test.
+<div style="width: 100px; height: 99px; overflow: hidden;">
+<div style="text-decoration: underline; font-size: 100px; -webkit-text-decoration-style: double; font-family: Ahem;">&nbsp;</div>
+</div>
+</body>
+</html>
index 094e57f53408b368f800d420f1d9a4d43e820c45..924d545e79326ac9b8af047af1dc175fcec1594b 100644 (file)
@@ -1,3 +1,33 @@
+2014-03-03  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        Space between double underlines does not scale with font size
+        https://bugs.webkit.org/show_bug.cgi?id=129521
+
+        Reviewed by Simon Fraser.
+
+        This patch moves the logic about how far to draw the second underline (when text-decoration-style: double
+        is specified) from InlineTextBox to GraphicsContext, because GraphicsContext is the authoritative source
+        about how thick underlines should be. The space between the two underlines is set to the thickness of
+        each of the underlines.
+
+        This patch also deletes some unused code in InlineTextBox that was never getting triggered, in addition
+        to unifying drawLineForText with drawLinesForText. This didn't have any performance impact in my testing.
+
+        Test: fast/css3-text/css3-text-decoration/text-decoration-style-double-space-scales.html
+
+        * platform/graphics/GraphicsContext.h: drawLineForText takes a boolean for if we should draw double
+        underlines.
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::drawLineForText):
+        (WebCore::GraphicsContext::drawLinesForText):
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::drawLineForText):
+        * platform/graphics/wince/GraphicsContextWinCE.cpp:
+        (WebCore::GraphicsContext::drawLineForText):
+        * rendering/InlineTextBox.cpp: Use new boolean argument
+        (WebCore::drawSkipInkUnderline):
+        (WebCore::InlineTextBox::paintDecoration):
+
 2014-02-28  Chris Fleizach  <cfleizach@apple.com>
 
         AX: Support IOS Accessibility in WK2
index a9bf5d004ce11baca7071962046d9834ce2e0fe5..ab79a34a85381761fb1404f3f636ed7faa4b3182 100644 (file)
@@ -368,8 +368,8 @@ namespace WebCore {
         FloatRect roundToDevicePixels(const FloatRect&, RoundingMode = RoundAllSides);
 
         FloatRect computeLineBoundsForText(const FloatPoint&, float width, bool printing);
-        void drawLineForText(const FloatPoint&, float width, bool printing);
-        void drawLinesForText(const FloatPoint&, const DashArray& widths, bool printing);
+        void drawLineForText(const FloatPoint&, float width, bool printing, bool doubleLines = false);
+        void drawLinesForText(const FloatPoint&, const DashArray& widths, bool printing, bool doubleLines = false);
         enum DocumentMarkerLineStyle {
 #if PLATFORM(IOS)
             TextCheckingDictationPhraseWithAlternativesLineStyle,
index 1ddf60f25754d1528ab0cd4b959cfd3e52e4ed63..7a660d9d339f20156979dd5999f0b33dcfdba246 100644 (file)
@@ -619,7 +619,7 @@ FloatRect GraphicsContext::computeLineBoundsForText(const FloatPoint& origin, fl
     return FloatRect(origin, FloatSize(width, strokeThickness()));
 }
 
-void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing)
+void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing, bool doubleUnderlines)
 {
     if (paintingDisabled())
         return;
@@ -634,17 +634,21 @@ void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, boo
     ShadowBlur& shadow = platformContext()->shadowBlur();
     if (GraphicsContext* shadowContext = shadow.beginShadowLayer(this, lineExtents)) {
         drawLineOnCairoContext(this, shadowContext->platformContext()->cr(), origin, endPoint);
+        if (doubleUnderlines)
+            drawLineOnCairoContext(this, shadowContext->platformContext()->cr(), origin + FloatSize(0, strokeThickness() * 2), endPoint + FloatSize(0, strokeThickness() * 2));
         shadow.endShadowLayer(this);
     }
 
     drawLineOnCairoContext(this, cairoContext, origin, endPoint);
+    if (doubleUnderlines)
+        drawLineOnCairoContext(this, cairoContext, origin + FloatSize(0, strokeThickness() * 2), endPoint + FloatSize(0, strokeThickness() * 2));
     cairo_restore(cairoContext);
 }
 
-void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing)
+void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing, bool doubleUnderlines)
 {
     for (size_t i = 0; i < widths.size(); i += 2)
-        drawLineForText(FloatPoint(point.x() + widths[i], point.y()), widths[i+1] - widths[i], printing);
+        drawLineForText(FloatPoint(point.x() + widths[i], point.y()), widths[i+1] - widths[i], printing, doubleUnderlines);
 }
 
 void GraphicsContext::updateDocumentMarkerResources()
index 24d11f90523756485bef37553776fd8d12196e9e..26d21e1f164a12b3ad2c21c970a7a41bcf3cf8e1 100644 (file)
@@ -1392,36 +1392,15 @@ FloatRect GraphicsContext::computeLineBoundsForText(const FloatPoint& point, flo
     return computeLineBoundsAndAntialiasingModeForText(*this, point, width, printing, dummyBool, dummyColor);
 }
 
-void GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool printing)
+void GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool printing, bool doubleLines)
 {
-    if (paintingDisabled())
-        return;
-
-    if (width <= 0)
-        return;
-
-    Color localStrokeColor(strokeColor());
-
-    bool shouldAntialiasLine;
-    FloatRect bounds = computeLineBoundsAndAntialiasingModeForText(*this, point, width, printing, shouldAntialiasLine, localStrokeColor);
-    bool fillColorIsNotEqualToStrokeColor = fillColor() != localStrokeColor;
-
-#if PLATFORM(IOS)
-    if (m_state.shouldUseContextColors)
-#endif
-        if (fillColorIsNotEqualToStrokeColor)
-            setCGFillColor(platformContext(), localStrokeColor, strokeColorSpace());
-
-    CGContextFillRect(platformContext(), bounds);
-
-#if PLATFORM(IOS)
-    if (m_state.shouldUseContextColors)
-#endif
-        if (fillColorIsNotEqualToStrokeColor)
-            setCGFillColor(platformContext(), fillColor(), fillColorSpace());
+    DashArray widths;
+    widths.append(width);
+    widths.append(0);
+    drawLinesForText(point, widths, printing, doubleLines);
 }
 
-void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing)
+void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing, bool doubleLines)
 {
     if (paintingDisabled())
         return;
@@ -1441,6 +1420,12 @@ void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray&
     for (size_t i = 0; i < widths.size(); i += 2)
         dashBounds.append(CGRectMake(bounds.x() + widths[i], bounds.y(), widths[i+1] - widths[i], bounds.height()));
 
+    if (doubleLines) {
+        // The space between double underlines is equal to the height of the underline
+        for (size_t i = 0; i < widths.size(); i += 2)
+            dashBounds.append(CGRectMake(bounds.x() + widths[i], bounds.y() + 2 * bounds.height(), widths[i+1] - widths[i], bounds.height()));
+    }
+
 #if PLATFORM(IOS)
     if (m_state.shouldUseContextColors)
 #endif
index 8299d634aeb2dddcaae931e611c3d068669a6866..9d0f717d70bd9810980233923166c270a79b8101 100644 (file)
@@ -953,7 +953,7 @@ FloatRect GraphicsContext::computeLineBoundsForText(const FloatPoint& origin, fl
     return FloatRect(origin, FloatSize(width, strokeThickness()));
 }
 
-void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing)
+void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing, bool doubleUnderlines)
 {
     if (paintingDisabled())
         return;
@@ -961,13 +961,15 @@ void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, boo
     StrokeStyle oldStyle = strokeStyle();
     setStrokeStyle(SolidStroke);
     drawLine(roundedIntPoint(origin), roundedIntPoint(origin + FloatSize(width, 0)));
+    if (doubleUnderlines)
+        drawLine(roundedIntPoint(origin + FloatSize(0, strokeThickness() * 2)), roundedIntPoint(origin + FloatSize(width, strokeThickness() * 2)));
     setStrokeStyle(oldStyle);
 }
 
-void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing)
+void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing, bool doubleUnderlines)
 {
     for (size_t i = 0; i < widths.size(); i += 2)
-        drawLineForText(FloatPoint(point.x() + widths[i], point.y()), widths[i+1] - widths[i], printing);
+        drawLineForText(FloatPoint(point.x() + widths[i], point.y()), widths[i+1] - widths[i], printing, doubleUnderlines);
 }
 
 void GraphicsContext::updateDocumentMarkerResources()
index 5bfe3c7c89f54747c6426c1adb48cc3aed66247b..d6fcfd4930fe7aff9fd35f3de9868526b4b2092d 100644 (file)
@@ -118,7 +118,7 @@ static DashArray translateIntersectionPointsToSkipInkBoundaries(const DashArray&
     return result;
 }
 
-static void drawSkipInkUnderline(TextPainter& textPainter, GraphicsContext& context, FloatPoint localOrigin, float underlineOffset, float width, bool isPrinting)
+static void drawSkipInkUnderline(TextPainter& textPainter, GraphicsContext& context, FloatPoint localOrigin, float underlineOffset, float width, bool isPrinting, bool doubleLines)
 {
     FloatPoint adjustedLocalOrigin = localOrigin;
     adjustedLocalOrigin.move(0, underlineOffset);
@@ -127,7 +127,7 @@ static void drawSkipInkUnderline(TextPainter& textPainter, GraphicsContext& cont
     DashArray a = translateIntersectionPointsToSkipInkBoundaries(intersections, underlineBoundingBox.height(), width);
 
     ASSERT(!(a.size() % 2));
-    context.drawLinesForText(adjustedLocalOrigin, a, isPrinting);
+    context.drawLinesForText(adjustedLocalOrigin, a, isPrinting, doubleLines);
 }
 #endif
 
@@ -984,56 +984,6 @@ static void strokeWavyTextDecoration(GraphicsContext& context, FloatPoint& p1, F
     context.strokePath(path);
 }
 
-// Because finding the bounding box of an underline is structurally similar to finding
-// the bounding box of a strikethrough, we can pull out the computation and parameterize
-// by the location of the decoration (yOffset, underlineOffset, and doubleOffset).
-static FloatRect boundingBoxForSingleDecoration(GraphicsContext& context, float textDecorationThickness,
-    float width, FloatPoint localOrigin, TextDecorationStyle decorationStyle,
-    bool isPrinting, float yOffset, float underlineOffset, float doubleOffset)
-{
-    FloatRect boundingBox;
-
-    switch (decorationStyle) {
-    case TextDecorationStyleWavy: {
-        FloatPoint start(localOrigin.x(), localOrigin.y() + yOffset);
-        FloatPoint end = start + FloatSize(width, 0);
-        context.adjustLineToPixelBoundaries(start, end, textDecorationThickness, context.strokeStyle());
-
-        float controlPointDistance;
-        float step;
-        getWavyStrokeParameters(textDecorationThickness, controlPointDistance, step);
-
-        adjustStepToDecorationLength(step, controlPointDistance, width);
-
-        controlPointDistance += textDecorationThickness;
-        FloatPoint boundingBoxOrigin = start - FloatSize(0, controlPointDistance);
-        FloatSize boundingBoxSize = FloatSize(width, 2 * controlPointDistance);
-        boundingBox = FloatRect(boundingBoxOrigin, boundingBoxSize);
-        break;
-    }
-    default:
-        boundingBox = context.computeLineBoundsForText(localOrigin + FloatSize(0, underlineOffset), width, isPrinting);
-        if (decorationStyle == TextDecorationStyleDouble)
-            boundingBox.unite(context.computeLineBoundsForText(localOrigin + FloatSize(0, doubleOffset), width, isPrinting));
-    }
-    return boundingBox;
-}
-
-static FloatRect boundingBoxForAllActiveDecorations(InlineTextBox& inlineTextBox, GraphicsContext& context, TextDecoration decoration, float textDecorationThickness, float width, float doubleOffset, TextDecorationStyle decorationStyle, const FloatPoint localOrigin, const RenderStyle& lineStyle, bool isPrinting, int baseline)
-{
-    FloatRect boundingBox;
-    if (decoration & TextDecorationUnderline) {
-        int underlineOffset = computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), &inlineTextBox, textDecorationThickness);
-        
-        boundingBox.unite(boundingBoxForSingleDecoration(context, textDecorationThickness, width, localOrigin, decorationStyle, isPrinting, underlineOffset + doubleOffset, underlineOffset, baseline + 1));
-    }
-    if (decoration & TextDecorationOverline)
-        boundingBox.unite(boundingBoxForSingleDecoration(context, textDecorationThickness, width, localOrigin, decorationStyle, isPrinting, -doubleOffset, 0, -doubleOffset));
-    if (decoration & TextDecorationLineThrough)
-        boundingBox.unite(boundingBoxForSingleDecoration(context, textDecorationThickness, width, localOrigin, decorationStyle, isPrinting, 2 * baseline / 3, 2 * baseline / 3, doubleOffset + 2 * baseline / 3));
-    return boundingBox;
-}
-
 void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint& boxOrigin, TextDecoration decoration, TextDecorationStyle decorationStyle, const ShadowData* shadow, TextPainter& textPainter)
 {
     // FIXME: We should improve this rule and not always just assume 1.
@@ -1107,37 +1057,9 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint&
             setShadow = true;
             shadow = shadow->next();
         }
-
-        // Offset between lines - always non-zero, so lines never cross each other.
-        float doubleOffset = textDecorationThickness + 1;
-        
-        bool clipDecorationToMask = false;
         
-        GraphicsContextStateSaver stateSaver(context, false);
-        
-        if (clipDecorationToMask) {
-            const float skipInkGapWidth = 1;
-
-            stateSaver.save();
-
-            FloatRect underlineRect = boundingBoxForAllActiveDecorations(*this, context, decoration, textDecorationThickness, width, doubleOffset, decorationStyle, localOrigin, lineStyle, isPrinting, baseline);
-            IntRect enclosingDeviceRect = enclosingIntRect(underlineRect);
-            std::unique_ptr<ImageBuffer> imageBuffer = context.createCompatibleBuffer(enclosingDeviceRect.size());
-
-            if (imageBuffer.get()) {
-                GraphicsContext& maskContext = *imageBuffer->context();
-                maskContext.setFillColor(Color::black, ColorSpaceDeviceRGB);
-                maskContext.setLineJoin(RoundJoin);
-                maskContext.translate(FloatPoint() - enclosingDeviceRect.location());
-
-                maskContext.fillRect(enclosingDeviceRect);
-                maskContext.setCompositeOperation(CompositeClear);
-    
-                textPainter.paintTextInContext(maskContext, skipInkGapWidth);
+        float wavyOffset = 2.f;
 
-                context.clipToImageBuffer(imageBuffer.get(), enclosingDeviceRect);
-            }
-        }
         context.setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
         if (decoration & TextDecorationUnderline) {
             context.setStrokeColor(underline, colorSpace);
@@ -1146,8 +1068,8 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint&
 
             switch (decorationStyle) {
             case TextDecorationStyleWavy: {
-                FloatPoint start(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset);
-                FloatPoint end(localOrigin.x() + width, localOrigin.y() + underlineOffset + doubleOffset);
+                FloatPoint start(localOrigin.x(), localOrigin.y() + underlineOffset + wavyOffset);
+                FloatPoint end(localOrigin.x() + width, localOrigin.y() + underlineOffset + wavyOffset);
                 strokeWavyTextDecoration(context, start, end, textDecorationThickness);
                 break;
             }
@@ -1155,54 +1077,34 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint&
 #if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
                 if ((lineStyle.textDecorationSkip() == TextDecorationSkipInk || lineStyle.textDecorationSkip() == TextDecorationSkipAuto) && isHorizontal()) {
                     if (!context.paintingDisabled()) {
-                        drawSkipInkUnderline(textPainter, context, localOrigin, underlineOffset, width, isPrinting);
-
-                        if (decorationStyle == TextDecorationStyleDouble)
-                            drawSkipInkUnderline(textPainter, context, localOrigin, underlineOffset + doubleOffset, width, isPrinting);
+                        drawSkipInkUnderline(textPainter, context, localOrigin, underlineOffset, width, isPrinting, decorationStyle == TextDecorationStyleDouble);
                     }
-                } else {
+                } else
                     // FIXME: Need to support text-decoration-skip: none.
 #endif // CSS3_TEXT_DECORATION_SKIP_INK
-                    context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset), width, isPrinting);
-
-                    if (decorationStyle == TextDecorationStyleDouble)
-                        context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset), width, isPrinting);
-#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
-                }
-#endif
+                    context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset), width, isPrinting, decorationStyle == TextDecorationStyleDouble);
             }
         }
         if (decoration & TextDecorationOverline) {
             context.setStrokeColor(overline, colorSpace);
             switch (decorationStyle) {
             case TextDecorationStyleWavy: {
-                FloatPoint start(localOrigin.x(), localOrigin.y() - doubleOffset);
-                FloatPoint end(localOrigin.x() + width, localOrigin.y() - doubleOffset);
+                FloatPoint start(localOrigin.x(), localOrigin.y() - wavyOffset);
+                FloatPoint end(localOrigin.x() + width, localOrigin.y() - wavyOffset);
                 strokeWavyTextDecoration(context, start, end, textDecorationThickness);
                 break;
             }
             default:
 #if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
                 if ((lineStyle.textDecorationSkip() == TextDecorationSkipInk || lineStyle.textDecorationSkip() == TextDecorationSkipAuto) && isHorizontal()) {
-                    if (!context.paintingDisabled()) {
-                        drawSkipInkUnderline(textPainter, context, localOrigin, 0, width, isPrinting);
-
-                        if (decorationStyle == TextDecorationStyleDouble)
-                            drawSkipInkUnderline(textPainter, context, localOrigin, -doubleOffset, width, isPrinting);
-                    }
-                } else {
+                    if (!context.paintingDisabled())
+                        drawSkipInkUnderline(textPainter, context, localOrigin, 0, width, isPrinting, decorationStyle == TextDecorationStyleDouble);
+                } else
                     // FIXME: Need to support text-decoration-skip: none.
 #endif // CSS3_TEXT_DECORATION_SKIP_INK
-                    context.drawLineForText(localOrigin, width, isPrinting);
-                    if (decorationStyle == TextDecorationStyleDouble)
-                        context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
-#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
-                }
-#endif
+                    context.drawLineForText(localOrigin, width, isPrinting, decorationStyle == TextDecorationStyleDouble);
             }
         }
-        if (clipDecorationToMask)
-            stateSaver.restore();
         if (decoration & TextDecorationLineThrough) {
             context.setStrokeColor(linethrough, colorSpace);
             switch (decorationStyle) {
@@ -1213,9 +1115,7 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint&
                 break;
             }
             default:
-                context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
-                if (decorationStyle == TextDecorationStyleDouble)
-                    context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
+                context.drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting, decorationStyle == TextDecorationStyleDouble);
             }
         }
     } while (shadow);