Parsing support for text-underline-offset and text-decoration-thickness
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Nov 2018 00:11:15 +0000 (00:11 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Nov 2018 00:11:15 +0000 (00:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191242

Reviewed by Simon Fraser.

Source/WebCore:

Before we can implement the properties properly, we have to parse them.

https://github.com/w3c/csswg-drafts/issues/3118#issuecomment-432297480 describes the grammar:
text-underline-position: auto | [ [ under | from-font] || [ left | right ] ]
text-underline-offset: auto | <length>
text-decoration-thickness: auto | from-font | <length>

This patch also takes the opportunity to update the grammar of text-underline-position to match the spec,
and to add an alias to the unprefixed version.

We still don't support the left and right values on text-underline-position. We should add those eventually.

Tests: fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html
       fast/css3-text/css3-text-decoration/text-underline-offset-parse.html

* WebCore.xcodeproj/project.pbxproj:
* css/CSSComputedStyleDeclaration.cpp:
(WebCore::textUnderlineOffsetToCSSValue):
(WebCore::textDecorationThicknessToCSSValue):
(WebCore::ComputedStyleExtractor::valueForPropertyinStyle):
* css/CSSPrimitiveValueMappings.h:
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
(WebCore::CSSPrimitiveValue::operator TextUnderlinePosition const):
(WebCore::CSSPrimitiveValue::operator OptionSet<TextUnderlinePosition> const): Deleted.
* css/CSSProperties.json:
* css/CSSValueKeywords.in:
* css/StyleBuilderConverter.h:
(WebCore::StyleBuilderConverter::convertTextUnderlinePosition):
(WebCore::StyleBuilderConverter::convertTextUnderlineOffset):
(WebCore::StyleBuilderConverter::convertTextDecorationThickness):
* css/StyleResolver.cpp:
(WebCore::shouldApplyPropertyInParseOrder):
* css/parser/CSSPropertyParser.cpp:
(WebCore::consumeTextUnderlineOffset):
(WebCore::consumeTextDecorationThickness):
(WebCore::CSSPropertyParser::parseSingleValue):
* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::textUnderlinePosition const):
(WebCore::RenderStyle::textUnderlineOffset const):
(WebCore::RenderStyle::textDecorationThickness const):
(WebCore::RenderStyle::setTextUnderlinePosition):
(WebCore::RenderStyle::setTextUnderlineOffset):
(WebCore::RenderStyle::setTextDecorationThickness):
(WebCore::RenderStyle::initialTextUnderlinePosition):
(WebCore::RenderStyle::initialTextUnderlineOffset):
(WebCore::RenderStyle::initialTextDecorationThickness):
* rendering/style/RenderStyleConstants.h:
* rendering/style/StyleRareInheritedData.cpp:
(WebCore::StyleRareInheritedData::StyleRareInheritedData):
(WebCore::StyleRareInheritedData::operator== const):
* rendering/style/StyleRareInheritedData.h:
* rendering/style/TextDecorationThickness.h: Added.
(WebCore::TextDecorationThickness::createWithAuto):
(WebCore::TextDecorationThickness::createFromFont):
(WebCore::TextDecorationThickness::createWithLength):
(WebCore::TextDecorationThickness::isAuto const):
(WebCore::TextDecorationThickness::isFromFont const):
(WebCore::TextDecorationThickness::isLength const):
(WebCore::TextDecorationThickness::setLengthValue):
(WebCore::TextDecorationThickness::lengthValue const):
(WebCore::TextDecorationThickness::operator== const):
(WebCore::TextDecorationThickness::operator!= const):
(WebCore::TextDecorationThickness::TextDecorationThickness):
(WebCore::operator<<):
* rendering/style/TextUnderlineOffset.h: Added.
(WebCore::TextUnderlineOffset::createWithAuto):
(WebCore::TextUnderlineOffset::createWithLength):
(WebCore::TextUnderlineOffset::isAuto const):
(WebCore::TextUnderlineOffset::isLength const):
(WebCore::TextUnderlineOffset::setLengthValue):
(WebCore::TextUnderlineOffset::lengthValue const):
(WebCore::TextUnderlineOffset::lengthOr const):
(WebCore::TextUnderlineOffset::operator== const):
(WebCore::TextUnderlineOffset::operator!= const):
(WebCore::TextUnderlineOffset::TextUnderlineOffset):
(WebCore::operator<<):
* style/InlineTextBoxStyle.cpp:
(WebCore::computeUnderlineOffset):
* style/InlineTextBoxStyle.h:

LayoutTests:

* fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt:
* fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position.html: Update the
test for the new grammar of text-underline-position
* fast/css3-text/css3-text-decoration/text-decoration-thickness-parse-expected.txt: Added.
* fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html: Added.
* fast/css3-text/css3-text-decoration/text-underline-offset-parse-expected.txt: Added.
* fast/css3-text/css3-text-decoration/text-underline-offset-parse.html: Added.

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt
LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position.html
LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse-expected.txt [new file with mode: 0644]
LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html [new file with mode: 0644]
LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse-expected.txt [new file with mode: 0644]
LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSPrimitiveValueMappings.h
Source/WebCore/css/CSSProperties.json
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/StyleBuilderConverter.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/RenderStyleConstants.h
Source/WebCore/rendering/style/StyleRareInheritedData.cpp
Source/WebCore/rendering/style/StyleRareInheritedData.h
Source/WebCore/rendering/style/TextDecorationThickness.h [new file with mode: 0644]
Source/WebCore/rendering/style/TextUnderlineOffset.h [new file with mode: 0644]
Source/WebCore/style/InlineTextBoxStyle.cpp
Source/WebCore/style/InlineTextBoxStyle.h

index 7be73b9..2368539 100644 (file)
@@ -1,5 +1,20 @@
 2018-11-05  Myles C. Maxfield  <mmaxfield@apple.com>
 
+        Parsing support for text-underline-offset and text-decoration-thickness
+        https://bugs.webkit.org/show_bug.cgi?id=191242
+
+        Reviewed by Simon Fraser.
+
+        * fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt:
+        * fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position.html: Update the
+        test for the new grammar of text-underline-position
+        * fast/css3-text/css3-text-decoration/text-decoration-thickness-parse-expected.txt: Added.
+        * fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html: Added.
+        * fast/css3-text/css3-text-decoration/text-underline-offset-parse-expected.txt: Added.
+        * fast/css3-text/css3-text-decoration/text-underline-offset-parse.html: Added.
+
+2018-11-05  Myles C. Maxfield  <mmaxfield@apple.com>
+
         Spelling dots are drawn in the wrong place
         https://bugs.webkit.org/show_bug.cgi?id=190764
 
index 89c6f8c..ed1d570 100644 (file)
@@ -31,14 +31,6 @@ PASS computedStyle.webkitTextUnderlinePosition is 'auto'
 PASS computedStyle.getPropertyCSSValue('-webkit-text-underline-position').toString() is '[object CSSPrimitiveValue]'
 PASS computedStyle.getPropertyCSSValue('-webkit-text-underline-position').cssText is 'auto'
 
-Value 'alphabetic':
-PASS e.style.webkitTextUnderlinePosition is 'alphabetic'
-PASS e.style.getPropertyCSSValue('-webkit-text-underline-position').toString() is '[object CSSPrimitiveValue]'
-PASS e.style.getPropertyCSSValue('-webkit-text-underline-position').cssText is 'alphabetic'
-PASS computedStyle.webkitTextUnderlinePosition is 'alphabetic'
-PASS computedStyle.getPropertyCSSValue('-webkit-text-underline-position').toString() is '[object CSSPrimitiveValue]'
-PASS computedStyle.getPropertyCSSValue('-webkit-text-underline-position').cssText is 'alphabetic'
-
 Value 'under':
 PASS e.style.webkitTextUnderlinePosition is 'under'
 PASS e.style.getPropertyCSSValue('-webkit-text-underline-position').toString() is '[object CSSPrimitiveValue]'
index 7f37928..a969306 100644 (file)
@@ -25,7 +25,7 @@ function testComputedStyle(propertyJS, propertyCSS, type, value)
 
 description("Test to make sure -webkit-text-underline-position property returns values properly.")
 
-// FIXME: This test tests property values 'auto', 'alphabetic' and 'under'. We don't fully match
+// FIXME: This test tests property values 'auto' and 'under'. We don't fully match
 // the specification as we don't support [ left | right ] and this is left for another implementation
 // as the rendering will need to be added.
 
@@ -59,12 +59,6 @@ testElementStyle("webkitTextUnderlinePosition", "-webkit-text-underline-position
 testComputedStyle("webkitTextUnderlinePosition", "-webkit-text-underline-position", "[object CSSPrimitiveValue]", "auto");
 debug('');
 
-debug("Value 'alphabetic':");
-e.style.webkitTextUnderlinePosition = 'alphabetic';
-testElementStyle("webkitTextUnderlinePosition", "-webkit-text-underline-position", "[object CSSPrimitiveValue]", "alphabetic");
-testComputedStyle("webkitTextUnderlinePosition", "-webkit-text-underline-position", "[object CSSPrimitiveValue]", "alphabetic");
-debug('');
-
 debug("Value 'under':");
 e.style.webkitTextUnderlinePosition = 'under';
 testElementStyle("webkitTextUnderlinePosition", "-webkit-text-underline-position", "[object CSSPrimitiveValue]", "under");
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse-expected.txt b/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse-expected.txt
new file mode 100644 (file)
index 0000000..7cc9949
--- /dev/null
@@ -0,0 +1,19 @@
+PASS window.getComputedStyle(document.getElementById('test1')).getPropertyValue('text-decoration-thickness') is "auto"
+PASS window.getComputedStyle(document.getElementById('test2')).getPropertyValue('text-decoration-thickness') is "auto"
+PASS window.getComputedStyle(document.getElementById('test3')).getPropertyValue('text-decoration-thickness') is "from-font"
+PASS window.getComputedStyle(document.getElementById('test4')).getPropertyValue('text-decoration-thickness') is "auto"
+PASS window.getComputedStyle(document.getElementById('test5')).getPropertyValue('text-decoration-thickness') is "auto"
+PASS window.getComputedStyle(document.getElementById('test6')).getPropertyValue('text-decoration-thickness') is "37px"
+PASS window.getComputedStyle(document.getElementById('test7')).getPropertyValue('text-decoration-thickness') is "200px"
+PASS window.getComputedStyle(document.getElementById('test8')).getPropertyValue('text-decoration-thickness') is "40px"
+PASS document.getElementById('target').sheet.cssRules[0].style.textDecorationThickness is ""
+PASS document.getElementById('target').sheet.cssRules[1].style.textDecorationThickness is "auto"
+PASS document.getElementById('target').sheet.cssRules[2].style.textDecorationThickness is "from-font"
+PASS document.getElementById('target').sheet.cssRules[3].style.textDecorationThickness is ""
+PASS document.getElementById('target').sheet.cssRules[4].style.textDecorationThickness is ""
+PASS document.getElementById('target').sheet.cssRules[5].style.textDecorationThickness is "37px"
+PASS document.getElementById('target').sheet.cssRules[6].style.textDecorationThickness is "2em"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html b/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html
new file mode 100644 (file)
index 0000000..1d9af36
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+<style id="target">
+#dummy {
+}
+#dummy {
+    text-decoration-thickness: auto;
+}
+#dummy {
+    text-decoration-thickness: from-font;
+}
+#dummy {
+    text-decoration-thickness: auto 37px;
+}
+#dummy {
+    text-decoration-thickness: garbage;
+}
+#dummy {
+    text-decoration-thickness: 37px;
+}
+#dummy {
+    text-decoration-thickness: 2em;
+}
+</style>
+</head>
+<body>
+<div id="test1"></div>
+<div id="test2" style="text-decoration-thickness: auto;"></div>
+<div id="test3" style="text-decoration-thickness: from-font;"></div>
+<div id="test4" style="text-decoration-thickness: auto 37px;"></div>
+<div id="test5" style="text-decoration-thickness: garbage;"></div>
+<div id="test6" style="text-decoration-thickness: 37px;"></div>
+<div id="test7" style="font-size: 100px; text-decoration-thickness: 2em;"></div>
+<div style="font-size: 20px; text-decoration-thickness: 2em;"><div id="test8" style="font-size: 100px;"></div></div>
+<script>
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test1')).getPropertyValue('text-decoration-thickness')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test2')).getPropertyValue('text-decoration-thickness')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test3')).getPropertyValue('text-decoration-thickness')", "from-font");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test4')).getPropertyValue('text-decoration-thickness')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test5')).getPropertyValue('text-decoration-thickness')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test6')).getPropertyValue('text-decoration-thickness')", "37px");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test7')).getPropertyValue('text-decoration-thickness')", "200px");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test8')).getPropertyValue('text-decoration-thickness')", "40px");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[0].style.textDecorationThickness", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[1].style.textDecorationThickness", "auto");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[2].style.textDecorationThickness", "from-font");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[3].style.textDecorationThickness", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[4].style.textDecorationThickness", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[5].style.textDecorationThickness", "37px");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[6].style.textDecorationThickness", "2em");
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse-expected.txt b/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse-expected.txt
new file mode 100644 (file)
index 0000000..7840c7b
--- /dev/null
@@ -0,0 +1,17 @@
+PASS window.getComputedStyle(document.getElementById('test1')).getPropertyValue('text-underline-offset') is "auto"
+PASS window.getComputedStyle(document.getElementById('test2')).getPropertyValue('text-underline-offset') is "auto"
+PASS window.getComputedStyle(document.getElementById('test3')).getPropertyValue('text-underline-offset') is "auto"
+PASS window.getComputedStyle(document.getElementById('test4')).getPropertyValue('text-underline-offset') is "auto"
+PASS window.getComputedStyle(document.getElementById('test5')).getPropertyValue('text-underline-offset') is "37px"
+PASS window.getComputedStyle(document.getElementById('test6')).getPropertyValue('text-underline-offset') is "200px"
+PASS window.getComputedStyle(document.getElementById('test7')).getPropertyValue('text-underline-offset') is "40px"
+PASS document.getElementById('target').sheet.cssRules[0].style.textUnderlineOffset is ""
+PASS document.getElementById('target').sheet.cssRules[1].style.textUnderlineOffset is "auto"
+PASS document.getElementById('target').sheet.cssRules[2].style.textUnderlineOffset is ""
+PASS document.getElementById('target').sheet.cssRules[3].style.textUnderlineOffset is ""
+PASS document.getElementById('target').sheet.cssRules[4].style.textUnderlineOffset is "37px"
+PASS document.getElementById('target').sheet.cssRules[5].style.textUnderlineOffset is "2em"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse.html b/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-offset-parse.html
new file mode 100644 (file)
index 0000000..ab01e1b
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+<style id="target">
+#dummy {
+}
+#dummy {
+    text-underline-offset: auto;
+}
+#dummy {
+    text-underline-offset: auto 37px;
+}
+#dummy {
+    text-underline-offset: garbage;
+}
+#dummy {
+    text-underline-offset: 37px;
+}
+#dummy {
+    text-underline-offset: 2em;
+}
+</style>
+</head>
+<body>
+<div id="test1"></div>
+<div id="test2" style="text-underline-offset: auto;"></div>
+<div id="test3" style="text-underline-offset: auto 37px;"></div>
+<div id="test4" style="text-underline-offset: garbage;"></div>
+<div id="test5" style="text-underline-offset: 37px;"></div>
+<div id="test6" style="font-size: 100px; text-underline-offset: 2em;"></div>
+<div style="font-size: 20px; text-underline-offset: 2em;"><div id="test7" style="font-size: 100px;"></div></div>
+<script>
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test1')).getPropertyValue('text-underline-offset')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test2')).getPropertyValue('text-underline-offset')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test3')).getPropertyValue('text-underline-offset')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test4')).getPropertyValue('text-underline-offset')", "auto");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test5')).getPropertyValue('text-underline-offset')", "37px");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test6')).getPropertyValue('text-underline-offset')", "200px");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('test7')).getPropertyValue('text-underline-offset')", "40px");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[0].style.textUnderlineOffset", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[1].style.textUnderlineOffset", "auto");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[2].style.textUnderlineOffset", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[3].style.textUnderlineOffset", "");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[4].style.textUnderlineOffset", "37px");
+shouldBeEqualToString("document.getElementById('target').sheet.cssRules[5].style.textUnderlineOffset", "2em");
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
index 7ee1ed9..1b694da 100644 (file)
@@ -1,5 +1,92 @@
 2018-11-05  Myles C. Maxfield  <mmaxfield@apple.com>
 
