Diff
Modified: trunk/LayoutTests/ChangeLog (168749 => 168750)
--- trunk/LayoutTests/ChangeLog 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/LayoutTests/ChangeLog 2014-05-13 23:25:34 UTC (rev 168750)
@@ -1,3 +1,21 @@
+2014-05-13 Myles C. Maxfield <lithe...@gmail.com>
+
+ Text decorations do not contribute to visual overflow
+ https://bugs.webkit.org/show_bug.cgi?id=132773
+
+ Reviewed by Darin Adler.
+
+ This test makes sure that repaint rects are extended to include text decorations that may
+ lie outside of the text layout rects. It compares text with an underline to text that has
+ had underline applied to it in a timer.
+
+ * fast/css3-text/css3-text-decoration/repaint/resources/Litherum.svg: Added. This font has a
+ descent of 0 (so it will not intersect underlines)
+ * fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect-expected.html: Added.
+ Apply the underline without any timeout
+ * fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect.html: Added.
+ Apply the underline with a timeout.
+
2014-05-13 Jon Honeycutt <jhoneyc...@apple.com>
platform/mac/plugins/testplugin-onnew-onpaint.html failing after r168668
Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/resources/Litherum.svg (0 => 168750)
--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/resources/Litherum.svg (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/resources/Litherum.svg 2014-05-13 23:25:34 UTC (rev 168750)
@@ -0,0 +1,12 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="Litherum" horiz-adv-x="1024">
+<font-face units-per-em="14" ascent="14" descent="0"/>
+<glyph unicode="|" horiz-adv-x="14" d="M0 0v14h14v-14z"/>
+<glyph unicode="-" horiz-adv-x="266" d="M0 0v14h266v-14z"/>
+</font>
+</defs>
+</svg>
Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect-expected.html (0 => 168750)
--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect-expected.html (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect-expected.html 2014-05-13 23:25:34 UTC (rev 168750)
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: 'Litherum';
+ src: url("./resources/Litherum.svg") format(svg)
+}
+div {
+ font-family: 'Litherum';
+ -webkit-text-decoration-skip: none;
+ -webkit-text-decoration-color: green;
+ width: 1px;
+ height: 1px;
+}
+</style>
+</head>
+<body>
+This test makes sure that underlines contribute to visual overflow.
+The SVG font has a descent of 0, which means that underlines will
+lie outside of the glyph boundaries. The test makes sure that
+drawing underlined text ends up the same as drawing text that has
+had the underline retroactively applied to it with _javascript_.
+<div style="position: relative">
+<div id="underline" style="position: absolute; left: 0px; top: 0px; text-decoration: underline;">|</div>
+<div id="underlineunder" style="position: absolute; left: 20px; top: 0px; -webkit-text-underline-position: under; text-decoration: underline">|</div>
+<div id="linethrough" style="position: absolute; left: 40px; top: 0px; text-decoration: line-through;">|</div>
+<div id="overline" style="position: absolute; left: 60px; top: 0px; text-decoration: overline;">|</div>
+
+<div id="wavyunderline" style="position: absolute; left: 0px; top: 20px; -webkit-text-decoration-style: wavy; text-decoration: underline;">|</div>
+<div id="wavyunderlineunder" style="position: absolute; left: 20px; top: 20px; -webkit-text-underline-position: under; -webkit-text-decoration-style: wavy; text-decoration: underline;">|</div>
+<div id="wavylinethrough" style="font-size: 1px; position: absolute; left: 40px; top: 20px; -webkit-text-decoration-style: wavy; text-decoration: line-through;">-</div>
+<div id="wavyoverline" style="position: absolute; left: 60px; top: 20px; -webkit-text-decoration-style: wavy; text-decoration: overline;">|</div>
+</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect.html (0 => 168750)
--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect.html (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect.html 2014-05-13 23:25:34 UTC (rev 168750)
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: 'Litherum';
+ src: url("./resources/Litherum.svg") format(svg)
+}
+div {
+ font-family: 'Litherum';
+ -webkit-text-decoration-skip: none;
+ -webkit-text-decoration-color: green;
+ width: 1px;
+ height: 1px;
+}
+</style>
+</head>
+<body>
+This test makes sure that underlines contribute to visual overflow.
+The SVG font has a descent of 0, which means that underlines will
+lie outside of the glyph boundaries. The test makes sure that
+drawing underlined text ends up the same as drawing text that has
+had the underline retroactively applied to it with _javascript_.
+<div style="position: relative">
+<div id="underline" style="position: absolute; left: 0px; top: 0px;">|</div>
+<div id="underlineunder" style="position: absolute; left: 20px; top: 0px; -webkit-text-underline-position: under;">|</div>
+<div id="linethrough" style="position: absolute; left: 40px; top: 0px;">|</div>
+<div id="overline" style="position: absolute; left: 60px; top: 0px;">|</div>
+
+<div id="wavyunderline" style="position: absolute; left: 0px; top: 20px; -webkit-text-decoration-style: wavy;">|</div>
+<div id="wavyunderlineunder" style="position: absolute; left: 20px; top: 20px; -webkit-text-underline-position: under; -webkit-text-decoration-style: wavy;">|</div>
+<div id="wavylinethrough" style="font-size: 1px; position: absolute; left: 40px; top: 20px; -webkit-text-decoration-style: wavy;">-</div>
+<div id="wavyoverline" style="position: absolute; left: 60px; top: 20px; -webkit-text-decoration-style: wavy;">|</div>
+</div>
+<script>
+function applyUnderline() {
+ document.getElementById('underline').style.textDecoration = "underline";
+ document.getElementById('underlineunder').style.textDecoration = "underline";
+ document.getElementById('linethrough').style.textDecoration = "line-through";
+ document.getElementById('overline').style.textDecoration = "overline";
+ document.getElementById('wavyunderline').style.textDecoration = "underline";
+ document.getElementById('wavyunderlineunder').style.textDecoration = "underline";
+ document.getElementById('wavylinethrough').style.textDecoration = "line-through";
+ document.getElementById('wavyoverline').style.textDecoration = "overline";
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+if (window.testRunner)
+ testRunner.waitUntilDone();
+window.addEventListener('load', applyUnderline, false);
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (168749 => 168750)
--- trunk/Source/WebCore/ChangeLog 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/ChangeLog 2014-05-13 23:25:34 UTC (rev 168750)
@@ -1,3 +1,29 @@
+2014-05-13 Myles C. Maxfield <lithe...@gmail.com>
+
+ Text decorations do not contribute to visual overflow
+ https://bugs.webkit.org/show_bug.cgi?id=132773
+
+ Reviewed by Darin Adler.
+
+ Tests: fast/css3-text/css3-text-decoration/repaint/underline-outside-of-layout-rect.html
+
+ * rendering/InlineTextBox.cpp:
+ (WebCore::textDecorationStrokeThickness): Refactor into a common function
+ (WebCore::wavyOffsetFromDecoration): Ditto
+ (WebCore::InlineTextBox::extendVerticalVisualOverflowForDecorations): Given
+ vertical overflow bounds, possibly extend those to include location of
+ decorations.
+ (WebCore::InlineTextBox::paintDecoration): Use refactored functions.
+ * rendering/InlineTextBox.h: Function signature
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::setLogicalWidthForTextRun): Call extendVerticalVisualOverflowForDecorations()
+ * rendering/style/RenderStyle.cpp:
+ (WebCore::RenderStyle::changeAffectsVisualOverflow): Inspects shadows and text decorations
+ (WebCore::RenderStyle::changeRequiresLayout): Calls changeAffectsVisualOverflow()
+ (WebCore::RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline): Moved code from here
+ to changeAffectsVisualOverflow().
+ * rendering/style/RenderStyle.h: Function signature
+
2014-05-13 Enrica Casucci <enr...@apple.com>
REGRESSION (WebKit2): Zooming to text field leaves it partially hidden by the form assistant.
Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (168749 => 168750)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2014-05-13 23:25:34 UTC (rev 168750)
@@ -973,6 +973,71 @@
context.strokePath(path);
}
+static inline float textDecorationStrokeThickness(float fontSize)
+{
+ const float textDecorationBaseFontSize = 16;
+ return fontSize / textDecorationBaseFontSize;
+}
+
+static inline float wavyOffsetFromDecoration()
+{
+ return 2;
+}
+
+void InlineTextBox::extendVerticalVisualOverflowForDecorations(float& top, float& bottom) const
+{
+ const RenderStyle& lineStyle = this->lineStyle();
+ TextDecoration decoration = lineStyle.textDecorationsInEffect();
+
+ if (decoration == TextDecorationNone)
+ return;
+
+ TextDecorationStyle decorationStyle = lineStyle.textDecorationStyle();
+ float strokeThickness = textDecorationStrokeThickness(renderer().style().fontSize());
+
+ float controlPointDistance;
+ float step;
+ float wavyOffset;
+
+ if (decorationStyle == TextDecorationStyleWavy) {
+ getWavyStrokeParameters(strokeThickness, controlPointDistance, step);
+ wavyOffset = wavyOffsetFromDecoration();
+ }
+
+ float height = logicalHeight();
+
+ // These metrics must match where underlines get drawn.
+ if (decoration & TextDecorationUnderline) {
+ float underlineOffset = computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), this, strokeThickness);
+ if (decorationStyle == TextDecorationStyleWavy) {
+ bottom = std::max(bottom, underlineOffset + wavyOffset + controlPointDistance + strokeThickness - height);
+ top = std::max(top, -(underlineOffset + wavyOffset - controlPointDistance - strokeThickness));
+ } else {
+ bottom = std::max(bottom, underlineOffset + strokeThickness - height);
+ top = std::max(top, -underlineOffset);
+ }
+ }
+ if (decoration & TextDecorationOverline) {
+ if (decorationStyle == TextDecorationStyleWavy) {
+ bottom = std::max(bottom, -wavyOffset + controlPointDistance + strokeThickness - height);
+ top = std::max(top, wavyOffset + controlPointDistance + strokeThickness);
+ } else {
+ bottom = std::max(bottom, strokeThickness - height);
+ // top is untouched
+ }
+ }
+ if (decoration & TextDecorationLineThrough) {
+ float baseline = lineStyle.fontMetrics().floatAscent();
+ if (decorationStyle == TextDecorationStyleWavy) {
+ bottom = std::max(bottom, 2 * baseline / 3 + controlPointDistance + strokeThickness - height);
+ top = std::max(top, -(2 * baseline / 3 - controlPointDistance - strokeThickness));
+ } else {
+ bottom = std::max(bottom, 2 * baseline / 3 + strokeThickness - height);
+ top = std::max(top, -(2 * baseline / 3));
+ }
+ }
+}
+
void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint& boxOrigin, TextDecoration decoration, TextDecorationStyle decorationStyle, const ShadowData* shadow, TextPainter& textPainter)
{
#if !ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
@@ -1000,8 +1065,7 @@
// Use a special function for underlines to get the positioning exactly right.
bool isPrinting = renderer().document().printing();
- const float textDecorationBaseFontSize = 16;
- float textDecorationThickness = renderer().style().fontSize() / textDecorationBaseFontSize;
+ float textDecorationThickness = textDecorationStrokeThickness(renderer().style().fontSize());
context.setStrokeThickness(textDecorationThickness);
bool linesAreOpaque = !isPrinting && (!(decoration & TextDecorationUnderline) || underline.alpha() == 255) && (!(decoration & TextDecorationOverline) || overline.alpha() == 255) && (!(decoration & TextDecorationLineThrough) || linethrough.alpha() == 255);
@@ -1047,13 +1111,13 @@
shadow = shadow->next();
}
- float wavyOffset = 2.f;
+ float wavyOffset = wavyOffsetFromDecoration();
context.setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
+ // These decorations should match the visual overflows computed in extendVerticalVisualOverflowForDecorations()
if (decoration & TextDecorationUnderline) {
context.setStrokeColor(underline, colorSpace);
- TextUnderlinePosition underlinePosition = lineStyle.textUnderlinePosition();
- const int underlineOffset = computeUnderlineOffset(underlinePosition, lineStyle.fontMetrics(), this, textDecorationThickness);
+ const int underlineOffset = computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), this, textDecorationThickness);
switch (decorationStyle) {
case TextDecorationStyleWavy: {
Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (168749 => 168750)
--- trunk/Source/WebCore/rendering/InlineTextBox.h 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h 2014-05-13 23:25:34 UTC (rev 168750)
@@ -159,6 +159,7 @@
public:
virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
virtual float positionForOffset(int offset) const;
+ void extendVerticalVisualOverflowForDecorations(float& top, float& bottom) const;
// Needs to be public, so the static paintTextWithShadows() function can use it.
static FloatSize applyShadowToGraphicsContext(GraphicsContext*, const ShadowData*, const FloatRect& textRect, bool stroked, bool opaque, bool horizontal);
Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (168749 => 168750)
--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2014-05-13 23:25:34 UTC (rev 168750)
@@ -524,7 +524,17 @@
copyToVector(fallbackFonts, it->value.first);
run->box()->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
}
- if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)) {
+
+ // Include text decoration visual overflow as part of the glyph overflow.
+ if (renderer->style().textDecorationsInEffect() != TextDecorationNone) {
+ float top = glyphOverflow.top;
+ float bottom = glyphOverflow.bottom;
+ toInlineTextBox(run->box())->extendVerticalVisualOverflowForDecorations(top, bottom);
+ glyphOverflow.top = static_cast<int>(ceilf(top));
+ glyphOverflow.bottom = static_cast<int>(ceilf(bottom));
+ }
+
+ if (glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right) {
ASSERT(run->box()->behavesLikeText());
GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->box()), std::make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
it->value.second = glyphOverflow;
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.cpp (168749 => 168750)
--- trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2014-05-13 23:25:34 UTC (rev 168750)
@@ -382,6 +382,22 @@
return true;
}
+inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const
+{
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()
+ && !rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
+ return true;
+
+ if (inherited_flags._text_decorations != other.inherited_flags._text_decorations
+ || visual->textDecoration != other.visual->textDecoration
+ || rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
+ || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor
+ || rareInheritedData->m_textDecorationSkip != other.rareInheritedData->m_textDecorationSkip)
+ return true;
+
+ return false;
+}
+
bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
{
if (m_box->width() != other->m_box->width()
@@ -404,6 +420,10 @@
if (surround->padding != other->surround->padding)
return true;
+ // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
+ if (changeAffectsVisualOverflow(*other))
+ return true;
+
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance
|| rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
@@ -434,10 +454,6 @@
|| rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
return true;
- // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
- if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
- return true;
-
if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
return true;
@@ -714,11 +730,6 @@
bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
{
if (inherited->color != other->inherited->color
- || inherited_flags._text_decorations != other->inherited_flags._text_decorations
- || visual->textDecoration != other->visual->textDecoration
- || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
- || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
- || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip
|| rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
|| rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
|| rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (168749 => 168750)
--- trunk/Source/WebCore/rendering/style/RenderStyle.h 2014-05-13 23:06:14 UTC (rev 168749)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h 2014-05-13 23:25:34 UTC (rev 168750)
@@ -1936,6 +1936,7 @@
static ptrdiff_t noninheritedFlagsMemoryOffset() { return OBJECT_OFFSETOF(RenderStyle, noninherited_flags); }
private:
+ bool changeAffectsVisualOverflow(const RenderStyle&) const;
bool changeRequiresLayout(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
bool changeRequiresPositionedLayoutOnly(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
bool changeRequiresLayerRepaint(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;