+        Parsing support for text-underline-offset and text-decoration-thickness
+        https://bugs.webkit.org/show_bug.cgi?id=191242
+
+        Reviewed by Simon Fraser.
+
+        Before we can implement the properties properly, we have to parse them.
+
+        https://github.com/w3c/csswg-drafts/issues/3118#issuecomment-432297480 describes the grammar:
+        text-underline-position: auto | [ [ under | from-font] || [ left | right ] ]
+        text-underline-offset: auto | <length>
+        text-decoration-thickness: auto | from-font | <length>
+
+        This patch also takes the opportunity to update the grammar of text-underline-position to match the spec,
+        and to add an alias to the unprefixed version.
+
+        We still don't support the left and right values on text-underline-position. We should add those eventually.
+
+        Tests: fast/css3-text/css3-text-decoration/text-decoration-thickness-parse.html
+               fast/css3-text/css3-text-decoration/text-underline-offset-parse.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::textUnderlineOffsetToCSSValue):
+        (WebCore::textDecorationThicknessToCSSValue):
+        (WebCore::ComputedStyleExtractor::valueForPropertyinStyle):
+        * css/CSSPrimitiveValueMappings.h:
+        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
+        (WebCore::CSSPrimitiveValue::operator TextUnderlinePosition const):
+        (WebCore::CSSPrimitiveValue::operator OptionSet<TextUnderlinePosition> const): Deleted.
+        * css/CSSProperties.json:
+        * css/CSSValueKeywords.in:
+        * css/StyleBuilderConverter.h:
+        (WebCore::StyleBuilderConverter::convertTextUnderlinePosition):
+        (WebCore::StyleBuilderConverter::convertTextUnderlineOffset):
+        (WebCore::StyleBuilderConverter::convertTextDecorationThickness):
+        * css/StyleResolver.cpp:
+        (WebCore::shouldApplyPropertyInParseOrder):
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::consumeTextUnderlineOffset):
+        (WebCore::consumeTextDecorationThickness):
+        (WebCore::CSSPropertyParser::parseSingleValue):
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::textUnderlinePosition const):
+        (WebCore::RenderStyle::textUnderlineOffset const):
+        (WebCore::RenderStyle::textDecorationThickness const):
+        (WebCore::RenderStyle::setTextUnderlinePosition):
+        (WebCore::RenderStyle::setTextUnderlineOffset):
+        (WebCore::RenderStyle::setTextDecorationThickness):
+        (WebCore::RenderStyle::initialTextUnderlinePosition):
+        (WebCore::RenderStyle::initialTextUnderlineOffset):
+        (WebCore::RenderStyle::initialTextDecorationThickness):
+        * rendering/style/RenderStyleConstants.h:
+        * rendering/style/StyleRareInheritedData.cpp:
+        (WebCore::StyleRareInheritedData::StyleRareInheritedData):
+        (WebCore::StyleRareInheritedData::operator== const):
+        * rendering/style/StyleRareInheritedData.h:
+        * rendering/style/TextDecorationThickness.h: Added.
+        (WebCore::TextDecorationThickness::createWithAuto):
+        (WebCore::TextDecorationThickness::createFromFont):
+        (WebCore::TextDecorationThickness::createWithLength):
+        (WebCore::TextDecorationThickness::isAuto const):
+        (WebCore::TextDecorationThickness::isFromFont const):
+        (WebCore::TextDecorationThickness::isLength const):
+        (WebCore::TextDecorationThickness::setLengthValue):
+        (WebCore::TextDecorationThickness::lengthValue const):
+        (WebCore::TextDecorationThickness::operator== const):
+        (WebCore::TextDecorationThickness::operator!= const):
+        (WebCore::TextDecorationThickness::TextDecorationThickness):
+        (WebCore::operator<<):
+        * rendering/style/TextUnderlineOffset.h: Added.
+        (WebCore::TextUnderlineOffset::createWithAuto):
+        (WebCore::TextUnderlineOffset::createWithLength):
+        (WebCore::TextUnderlineOffset::isAuto const):
+        (WebCore::TextUnderlineOffset::isLength const):
+        (WebCore::TextUnderlineOffset::setLengthValue):
+        (WebCore::TextUnderlineOffset::lengthValue const):
+        (WebCore::TextUnderlineOffset::lengthOr const):
+        (WebCore::TextUnderlineOffset::operator== const):
+        (WebCore::TextUnderlineOffset::operator!= const):
+        (WebCore::TextUnderlineOffset::TextUnderlineOffset):
+        (WebCore::operator<<):
+        * style/InlineTextBoxStyle.cpp:
+        (WebCore::computeUnderlineOffset):
+        * style/InlineTextBoxStyle.h:
+
+2018-11-05  Myles C. Maxfield  <mmaxfield@apple.com>
+
         Spelling dots are drawn in the wrong place
         https://bugs.webkit.org/show_bug.cgi?id=190764
 
index 86146c9..6905739 100644 (file)
                1C24EEA51C729CE40080F8FC /* FontFaceSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C24EEA31C729CE40080F8FC /* FontFaceSet.h */; };
                1C24EEA91C72A7B40080F8FC /* JSFontFaceSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C24EEA71C72A7B40080F8FC /* JSFontFaceSet.h */; };
                1C6626111C6E7CA600AB527C /* FontFace.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C66260F1C6E7CA600AB527C /* FontFace.h */; };
+               1C73A7132185757E004CCEA5 /* TextUnderlineOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CB6B4FB217B83940093B9CD /* TextUnderlineOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1C73A71521857587004CCEA5 /* TextDecorationThickness.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CB6B4F8217B83930093B9CD /* TextDecorationThickness.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1C81B95A0E97330800266E07 /* InspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9560E97330800266E07 /* InspectorController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1C81B95C0E97330800266E07 /* InspectorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9580E97330800266E07 /* InspectorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1CA19E160DC255CA0065A994 /* EventLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CA19E150DC255CA0065A994 /* EventLoop.h */; };
                1CAF347E0A6C405200ABE06E /* WebScriptObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObject.h; sourceTree = "<group>"; };
                1CAF347F0A6C405200ABE06E /* WebScriptObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptObject.mm; sourceTree = "<group>"; };
                1CAF34800A6C405200ABE06E /* WebScriptObjectPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObjectPrivate.h; sourceTree = "<group>"; };
+               1CB6B4F8217B83930093B9CD /* TextDecorationThickness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextDecorationThickness.h; sourceTree = "<group>"; };
+               1CB6B4FB217B83940093B9CD /* TextUnderlineOffset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextUnderlineOffset.h; sourceTree = "<group>"; };
                1CCDF5BB1990332400BCEBAD /* SVGToOTFFontConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGToOTFFontConversion.cpp; sourceTree = "<group>"; };
                1CCDF5BC1990332400BCEBAD /* SVGToOTFFontConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGToOTFFontConversion.h; sourceTree = "<group>"; };
                1CDD45E40BA9C84600F90147 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
                                313591011E7DDC6000F30630 /* RTCIceGatheringState.h */,
                                313591021E7DDC6000F30630 /* RTCIceTransportPolicy.h */,
                                313591031E7DDC6000F30630 /* RTCIceTransportState.h */,
-                               412BA5FE218C651800365474 /* RTCPMuxPolicy.h */,
                                07221BAA17CF0AD400848E51 /* RTCPeerConnectionHandlerClient.h */,
                                41A48A9D1E8312EB00D2AC2D /* RTCPeerConnectionState.h */,
+                               412BA5FE218C651800365474 /* RTCPMuxPolicy.h */,
                                31EB54DD1E7DC74400C1623B /* RTCRtpTransceiverDirection.h */,
                                313591041E7DDC6000F30630 /* RTCSdpType.h */,
                                07221BAB17CF0AD400848E51 /* RTCSessionDescriptionDescriptor.cpp */,
                                BC2274750E8366E200E7F975 /* SVGRenderStyle.h */,
                                BC2274760E8366E200E7F975 /* SVGRenderStyleDefs.cpp */,
                                BC2274770E8366E200E7F975 /* SVGRenderStyleDefs.h */,
+                               1CB6B4F8217B83930093B9CD /* TextDecorationThickness.h */,
                                448B1B780F3A2F9B0047A9E2 /* TextSizeAdjustment.h */,
+                               1CB6B4FB217B83940093B9CD /* TextUnderlineOffset.h */,
                                0F15ED591B7EC7C500EDDFEB /* WillChangeData.cpp */,
                                0F15ED5A1B7EC7C500EDDFEB /* WillChangeData.h */,
                        );
                                9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */,
                                142B97CA13138943008BEF4B /* TextControlInnerElements.h in Headers */,
                                582DE3251C30C85400BE02A8 /* TextDecorationPainter.h in Headers */,
+                               1C73A71521857587004CCEA5 /* TextDecorationThickness.h in Headers */,
                                97BC84B412371180000C6161 /* TextDocument.h in Headers */,
                                97BC84841236FD93000C6161 /* TextDocumentParser.h in Headers */,
                                B2C3DA470D006C1D00EF6F26 /* TextEncoding.h in Headers */,
                                076970871463AD8700F502CF /* TextTrackList.h in Headers */,
                                B1AD4E7413A12A4600846B27 /* TextTrackLoader.h in Headers */,
                                CD8B5A49180E138B008B8E65 /* TextTrackMediaSource.h in Headers */,
+                               1C73A7132185757E004CCEA5 /* TextUnderlineOffset.h in Headers */,
                                29FAF4B6195AB08900A522DC /* TextUndoInsertionMarkupMac.h in Headers */,
                                498770F11242C535002226BA /* Texture.h in Headers */,
                                CD9D82761C7AE535006FF066 /* TextureCacheCV.h in Headers */,
index 0749d9a..2ef6629 100644 (file)
@@ -215,7 +215,7 @@ static const CSSPropertyID computedProperties[] = {
     CSSPropertyWebkitTextDecorationStyle,
     CSSPropertyWebkitTextDecorationColor,
     CSSPropertyWebkitTextDecorationSkip,
-    CSSPropertyWebkitTextUnderlinePosition,
+    CSSPropertyTextUnderlinePosition,
     CSSPropertyTextIndent,
     CSSPropertyTextRendering,
     CSSPropertyTextShadow,
@@ -1802,6 +1802,24 @@ static Ref<CSSValue> renderTextDecorationSkipFlagsToCSSValue(OptionSet<TextDecor
     return CSSValuePool::singleton().createExplicitInitialValue();
 }
 
+static Ref<CSSValue> textUnderlineOffsetToCSSValue(const TextUnderlineOffset& textUnderlineOffset)
+{
+    if (textUnderlineOffset.isAuto())
+        return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
+    ASSERT(textUnderlineOffset.isLength());
+    return CSSValuePool::singleton().createValue(textUnderlineOffset.lengthValue(), CSSPrimitiveValue::CSS_PX);
+}
+
+static Ref<CSSValue> textDecorationThicknessToCSSValue(const TextDecorationThickness& textDecorationThickness)
+{
+    if (textDecorationThickness.isAuto())
+        return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
+    if (textDecorationThickness.isFromFont())
+        return CSSValuePool::singleton().createIdentifierValue(CSSValueFromFont);
+    ASSERT(textDecorationThickness.isLength());
+    return CSSValuePool::singleton().createValue(textDecorationThickness.lengthValue(), CSSPrimitiveValue::CSS_PX);
+}
+
 static Ref<CSSValue> renderEmphasisPositionFlagsToCSSValue(OptionSet<TextEmphasisPosition> textEmphasisPosition)
 {
     ASSERT(!((textEmphasisPosition & TextEmphasisPosition::Over) && (textEmphasisPosition & TextEmphasisPosition::Under)));
@@ -3331,8 +3349,12 @@ RefPtr<CSSValue> ComputedStyleExtractor::valueForPropertyinStyle(const RenderSty
             return currentColorOrValidColor(&style, style.textDecorationColor());
         case CSSPropertyWebkitTextDecorationSkip:
             return renderTextDecorationSkipFlagsToCSSValue(style.textDecorationSkip());
-        case CSSPropertyWebkitTextUnderlinePosition:
+        case CSSPropertyTextUnderlinePosition:
             return cssValuePool.createValue(style.textUnderlinePosition());
+        case CSSPropertyTextUnderlineOffset:
+            return textUnderlineOffsetToCSSValue(style.textUnderlineOffset());
+        case CSSPropertyTextDecorationThickness:
+            return textDecorationThicknessToCSSValue(style.textDecorationThickness());
         case CSSPropertyWebkitTextDecorationsInEffect:
             return renderTextDecorationFlagsToCSSValue(style.textDecorationsInEffect());
         case CSSPropertyWebkitTextFillColor:
index 7875fda..c95ff65 100644 (file)
@@ -2636,42 +2636,41 @@ template<> inline CSSPrimitiveValue::operator TextDecorationStyle() const
     return TextDecorationStyle::Solid;
 }
 
-template<> inline CSSPrimitiveValue::CSSPrimitiveValue(OptionSet<TextUnderlinePosition> e)
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextUnderlinePosition position)
     : CSSValue(PrimitiveClass)
 {
     m_primitiveUnitType = CSS_VALUE_ID;
-    switch (static_cast<TextUnderlinePosition>(e.toRaw())) {
+    switch (position) {
     case TextUnderlinePosition::Auto:
         m_value.valueID = CSSValueAuto;
         break;
-    case TextUnderlinePosition::Alphabetic:
-        m_value.valueID = CSSValueAlphabetic;
-        break;
     case TextUnderlinePosition::Under:
         m_value.valueID = CSSValueUnder;
         break;
+    case TextUnderlinePosition::FromFont:
+        m_value.valueID = CSSValueFromFont;
+        break;
     }
 
     // FIXME: Implement support for 'under left' and 'under right' values.
 }
 
-template<> inline CSSPrimitiveValue::operator OptionSet<TextUnderlinePosition>() const
+template<> inline CSSPrimitiveValue::operator TextUnderlinePosition() const
 {
     ASSERT(isValueID());
 
     switch (m_value.valueID) {
     case CSSValueAuto:
         return TextUnderlinePosition::Auto;
-    case CSSValueAlphabetic:
-        return TextUnderlinePosition::Alphabetic;
     case CSSValueUnder:
         return TextUnderlinePosition::Under;
+    case CSSValueFromFont:
+        return TextUnderlinePosition::FromFont;
     default:
         break;
     }
 
     // FIXME: Implement support for 'under left' and 'under right' values.
-
     ASSERT_NOT_REACHED();
     return TextUnderlinePosition::Auto;
 }
index bc6b578..28d8482 100644 (file)
                 "url": "https://www.w3.org/TR/css-text-decor-3/#text-decoration-skip"
             }
         },
-        "-webkit-text-underline-position": {
+        "text-underline-position": {
+            "codegen-properties": {
+                "aliases": [
+                    "-webkit-text-underline-position"
+                ]
+            },
+            "inherited": true,
+            "status": {
+                "status": "experimental"
+            },
+            "specification": {
+                "category": "css-text-decor",
+                "url": "https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property"
+            }
+        },
+        "text-underline-offset": {
+            "inherited": true,
+            "codegen-properties": {
+                "converter": "TextUnderlineOffset"
+            },
+            "status": {
+                "status": "experimental"
+            },
+            "specification": {
+                "category": "css-text-decor",
+                "url": "https://www.w3.org/TR/css-text-decor-4/#underline-offset"
+            }
+        },
+        "text-decoration-thickness": {
             "inherited": true,
             "codegen-properties": {
-                "converter": "TextUnderlinePosition"
+                "converter": "TextDecorationThickness"
             },
             "status": {
                 "status": "experimental"
             },
             "specification": {
                 "category": "css-text-decor",
-                "url": "https://www.w3.org/TR/css-text-decor-3/#text-underline-position"
+                "url": "https://www.w3.org/TR/css-text-decor-4/#text-decoration-thickness"
             }
         },
         "-webkit-text-decorations-in-effect": {
index 4632363..90f912a 100644 (file)
@@ -1403,3 +1403,6 @@ standalone
 minimal-ui
 browser
 #endif
+
+// text-decoration-thickness, text-underline-offset
+from-font
index 63eb131..0e838bb 100644 (file)
@@ -87,7 +87,9 @@ public:
     static int convertMarqueeRepetition(StyleResolver&, const CSSValue&);
     static int convertMarqueeSpeed(StyleResolver&, const CSSValue&);
     static Ref<QuotesData> convertQuotes(StyleResolver&, const CSSValue&);
-    static OptionSet<TextUnderlinePosition> convertTextUnderlinePosition(StyleResolver&, const CSSValue&);
+    static TextUnderlinePosition convertTextUnderlinePosition(StyleResolver&, const CSSValue&);
+    static TextUnderlineOffset convertTextUnderlineOffset(StyleResolver&, const CSSValue&);
+    static TextDecorationThickness convertTextDecorationThickness(StyleResolver&, const CSSValue&);
     static RefPtr<StyleReflection> convertReflection(StyleResolver&, const CSSValue&);
     static IntSize convertInitialLetter(StyleResolver&, const CSSValue&);
     static float convertTextStrokeWidth(StyleResolver&, const CSSValue&);
@@ -637,16 +639,40 @@ inline Ref<QuotesData> StyleBuilderConverter::convertQuotes(StyleResolver&, cons
     return QuotesData::create(quotes);
 }
 
-inline OptionSet<TextUnderlinePosition> StyleBuilderConverter::convertTextUnderlinePosition(StyleResolver&, const CSSValue& value)
+inline TextUnderlinePosition StyleBuilderConverter::convertTextUnderlinePosition(StyleResolver&, const CSSValue& value)
 {
-    // This is true if value is 'auto' or 'alphabetic'.
-    if (is<CSSPrimitiveValue>(value))
-        return downcast<CSSPrimitiveValue>(value);
+    ASSERT(is<CSSPrimitiveValue>(value));
+    return downcast<CSSPrimitiveValue>(value);
+}
 
-    OptionSet<TextUnderlinePosition> combinedPosition;
-    for (auto& currentValue : downcast<CSSValueList>(value))
-        combinedPosition.add(downcast<CSSPrimitiveValue>(currentValue.get()));
-    return combinedPosition;
+inline TextUnderlineOffset StyleBuilderConverter::convertTextUnderlineOffset(StyleResolver& styleResolver, const CSSValue& value)
+{
+    ASSERT(is<CSSPrimitiveValue>(value));
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    switch (primitiveValue.valueID()) {
+    case CSSValueAuto:
+        return TextUnderlineOffset::createWithAuto();
+    default:
+        ASSERT(primitiveValue.isLength());
+        auto computedLength = convertComputedLength<float>(styleResolver, primitiveValue);
+        return TextUnderlineOffset::createWithLength(computedLength);
+    }
+}
+
+inline TextDecorationThickness StyleBuilderConverter::convertTextDecorationThickness(StyleResolver& styleResolver, const CSSValue& value)
+{
+    ASSERT(is<CSSPrimitiveValue>(value));
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    switch (primitiveValue.valueID()) {
+    case CSSValueAuto:
+        return TextDecorationThickness::createWithAuto();
+    case CSSValueFromFont:
+        return TextDecorationThickness::createFromFont();
+    default:
+        ASSERT(primitiveValue.isLength());
+        auto computedLength = convertComputedLength<float>(styleResolver, primitiveValue);
+        return TextDecorationThickness::createWithLength(computedLength);
+    }
 }
 
 inline RefPtr<StyleReflection> StyleBuilderConverter::convertReflection(StyleResolver& styleResolver, const CSSValue& value)
index fd4cfee..57671c9 100644 (file)
@@ -1175,7 +1175,9 @@ static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
     case CSSPropertyWebkitTextDecorationStyle:
     case CSSPropertyWebkitTextDecorationColor:
     case CSSPropertyWebkitTextDecorationSkip:
-    case CSSPropertyWebkitTextUnderlinePosition:
+    case CSSPropertyTextUnderlinePosition:
+    case CSSPropertyTextUnderlineOffset:
+    case CSSPropertyTextDecorationThickness:
     case CSSPropertyTextDecoration:
         return true;
     default:
index c3a23b5..d3a0477 100644 (file)
@@ -2337,6 +2337,20 @@ static RefPtr<CSSValue> consumeBorderRadiusCorner(CSSParserTokenRange& range, CS
     return createPrimitiveValuePair(parsedValue1.releaseNonNull(), parsedValue2.releaseNonNull(), Pair::IdenticalValueEncoding::Coalesce);
 }
 
+static RefPtr<CSSValue> consumeTextUnderlineOffset(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    if (auto value = consumeIdent<CSSValueAuto>(range))
+        return value;
+    return consumeLength(range, cssParserMode, ValueRangeAll);
+}
+
+static RefPtr<CSSValue> consumeTextDecorationThickness(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    if (auto value = consumeIdent<CSSValueAuto, CSSValueFromFont>(range))
+        return value;
+    return consumeLength(range, cssParserMode, ValueRangeAll);
+}
+
 static RefPtr<CSSPrimitiveValue> consumeVerticalAlign(CSSParserTokenRange& range, CSSParserMode cssParserMode)
 {
     RefPtr<CSSPrimitiveValue> parsedValue = consumeIdentRange(range, CSSValueBaseline, CSSValueWebkitBaselineMiddle);
@@ -4165,9 +4179,13 @@ RefPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID property, CSS
         return consumeInteger(m_range, 0);
     case CSSPropertyOrder:
         return consumeInteger(m_range);
-    case CSSPropertyWebkitTextUnderlinePosition:
-        // auto | alphabetic | [ under || [ left | right ] ], but we only support auto | alphabetic | under for now
-        return consumeIdent<CSSValueAuto, CSSValueUnder, CSSValueAlphabetic>(m_range);
+    case CSSPropertyTextUnderlinePosition:
+        // auto | [ [ under | from-font ] || [ left | right ] ], but we only support auto | under | from-font for now
+        return consumeIdent<CSSValueAuto, CSSValueUnder, CSSValueFromFont>(m_range);
+    case CSSPropertyTextUnderlineOffset:
+        return consumeTextUnderlineOffset(m_range, m_context.mode);
+    case CSSPropertyTextDecorationThickness:
+        return consumeTextDecorationThickness(m_range, m_context.mode);
     case CSSPropertyVerticalAlign:
         return consumeVerticalAlign(m_range, m_context.mode);
     case CSSPropertyShapeOutside:
index 708e6bf..981b8ee 100644 (file)
@@ -374,7 +374,9 @@ public:
     OptionSet<TextDecoration> textDecoration() const { return OptionSet<TextDecoration>::fromRaw(m_visualData->textDecoration); }
     TextDecorationStyle textDecorationStyle() const { return static_cast<TextDecorationStyle>(m_rareNonInheritedData->textDecorationStyle); }
     OptionSet<TextDecorationSkip> textDecorationSkip() const { return OptionSet<TextDecorationSkip>::fromRaw(m_rareInheritedData->textDecorationSkip); }
-    OptionSet<TextUnderlinePosition> textUnderlinePosition() const { return OptionSet<TextUnderlinePosition>::fromRaw(m_rareInheritedData->textUnderlinePosition); }
+    TextUnderlinePosition textUnderlinePosition() const { return static_cast<TextUnderlinePosition>(m_rareInheritedData->textUnderlinePosition); }
+    TextUnderlineOffset textUnderlineOffset() const { return m_rareInheritedData->textUnderlineOffset; }
+    TextDecorationThickness textDecorationThickness() const { return m_rareInheritedData->textDecorationThickness; }
 
 #if ENABLE(CSS3_TEXT)
     TextIndentLine textIndentLine() const { return static_cast<TextIndentLine>(m_rareInheritedData->textIndentLine); }
@@ -921,7 +923,9 @@ public:
     void setTextDecoration(OptionSet<TextDecoration> v) { SET_VAR(m_visualData, textDecoration, v.toRaw()); }
     void setTextDecorationStyle(TextDecorationStyle v) { SET_VAR(m_rareNonInheritedData, textDecorationStyle, static_cast<unsigned>(v)); }
     void setTextDecorationSkip(OptionSet<TextDecorationSkip> skip) { SET_VAR(m_rareInheritedData, textDecorationSkip, skip.toRaw()); }
-    void setTextUnderlinePosition(OptionSet<TextUnderlinePosition> v) { SET_VAR(m_rareInheritedData, textUnderlinePosition, v.toRaw()); }
+    void setTextUnderlinePosition(TextUnderlinePosition position) { SET_VAR(m_rareInheritedData, textUnderlinePosition, static_cast<unsigned>(position)); }
+    void setTextUnderlineOffset(TextUnderlineOffset textUnderlineOffset) { SET_VAR(m_rareInheritedData, textUnderlineOffset, textUnderlineOffset); }
+    void setTextDecorationThickness(TextDecorationThickness textDecorationThickness) { SET_VAR(m_rareInheritedData, textDecorationThickness, textDecorationThickness); }
     void setDirection(TextDirection v) { m_inheritedFlags.direction = static_cast<unsigned>(v); }
     void setHasExplicitlySetDirection(bool v) { m_nonInheritedFlags.hasExplicitlySetDirection = v; }
     void setLineHeight(Length&&);
@@ -1482,7 +1486,9 @@ public:
     static OptionSet<TextDecoration> initialTextDecoration() { return OptionSet<TextDecoration> { }; }
     static TextDecorationStyle initialTextDecorationStyle() { return TextDecorationStyle::Solid; }
     static OptionSet<TextDecorationSkip> initialTextDecorationSkip() { return TextDecorationSkip::Auto; }
-    static OptionSet<TextUnderlinePosition> initialTextUnderlinePosition() { return TextUnderlinePosition::Auto; }
+    static TextUnderlinePosition initialTextUnderlinePosition() { return TextUnderlinePosition::Auto; }
+    static TextUnderlineOffset initialTextUnderlineOffset() { return TextUnderlineOffset::createWithAuto(); }
+    static TextDecorationThickness initialTextDecorationThickness() { return TextDecorationThickness::createWithAuto(); }
     static float initialZoom() { return 1.0f; }
     static TextZoom initialTextZoom() { return TextZoom::Normal; }
     static float initialOutlineOffset() { return 0; }
index 3edee09..176eb21 100644 (file)
@@ -731,12 +731,11 @@ enum class TextDecorationSkip : uint8_t {
     Auto      = 1 << 2
 };
 
-// FIXME: There is no reason for the values in the enum to be powers of two.
 enum class TextUnderlinePosition : uint8_t {
     // FIXME: Implement support for 'under left' and 'under right' values.
-    Auto       = 1 << 0,
-    Alphabetic = 1 << 1,
-    Under      = 1 << 2
+    Auto,
+    Under,
+    FromFont
 };
 
 enum class TextZoom : uint8_t {
index 2aada1c..5fb79b3 100644 (file)
@@ -45,6 +45,8 @@ struct GreaterThanOrSameSizeAsStyleRareInheritedData : public RefCounted<Greater
     void* refPtrs[3];
     Length lengths[2];
     float secondFloat;
+    TextUnderlineOffset offset;
+    TextDecorationThickness thickness;
     unsigned bitfields[4];
     short pagedMediaShorts[2];
     unsigned unsigneds[1];
@@ -75,6 +77,8 @@ StyleRareInheritedData::StyleRareInheritedData()
     , textStrokeWidth(RenderStyle::initialTextStrokeWidth())
     , indent(RenderStyle::initialTextIndent())
     , effectiveZoom(RenderStyle::initialZoom())
+    , textUnderlineOffset(RenderStyle::initialTextUnderlineOffset())
+    , textDecorationThickness(RenderStyle::initialTextDecorationThickness())
     , customProperties(StyleCustomPropertyData::create())
     , widows(RenderStyle::initialWidows())
     , orphans(RenderStyle::initialOrphans())
@@ -116,7 +120,7 @@ StyleRareInheritedData::StyleRareInheritedData()
     , textJustify(RenderStyle::initialTextJustify())
 #endif
     , textDecorationSkip(RenderStyle::initialTextDecorationSkip().toRaw())
-    , textUnderlinePosition(RenderStyle::initialTextUnderlinePosition().toRaw())
+    , textUnderlinePosition(static_cast<unsigned>(RenderStyle::initialTextUnderlinePosition()))
     , rubyPosition(static_cast<unsigned>(RenderStyle::initialRubyPosition()))
     , textZoom(static_cast<unsigned>(RenderStyle::initialTextZoom()))
 #if PLATFORM(IOS_FAMILY)
@@ -168,6 +172,8 @@ inline StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedDa
     , cursorData(o.cursorData)
     , indent(o.indent)
     , effectiveZoom(o.effectiveZoom)
+    , textUnderlineOffset(o.textUnderlineOffset)
+    , textDecorationThickness(o.textDecorationThickness)
     , customProperties(o.customProperties)
     , widows(o.widows)
     , orphans(o.orphans)
@@ -273,6 +279,8 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
         && arePointingToEqualData(cursorData, o.cursorData)
         && indent == o.indent
         && effectiveZoom == o.effectiveZoom
+        && textUnderlineOffset == o.textUnderlineOffset
+        && textDecorationThickness == o.textDecorationThickness
         && widows == o.widows
         && orphans == o.orphans
         && hasAutoWidows == o.hasAutoWidows
index b83a8c0..a3ad175 100644 (file)
@@ -28,6 +28,8 @@
 #include "DataRef.h"
 #include "Length.h"
 #include "StyleCustomPropertyData.h"
+#include "TextDecorationThickness.h"
+#include "TextUnderlineOffset.h"
 #include <wtf/RefCounted.h>
 #include <wtf/text/AtomicString.h>
 
@@ -79,6 +81,9 @@ public:
     RefPtr<CursorList> cursorData;
     Length indent;
     float effectiveZoom;
+
+    TextUnderlineOffset textUnderlineOffset;
+    TextDecorationThickness textDecorationThickness;
     
     Length wordSpacing;
 
@@ -128,7 +133,7 @@ public:
     unsigned textJustify : 2; // TextJustify
 #endif
     unsigned textDecorationSkip : 5; // TextDecorationSkip
-    unsigned textUnderlinePosition : 3; // TextUnderlinePosition
+    unsigned textUnderlinePosition : 2; // TextUnderlinePosition
     unsigned rubyPosition : 2; // RubyPosition
     unsigned textZoom: 1; // TextZoom
 
diff --git a/Source/WebCore/rendering/style/TextDecorationThickness.h b/Source/WebCore/rendering/style/TextDecorationThickness.h
new file mode 100644 (file)
index 0000000..be9d28f
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "FontMetrics.h"
+#include "Length.h"
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+class TextDecorationThickness {
+public:
+    static TextDecorationThickness createWithAuto()
+    {
+        return TextDecorationThickness(Type::Auto);
+    }
+    static TextDecorationThickness createFromFont()
+    {
+        return TextDecorationThickness(Type::FromFont);
+    }
+    static TextDecorationThickness createWithLength(float length)
+    {
+        TextDecorationThickness result(Type::Length);
+        result.setLengthValue(length);
+        return result;
+    }
+
+    bool isAuto() const
+    {
+        return m_type == Type::Auto;
+    }
+
+    bool isFromFont() const
+    {
+        return m_type == Type::FromFont;
+    }
+
+    bool isLength() const
+    {
+        return m_type == Type::Length;
+    }
+
+    void setLengthValue(float length)
+    {
+        ASSERT(isLength());
+        m_length = length;
+    }
+
+    float lengthValue() const
+    {
+        ASSERT(isLength());
+        return m_length;
+    }
+
+    bool operator==(const TextDecorationThickness& other) const
+    {
+        switch (m_type) {
+        case Type::Auto:
+        case Type::FromFont:
+            return m_type == other.m_type;
+        case Type::Length:
+            return m_type == other.m_type && m_length == other.m_length;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    bool operator!=(const TextDecorationThickness& other) const
+    {
+        return !(*this == other);
+    }
+
+private:
+    enum class Type : uint8_t {
+        Auto,
+        FromFont,
+        Length
+    };
+
+    TextDecorationThickness(Type type)
+        : m_type { type }
+    {
+    }
+
+    Type m_type;
+    float m_length;
+};
+
+inline TextStream& operator<<(TextStream& ts, const TextDecorationThickness& thickness)
+{
+    if (thickness.isAuto())
+        ts << "auto";
+    else if (thickness.isFromFont())
+        ts << "from-font";
+    else
+        ts << TextStream::FormatNumberRespectingIntegers(thickness.lengthValue());
+    return ts;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/style/TextUnderlineOffset.h b/Source/WebCore/rendering/style/TextUnderlineOffset.h
new file mode 100644 (file)
index 0000000..961e7b2
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Length.h"
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+class TextUnderlineOffset {
+public:
+    static TextUnderlineOffset createWithAuto()
+    {
+        return TextUnderlineOffset(Type::Auto);
+    }
+
+    static TextUnderlineOffset createWithLength(float length)
+    {
+        TextUnderlineOffset result(Type::Length);
+        result.setLengthValue(length);
+        return result;
+    }
+
+    bool isAuto() const
+    {
+        return !isLength();
+    }
+
+    bool isLength() const
+    {
+        return static_cast<bool>(m_length);
+    }
+
+    void setLengthValue(float length)
+    {
+        ASSERT(isLength());
+        m_length = length;
+    }
+
+    float lengthValue() const
+    {
+        ASSERT(isLength());
+        return *m_length;
+    }
+
+    float lengthOr(float defaultValue) const
+    {
+        return m_length.value_or(defaultValue);
+    }
+
+    bool operator==(const TextUnderlineOffset& other) const
+    {
+        return m_length == other.m_length;
+    }
+
+    bool operator!=(const TextUnderlineOffset& other) const
+    {
+        return !(*this == other);
+    }
+
+private:
+    enum class Type {
+        Auto,
+        Length
+    };
+
+    TextUnderlineOffset(Type type)
+    {
+        if (type == Type::Length)
+            m_length = 0;
+    }
+
+    std::optional<float> m_length;
+};
+
+inline TextStream& operator<<(TextStream& ts, const TextUnderlineOffset& offset)
+{
+    if (offset.isAuto())
+        ts << "auto";
+    else
+        ts << TextStream::FormatNumberRespectingIntegers(offset.lengthValue());
+    return ts;
+}
+
+} // namespace WebCore
index 136f31a..ab1567f 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace WebCore {
     
-int computeUnderlineOffset(OptionSet<TextUnderlinePosition> underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness)
+int computeUnderlineOffset(TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness)
 {
     // This represents the gap between the baseline and the closest edge of the underline.
     int gap = std::max<int>(1, ceilf(textDecorationThickness / 2.0));
@@ -50,13 +50,14 @@ int computeUnderlineOffset(OptionSet<TextUnderlinePosition> underlinePosition, c
     auto resolvedUnderlinePosition = underlinePosition;
     if (resolvedUnderlinePosition == TextUnderlinePosition::Auto) {
         if (inlineTextBox)
-            resolvedUnderlinePosition = inlineTextBox->root().baselineType() == IdeographicBaseline ? TextUnderlinePosition::Under : TextUnderlinePosition::Alphabetic;
+            resolvedUnderlinePosition = inlineTextBox->root().baselineType() == IdeographicBaseline ? TextUnderlinePosition::Under : TextUnderlinePosition::Auto;
         else
-            resolvedUnderlinePosition = TextUnderlinePosition::Alphabetic;
+            resolvedUnderlinePosition = TextUnderlinePosition::Auto;
     }
     
-    switch (static_cast<TextUnderlinePosition>(resolvedUnderlinePosition.toRaw())) {
-    case TextUnderlinePosition::Alphabetic:
+    switch (resolvedUnderlinePosition) {
+    case TextUnderlinePosition::Auto:
+    case TextUnderlinePosition::FromFont:
         return fontMetrics.ascent() + gap;
     case TextUnderlinePosition::Under: {
         ASSERT(inlineTextBox);
@@ -76,8 +77,6 @@ int computeUnderlineOffset(OptionSet<TextUnderlinePosition> underlinePosition, c
         }
         return inlineTextBox->logicalHeight() + gap + std::max<float>(offset, 0);
     }
-    case TextUnderlinePosition::Auto:
-        ASSERT_NOT_REACHED();
     }
 
     ASSERT_NOT_REACHED();
index cc5312a..a8525a4 100644 (file)
@@ -46,6 +46,6 @@ inline float wavyOffsetFromDecoration()
 
 GlyphOverflow visualOverflowForDecorations(const RenderStyle& lineStyle, const InlineTextBox*);
 void getWavyStrokeParameters(float fontSize, float& controlPointDistance, float& step);
-int computeUnderlineOffset(OptionSet<TextUnderlinePosition>, const FontMetrics&, const InlineTextBox*, int textDecorationThickness);
+int computeUnderlineOffset(TextUnderlinePosition, const FontMetrics&, const InlineTextBox*, int textDecorationThickness);
     
 } // namespace WebCore