Unify font-variant-* with font-variant shorthand
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Nov 2015 21:20:32 +0000 (21:20 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Nov 2015 21:20:32 +0000 (21:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149773

Reviewed by Darin Adler.

Source/WebCore:

This patch makes font-variant a shorthand for the following properties:
font-variant-ligatures
font-variant-position
font-variant-caps
font-variant-numeric
font-variant-alternates
font-variant-east-asian

This is consistent with the CSS Fonts Level 3 spec.

This patch also migrates the "font" longhand to use the font-variant-caps
property.

Test: fast/text/font-variant-shorthand.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::fontVariantEastAsianPropertyValue): Rename FontVariantEastAsian values.
(WebCore::fontVariantFromStyle): We must consult with the longhand properties to determine
font-variant computed style.
(WebCore::ComputedStyleExtractor::propertyValue): Don't put any-old font-variant-caps inside
the font shorthand.
* css/CSSFontSelector.cpp:
(WebCore::CSSFontSelector::addFontFaceRule): Guard against incorrect downcasts (due to inherit
of the new shorthand property).
* css/CSSParser.cpp: Parse font-variant as a shorthand. Also implement its "normal" and "none" values.
(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseFont):
(WebCore::CSSParser::parseSystemFont):
(WebCore::CSSParser::parseFontVariantLigatures):
(WebCore::CSSParser::parseFontVariantNumeric):
(WebCore::CSSParser::parseFontVariantEastAsian):
(WebCore::CSSParser::parseFontVariant):
(WebCore::isValidKeywordPropertyAndValue): Deleted.
(WebCore::isKeywordPropertyID): Deleted.
* css/CSSParser.h:
* css/CSSPropertyNames.in: Turn font-variant into a shorthand property.
* css/FontVariantBuilder.h: Guard against incorrect downcasts. Also update for renamed
FontVariantEastAsian type.
(WebCore::applyValueFontVariantLigatures):
(WebCore::applyValueFontVariantNumeric):
(WebCore::applyValueFontVariantEastAsian):
* css/StyleProperties.cpp: Update to use the more specific property.
(WebCore::StyleProperties::appendFontLonghandValueIfExplicit):
(WebCore::StyleProperties::fontValue):
(WebCore::StyleProperties::asText):
* css/StyleResolver.cpp: Ditto.
(WebCore::StyleResolver::isValidCueStyleProperty):
* editing/EditingStyle.cpp: Ditto.
* editing/cocoa/HTMLConverter.mm: Ditto.
(HTMLConverterCaches::propertyValueForNode):
(HTMLConverter::computedAttributesForElement):
* editing/ios/EditorIOS.mm: Ditto.
(WebCore::Editor::removeUnchangeableStyles):
* html/canvas/CanvasRenderingContext2D.cpp: Ditto.
(WebCore::CanvasRenderingContext2D::font):
(WebCore::CanvasRenderingContext2D::setFont):
* platform/graphics/FontCache.h: Removing duplicate cache key value.
(WebCore::FontDescriptionKey::makeFlagsKey):
* platform/graphics/FontCascade.cpp: Migrate to the new font-variant-caps from the old member variable.
(WebCore::FontCascade::glyphDataForCharacter):
* platform/graphics/FontCascade.h: Ditto.
(WebCore::FontCascade::isSmallCaps):
* platform/graphics/FontDescription.cpp: Ditto.
(WebCore::FontDescription::FontDescription):
* platform/graphics/FontDescription.h: Ditto.
(WebCore::FontCascadeDescription::equalForTextAutoSizing):
(WebCore::FontDescription::smallCaps): Deleted.
(WebCore::FontDescription::setSmallCaps): Deleted.
(WebCore::FontDescription::setIsSmallCaps): Deleted.
(WebCore::FontDescription::operator==): Deleted.
* platform/graphics/cocoa/FontCacheCoreText.cpp: Rename FontVariantEastAsianWidth.
(WebCore::computeFeatureSettingsFromVariants):
* platform/text/TextFlags.h: Ditto.
(WebCore::FontVariantSettings::operator==):
* rendering/RenderText.cpp: Migrage to the new font-variant-caps from the old member variable.
(WebCore::RenderText::widthFromCache):

LayoutTests:

Update tests. Also temporarily skip existing font-features tests until
https://bugs.webkit.org/show_bug.cgi?id=149774 is fixed.

* css3/font-variant-parsing-expected.txt:
* css3/font-variant-parsing.html:
* fast/css/font-property-priority-expected.txt:
* fast/css/font-shorthand-expected.txt:
* fast/css/parsing-font-variant-ligatures-expected.txt:
* fast/css/parsing-font-variant-ligatures.html:
* fast/inspector-support/style-expected.txt:
* fast/text/font-variant-shorthand-expected.txt: Added.
* fast/text/font-variant-shorthand.html: Added.
* platform/mac/TestExpectations:
* platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.txt:

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

33 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/font-variant-parsing-expected.txt
LayoutTests/css3/font-variant-parsing.html
LayoutTests/fast/css/font-property-priority-expected.txt
LayoutTests/fast/css/font-shorthand-expected.txt
LayoutTests/fast/css/parsing-font-variant-ligatures-expected.txt
LayoutTests/fast/css/parsing-font-variant-ligatures.html
LayoutTests/fast/inspector-support/style-expected.txt
LayoutTests/fast/text/font-variant-shorthand-expected.txt [new file with mode: 0644]
LayoutTests/fast/text/font-variant-shorthand.html [new file with mode: 0644]
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSFontSelector.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSPropertyNames.in
Source/WebCore/css/FontVariantBuilder.h
Source/WebCore/css/StyleProperties.cpp
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/editing/EditingStyle.cpp
Source/WebCore/editing/cocoa/HTMLConverter.mm
Source/WebCore/editing/ios/EditorIOS.mm
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/FontCascade.cpp
Source/WebCore/platform/graphics/FontCascade.h
Source/WebCore/platform/graphics/FontDescription.cpp
Source/WebCore/platform/graphics/FontDescription.h
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp
Source/WebCore/platform/text/TextFlags.h
Source/WebCore/rendering/RenderText.cpp

index 987aa4b..702b504 100644 (file)
@@ -1,3 +1,25 @@
+2015-11-30  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        Unify font-variant-* with font-variant shorthand
+        https://bugs.webkit.org/show_bug.cgi?id=149773
+
+        Reviewed by Darin Adler.
+
+        Update tests. Also temporarily skip existing font-features tests until
+        https://bugs.webkit.org/show_bug.cgi?id=149774 is fixed.
+
+        * css3/font-variant-parsing-expected.txt:
+        * css3/font-variant-parsing.html:
+        * fast/css/font-property-priority-expected.txt:
+        * fast/css/font-shorthand-expected.txt:
+        * fast/css/parsing-font-variant-ligatures-expected.txt:
+        * fast/css/parsing-font-variant-ligatures.html:
+        * fast/inspector-support/style-expected.txt:
+        * fast/text/font-variant-shorthand-expected.txt: Added.
+        * fast/text/font-variant-shorthand.html: Added.
+        * platform/mac/TestExpectations:
+        * platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.txt:
+
 2015-11-30  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: After versionchange transactions abort, fire onerror on the original IDBOpenDBRequest.
index b774d8a..8b76eb2 100644 (file)
@@ -3,7 +3,7 @@ PASS window.getComputedStyle(document.getElementById('testElement')).getProperty
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "normal"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "normal"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "common-ligatures"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "normal"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "common-ligatures"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "no-common-ligatures"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "discretionary-ligatures"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-ligatures').cssText is "no-discretionary-ligatures"
@@ -49,9 +49,9 @@ PASS window.getComputedStyle(document.getElementById('testElement')).getProperty
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "ordinal"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "slashed-zero"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "lining-nums slashed-zero"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "normal"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "normal"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "normal"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "oldstyle-nums"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "tabular-nums"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "stacked-fractions"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "lining-nums proportional-nums"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "lining-nums diagonal-fractions"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-numeric').cssText is "ordinal slashed-zero"
@@ -74,13 +74,13 @@ PASS window.getComputedStyle(document.getElementById('testElement')).getProperty
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "full-width"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "proportional-width"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "ruby"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "normal"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "normal"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "jis83"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "traditional"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "traditional full-width"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "jis04 proportional-width"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "jis04 proportional-width ruby"
 PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "jis83 ruby"
-PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "normal"
+PASS window.getComputedStyle(document.getElementById('testElement')).getPropertyCSSValue('font-variant-east-asian').cssText is "proportional-width"
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 9fcd818..185d038 100644 (file)
@@ -20,7 +20,7 @@ runTest("font-variant-ligatures", "normal", "normal");
 runTest("font-variant-ligatures", "normal common-ligatures", "normal");
 runTest("font-variant-ligatures", "notavalidvalue", "normal");
 runTest("font-variant-ligatures", "common-ligatures", "common-ligatures");
-runTest("font-variant-ligatures", "common-ligatures common-ligatures", "normal");
+runTest("font-variant-ligatures", "common-ligatures common-ligatures", "common-ligatures");
 runTest("font-variant-ligatures", "no-common-ligatures", "no-common-ligatures");
 runTest("font-variant-ligatures", "discretionary-ligatures", "discretionary-ligatures");
 runTest("font-variant-ligatures", "no-discretionary-ligatures", "no-discretionary-ligatures");
@@ -69,9 +69,9 @@ runTest("font-variant-numeric", "stacked-fractions", "stacked-fractions");
 runTest("font-variant-numeric", "ordinal", "ordinal");
 runTest("font-variant-numeric", "slashed-zero", "slashed-zero");
 runTest("font-variant-numeric", "lining-nums slashed-zero", "lining-nums slashed-zero");
-runTest("font-variant-numeric", "lining-nums oldstyle-nums", "normal");
-runTest("font-variant-numeric", "proportional-nums tabular-nums", "normal");
-runTest("font-variant-numeric", "diagonal-fractions stacked-fractions", "normal");
+runTest("font-variant-numeric", "lining-nums oldstyle-nums", "oldstyle-nums");
+runTest("font-variant-numeric", "proportional-nums tabular-nums", "tabular-nums");
+runTest("font-variant-numeric", "diagonal-fractions stacked-fractions", "stacked-fractions");
 runTest("font-variant-numeric", "lining-nums proportional-nums", "lining-nums proportional-nums");
 runTest("font-variant-numeric", "lining-nums diagonal-fractions", "lining-nums diagonal-fractions");
 runTest("font-variant-numeric", "ordinal slashed-zero", "ordinal slashed-zero");
@@ -96,13 +96,13 @@ runTest("font-variant-east-asian", "traditional", "traditional");
 runTest("font-variant-east-asian", "full-width", "full-width");
 runTest("font-variant-east-asian", "proportional-width", "proportional-width");
 runTest("font-variant-east-asian", "ruby", "ruby");
-runTest("font-variant-east-asian", "jis78 jis83", "normal");
-runTest("font-variant-east-asian", "jis90 traditional", "normal");
+runTest("font-variant-east-asian", "jis78 jis83", "jis83");
+runTest("font-variant-east-asian", "jis90 traditional", "traditional");
 runTest("font-variant-east-asian", "full-width traditional", "traditional full-width");
 runTest("font-variant-east-asian", "jis04 proportional-width", "jis04 proportional-width");
 runTest("font-variant-east-asian", "jis04 proportional-width ruby", "jis04 proportional-width ruby");
 runTest("font-variant-east-asian", "jis83 ruby", "jis83 ruby");
-runTest("font-variant-east-asian", "full-width proportional-width", "normal");
+runTest("font-variant-east-asian", "full-width proportional-width", "proportional-width");
 </script>
 <script src="../resources/js-test-post.js"></script>
 </body>
index 2f5b1b4..7396352 100644 (file)
@@ -1,6 +1,6 @@
 Test for rdar://problem/6065547 REGRESSION (r34879): "Subject" in unread emails in Yahoo mail is not shown in bold.
 
 Property 'font-weight' has priority 'important'.
-Property 'font-variant' has priority 'important'.
+Property 'font-variant-caps' has priority 'important'.
 Property 'font-style' has priority 'important'.
 
index 7f68495..c1613fd 100644 (file)
@@ -1,7 +1,7 @@
 Test
 Font for '12px monospace':
 font-style: normal (original property was font and property was implicitly set.)
-font-variant: normal (original property was font and property was implicitly set.)
+font-variant-caps: normal (original property was font and property was implicitly set.)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: normal (original property was font and property was implicitly set.)
@@ -9,7 +9,7 @@ font-family: monospace (original property was font)
 
 Font for '12px/24px serif':
 font-style: normal (original property was font and property was implicitly set.)
-font-variant: normal (original property was font and property was implicitly set.)
+font-variant-caps: normal (original property was font and property was implicitly set.)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: 24px (original property was font)
@@ -17,7 +17,7 @@ font-family: serif (original property was font)
 
 Font for 'normal 12px serif':
 font-style: normal (original property was font)
-font-variant: normal (original property was font and property was implicitly set.)
+font-variant-caps: normal (original property was font and property was implicitly set.)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: normal (original property was font and property was implicitly set.)
@@ -25,7 +25,7 @@ font-family: serif (original property was font)
 
 Font for 'normal normal 12px serif':
 font-style: normal (original property was font)
-font-variant: normal (original property was font)
+font-variant-caps: normal (original property was font)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: normal (original property was font and property was implicitly set.)
@@ -33,7 +33,7 @@ font-family: serif (original property was font)
 
 Font for 'normal normal normal 12px serif':
 font-style: normal (original property was font)
-font-variant: normal (original property was font)
+font-variant-caps: normal (original property was font)
 font-weight: normal (original property was font)
 font-size: 12px (original property was font)
 line-height: normal (original property was font and property was implicitly set.)
@@ -41,7 +41,7 @@ font-family: serif (original property was font)
 
 Font for 'italic small-caps 12px/24px serif':
 font-style: italic (original property was font)
-font-variant: small-caps (original property was font)
+font-variant-caps: small-caps (original property was font)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: 24px (original property was font)
@@ -50,13 +50,13 @@ font-family: serif (original property was font)
 Font for 'italic bold 12px/24px serif':
 font-style: italic (original property was font)
 font-weight: bold (original property was font)
-font-variant: normal (original property was font and property was implicitly set.)
+font-variant-caps: normal (original property was font and property was implicitly set.)
 font-size: 12px (original property was font)
 line-height: 24px (original property was font)
 font-family: serif (original property was font)
 
 Font for 'small-caps bold 14px/28px Arial, sans-serif':
-font-variant: small-caps (original property was font)
+font-variant-caps: small-caps (original property was font)
 font-weight: bold (original property was font)
 font-style: normal (original property was font and property was implicitly set.)
 font-size: 14px (original property was font)
@@ -65,7 +65,7 @@ font-family: Arial, sans-serif (original property was font)
 
 Font for 'italic small-caps bold 14px/28px Arial, sans-serif':
 font-style: italic (original property was font)
-font-variant: small-caps (original property was font)
+font-variant-caps: small-caps (original property was font)
 font-weight: bold (original property was font)
 font-size: 14px (original property was font)
 line-height: 28px (original property was font)
index e48d3e9..77b6b0e 100644 (file)
@@ -13,7 +13,7 @@ PASS: 'discretionary-ligatures' parsed as 'discretionary-ligatures' and computed
 PASS: 'no-historical-ligatures' parsed as 'no-historical-ligatures' and computed to 'no-historical-ligatures'
 PASS: 'historical-ligatures' parsed as 'historical-ligatures' and computed to 'historical-ligatures'
 
-PASS: 'no-common-ligatures no-common-ligatures' parsed as '' and computed to 'normal'
+PASS: 'no-common-ligatures no-common-ligatures' parsed as 'no-common-ligatures' and computed to 'no-common-ligatures'
 PASS: 'common-ligatures no-discretionary-ligatures' parsed as 'common-ligatures no-discretionary-ligatures' and computed to 'common-ligatures no-discretionary-ligatures'
 PASS: 'common-ligatures no-discretionary-ligatures historical-ligatures' parsed as 'common-ligatures no-discretionary-ligatures historical-ligatures' and computed to 'common-ligatures no-discretionary-ligatures historical-ligatures'
 PASS: 'common-ligatures no-discretionary-ligatures normal' parsed as '' and computed to 'normal'
index 1facab5..ea846a7 100644 (file)
@@ -43,7 +43,7 @@
     test('historical-ligatures', 'historical-ligatures', 'historical-ligatures');
 
     log("");
-    test('no-common-ligatures no-common-ligatures', '', 'normal');
+    test('no-common-ligatures no-common-ligatures', 'no-common-ligatures', 'no-common-ligatures');
     test('common-ligatures no-discretionary-ligatures', 'common-ligatures no-discretionary-ligatures', 'common-ligatures no-discretionary-ligatures');
     test('common-ligatures no-discretionary-ligatures historical-ligatures', 'common-ligatures no-discretionary-ligatures historical-ligatures', 'common-ligatures no-discretionary-ligatures historical-ligatures');
     test('common-ligatures no-discretionary-ligatures normal', '', 'normal');
index 4963cae..6e3a994 100644 (file)
@@ -16,7 +16,7 @@ margin-bottom: 1em (original property was margin and property was implicitly set
 margin-left: 1em (original property was margin and property was implicitly set.)
 color: white
 font-style: normal (original property was font and property was implicitly set.)
-font-variant: normal (original property was font and property was implicitly set.)
+font-variant-caps: normal (original property was font and property was implicitly set.)
 font-weight: normal (original property was font and property was implicitly set.)
 font-size: 24px (original property was font)
 line-height: normal (original property was font and property was implicitly set.)
diff --git a/LayoutTests/fast/text/font-variant-shorthand-expected.txt b/LayoutTests/fast/text/font-variant-shorthand-expected.txt
new file mode 100644 (file)
index 0000000..24dfa69
--- /dev/null
@@ -0,0 +1,42 @@
+This test makes sure that the two shorthand properties which set font-variant-caps get resolved correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.getComputedStyle(document.getElementById('t1')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t2')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t3')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t4')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t5')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t6')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t7')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t8')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t9')).getPropertyValue('font-variant-caps') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t10')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t11')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t12')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t13')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t14')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t15')).getPropertyValue('font-variant-caps') is "normal"
+PASS window.getComputedStyle(document.getElementById('t1')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t2')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t3')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t4')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t5')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t6')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t7')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t8')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t9')).getPropertyValue('font-variant') is "small-caps"
+PASS window.getComputedStyle(document.getElementById('t10')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t11')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t12')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t13')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t14')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t15')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t16')).getPropertyValue('font-variant') is "common-ligatures super small-caps lining-nums historical-forms simplified"
+PASS window.getComputedStyle(document.getElementById('t17')).getPropertyValue('font-variant') is "normal"
+PASS window.getComputedStyle(document.getElementById('t17')).getPropertyValue('font-variant-caps') is "normal"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/text/font-variant-shorthand.html b/LayoutTests/fast/text/font-variant-shorthand.html
new file mode 100644 (file)
index 0000000..4019c3f
--- /dev/null
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+.test {
+    font: 30px Times;
+    display: none;
+}
+#t1 {
+    font-variant-caps: small-caps;
+}
+#t2 {
+    font-variant: small-caps;
+}
+#t3 {
+    font: small-caps 30px Times;
+}
+#t4 {
+    font-variant: normal;
+    font: small-caps 30px Times;
+}
+#t5 {
+    font-variant-caps: normal;
+    font: small-caps 30px Times;
+}
+#t6 {
+    font: 30px Times;
+    font-variant-caps: small-caps;
+}
+#t7 {
+    font-variant: normal;
+    font-variant-caps: small-caps;
+}
+#t8 {
+    font-variant-caps: normal;
+    font-variant: small-caps;
+}
+#t9 {
+    font: 30px Times;
+    font-variant: small-caps;
+}
+#t10 {
+    font-variant: small-caps;
+    font: 30px Times;
+}
+#t11 {
+    font-variant-caps: small-caps;
+    font: 30px Times;
+}
+#t12 {
+    font: small-caps 30px Times;
+    font-variant-caps: normal;
+}
+#t13 {
+    font-variant: small-caps;
+    font-variant-caps: normal;
+}
+#t14 {
+    font-variant-caps: small-caps;
+    font-variant: normal;
+}
+#t15 {
+    font: small-caps 30px Times;
+    font-variant: normal;
+}
+#t16 {
+    font-variant-ligatures: common-ligatures;
+    font-variant-position: super;
+    font-variant-caps: small-caps;
+    font-variant-numeric: lining-nums;
+    font-variant-alternates: historical-forms;
+    font-variant-east-asian: simplified;
+}
+</style>
+</head>
+<body>
+
+<div class="test" id="t1">Hello</div>
+<div class="test" id="t2">Hello</div>
+<div class="test" id="t3">Hello</div>
+<div class="test" id="t4">Hello</div>
+<div class="test" id="t5">Hello</div>
+<div class="test" id="t6">Hello</div>
+<div class="test" id="t7">Hello</div>
+<div class="test" id="t8">Hello</div>
+<div class="test" id="t9">Hello</div>
+<div class="test" id="t10">Hello</div>
+<div class="test" id="t11">Hello</div>
+<div class="test" id="t12">Hello</div>
+<div class="test" id="t13">Hello</div>
+<div class="test" id="t14">Hello</div>
+<div class="test" id="t15">Hello</div>
+<div class="test" id="t16">Hello</div>
+<div class="test" id="t17">Hello</div>
+<script>
+description("This test makes sure that the two shorthand properties which set font-variant-caps get resolved correctly.");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t1')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t2')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t3')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t4')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t5')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t6')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t7')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t8')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t9')).getPropertyValue('font-variant-caps')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t10')).getPropertyValue('font-variant-caps')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t11')).getPropertyValue('font-variant-caps')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t12')).getPropertyValue('font-variant-caps')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t13')).getPropertyValue('font-variant-caps')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t14')).getPropertyValue('font-variant-caps')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t15')).getPropertyValue('font-variant-caps')", "normal");
+
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t1')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t2')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t3')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t4')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t5')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t6')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t7')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t8')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t9')).getPropertyValue('font-variant')", "small-caps");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t10')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t11')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t12')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t13')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t14')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t15')).getPropertyValue('font-variant')", "normal");
+
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t16')).getPropertyValue('font-variant')", "common-ligatures super small-caps lining-nums historical-forms simplified");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t17')).getPropertyValue('font-variant')", "normal");
+shouldBeEqualToString("window.getComputedStyle(document.getElementById('t17')).getPropertyValue('font-variant-caps')", "normal");
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index dfa38e1..396ae9e 100644 (file)
@@ -1397,3 +1397,10 @@ webkit.org/b/150956 imported/w3c/web-platform-tests/html/semantics/embedded-cont
 webkit.org/b/140217 http/tests/navigation/forward-and-cancel.html [ Pass Failure ]
 
 webkit.org/b/151469 imported/w3c/html-templates/parsing-html-templates/creating-an-element-for-the-token/template-owner-document.html [ Pass Crash ]
+
+# Temporarily disable font-features tests until synthesis for font-variant-caps is implemented.
+webkit.org/b/149774 css3/font-feature-settings-font-face-rendering.html [ Pass Failure ImageOnlyFailure ]
+webkit.org/b/149774 css3/font-feature-settings-rendering.html [ Pass Failure ImageOnlyFailure ]
+webkit.org/b/149774 css3/font-variant-all.html [ Pass Failure ImageOnlyFailure ]
+webkit.org/b/149774 css3/font-variant-font-face-all.html [ Pass Failure ImageOnlyFailure ]
+webkit.org/b/149774 css3/font-variant-font-face-override.html [ Pass Failure ImageOnlyFailure ]
index 0f1b646..78f3ddd 100644 (file)
@@ -13,8 +13,8 @@ layer at (0,0) size 800x377
               text run at (21,1) width 176: "\x{7B2C}\x{4E8C}\x{6BB5}\x{843D} Paragraph 2"
         RenderBlock {DIV} at (278,1) size 277x275 [bgcolor=#FFFFEE]
           RenderBlock {P} at (14,28) size 63x219 [bgcolor=#FFAAAA] [border: none (20px solid #FF8888) none (20px solid #FF8888)]
-            RenderText {#text} at (21,1) size 20x195
-              text run at (21,1) width 195: "\x{7B2C}\x{4E00}\x{6BB5}\x{843D} Paragraph 1"
+            RenderText {#text} at (21,1) size 20x175
+              text run at (21,1) width 175: "\x{7B2C}\x{4E00}\x{6BB5}\x{843D} Paragraph 1"
           RenderBlock {P} at (90,28) size 63x219 [bgcolor=#FFAAAA] [border: none (20px solid #FF8888) none (20px solid #FF8888)]
-            RenderText {#text} at (21,1) size 20x195
-              text run at (21,1) width 195: "\x{7B2C}\x{4E8C}\x{6BB5}\x{843D} Paragraph 2"
+            RenderText {#text} at (21,1) size 20x181
+              text run at (21,1) width 181: "\x{7B2C}\x{4E8C}\x{6BB5}\x{843D} Paragraph 2"
index 57827f3..2b9d915 100644 (file)
@@ -1,3 +1,87 @@
+2015-11-30  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        Unify font-variant-* with font-variant shorthand
+        https://bugs.webkit.org/show_bug.cgi?id=149773
+
+        Reviewed by Darin Adler.
+
+        This patch makes font-variant a shorthand for the following properties:
+        font-variant-ligatures
+        font-variant-position
+        font-variant-caps
+        font-variant-numeric
+        font-variant-alternates
+        font-variant-east-asian
+
+        This is consistent with the CSS Fonts Level 3 spec.
+
+        This patch also migrates the "font" longhand to use the font-variant-caps
+        property.
+
+        Test: fast/text/font-variant-shorthand.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::fontVariantEastAsianPropertyValue): Rename FontVariantEastAsian values.
+        (WebCore::fontVariantFromStyle): We must consult with the longhand properties to determine
+        font-variant computed style.
+        (WebCore::ComputedStyleExtractor::propertyValue): Don't put any-old font-variant-caps inside
+        the font shorthand.
+        * css/CSSFontSelector.cpp:
+        (WebCore::CSSFontSelector::addFontFaceRule): Guard against incorrect downcasts (due to inherit
+        of the new shorthand property).
+        * css/CSSParser.cpp: Parse font-variant as a shorthand. Also implement its "normal" and "none" values.
+        (WebCore::CSSParser::parseValue):
+        (WebCore::CSSParser::parseFont):
+        (WebCore::CSSParser::parseSystemFont):
+        (WebCore::CSSParser::parseFontVariantLigatures):
+        (WebCore::CSSParser::parseFontVariantNumeric):
+        (WebCore::CSSParser::parseFontVariantEastAsian):
+        (WebCore::CSSParser::parseFontVariant):
+        (WebCore::isValidKeywordPropertyAndValue): Deleted.
+        (WebCore::isKeywordPropertyID): Deleted.
+        * css/CSSParser.h:
+        * css/CSSPropertyNames.in: Turn font-variant into a shorthand property.
+        * css/FontVariantBuilder.h: Guard against incorrect downcasts. Also update for renamed
+        FontVariantEastAsian type.
+        (WebCore::applyValueFontVariantLigatures):
+        (WebCore::applyValueFontVariantNumeric):
+        (WebCore::applyValueFontVariantEastAsian):
+        * css/StyleProperties.cpp: Update to use the more specific property.
+        (WebCore::StyleProperties::appendFontLonghandValueIfExplicit):
+        (WebCore::StyleProperties::fontValue):
+        (WebCore::StyleProperties::asText):
+        * css/StyleResolver.cpp: Ditto.
+        (WebCore::StyleResolver::isValidCueStyleProperty):
+        * editing/EditingStyle.cpp: Ditto.
+        * editing/cocoa/HTMLConverter.mm: Ditto.
+        (HTMLConverterCaches::propertyValueForNode):
+        (HTMLConverter::computedAttributesForElement):
+        * editing/ios/EditorIOS.mm: Ditto.
+        (WebCore::Editor::removeUnchangeableStyles):
+        * html/canvas/CanvasRenderingContext2D.cpp: Ditto.
+        (WebCore::CanvasRenderingContext2D::font):
+        (WebCore::CanvasRenderingContext2D::setFont):
+        * platform/graphics/FontCache.h: Removing duplicate cache key value.
+        (WebCore::FontDescriptionKey::makeFlagsKey):
+        * platform/graphics/FontCascade.cpp: Migrate to the new font-variant-caps from the old member variable.
+        (WebCore::FontCascade::glyphDataForCharacter):
+        * platform/graphics/FontCascade.h: Ditto.
+        (WebCore::FontCascade::isSmallCaps):
+        * platform/graphics/FontDescription.cpp: Ditto.
+        (WebCore::FontDescription::FontDescription):
+        * platform/graphics/FontDescription.h: Ditto.
+        (WebCore::FontCascadeDescription::equalForTextAutoSizing):
+        (WebCore::FontDescription::smallCaps): Deleted.
+        (WebCore::FontDescription::setSmallCaps): Deleted.
+        (WebCore::FontDescription::setIsSmallCaps): Deleted.
+        (WebCore::FontDescription::operator==): Deleted.
+        * platform/graphics/cocoa/FontCacheCoreText.cpp: Rename FontVariantEastAsianWidth.
+        (WebCore::computeFeatureSettingsFromVariants):
+        * platform/text/TextFlags.h: Ditto.
+        (WebCore::FontVariantSettings::operator==):
+        * rendering/RenderText.cpp: Migrage to the new font-variant-caps from the old member variable.
+        (WebCore::RenderText::widthFromCache):
+
 2015-11-30  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: After versionchange transactions abort, fire onerror on the original IDBOpenDBRequest.
index 1814c32..4ebdeb3 100644 (file)
@@ -1382,10 +1382,10 @@ static Ref<CSSValue> fontVariantEastAsianPropertyValue(FontVariantEastAsianVaria
     switch (width) {
     case FontVariantEastAsianWidth::Normal:
         break;
-    case FontVariantEastAsianWidth::FullWidth:
+    case FontVariantEastAsianWidth::Full:
         valueList->append(cssValuePool.createIdentifierValue(CSSValueFullWidth));
         break;
-    case FontVariantEastAsianWidth::ProportionalWidth:
+    case FontVariantEastAsianWidth::Proportional:
         valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalWidth));
         break;
     }
@@ -1816,23 +1816,203 @@ static Ref<CSSPrimitiveValue> fontSizeFromStyle(RenderStyle& style)
     return zoomAdjustedPixelValue(style.fontDescription().computedPixelSize(), style);
 }
 
-static Ref<CSSPrimitiveValue> fontStyleFromStyle(RenderStyle* style)
+static Ref<CSSPrimitiveValue> fontStyleFromStyle(RenderStyle& style)
 {
-    if (style->fontDescription().italic())
+    if (style.fontDescription().italic())
         return CSSValuePool::singleton().createIdentifierValue(CSSValueItalic);
     return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
 }
 
-static Ref<CSSPrimitiveValue> fontVariantFromStyle(RenderStyle* style)
+static Ref<CSSValue> fontVariantFromStyle(RenderStyle& style)
 {
-    if (style->fontDescription().smallCaps())
-        return CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
-    return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
+    if (style.fontDescription().variantSettings().isAllNormal())
+        return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
+
+    auto list = CSSValueList::createSpaceSeparated();
+
+    switch (style.fontDescription().variantCommonLigatures()) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
+        break;
+    case FontVariantLigatures::No:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
+        break;
+    }
+
+    switch (style.fontDescription().variantDiscretionaryLigatures()) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
+        break;
+    case FontVariantLigatures::No:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
+        break;
+    }
+
+    switch (style.fontDescription().variantHistoricalLigatures()) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
+        break;
+    case FontVariantLigatures::No:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
+        break;
+    }
+
+    switch (style.fontDescription().variantContextualAlternates()) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
+        break;
+    case FontVariantLigatures::No:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
+        break;
+    }
+
+    switch (style.fontDescription().variantPosition()) {
+    case FontVariantPosition::Normal:
+        break;
+    case FontVariantPosition::Subscript:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
+        break;
+    case FontVariantPosition::Superscript:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
+        break;
+    }
+
+    switch (style.fontDescription().variantCaps()) {
+    case FontVariantCaps::Normal:
+        break;
+    case FontVariantCaps::Small:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
+        break;
+    case FontVariantCaps::AllSmall:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
+        break;
+    case FontVariantCaps::Petite:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
+        break;
+    case FontVariantCaps::AllPetite:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
+        break;
+    case FontVariantCaps::Unicase:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
+        break;
+    case FontVariantCaps::Titling:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
+        break;
+    }
+
+    switch (style.fontDescription().variantNumericFigure()) {
+    case FontVariantNumericFigure::Normal:
+        break;
+    case FontVariantNumericFigure::LiningNumbers:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
+        break;
+    case FontVariantNumericFigure::OldStyleNumbers:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
+        break;
+    }
+
+    switch (style.fontDescription().variantNumericSpacing()) {
+    case FontVariantNumericSpacing::Normal:
+        break;
+    case FontVariantNumericSpacing::ProportionalNumbers:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
+        break;
+    case FontVariantNumericSpacing::TabularNumbers:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
+        break;
+    }
+
+    switch (style.fontDescription().variantNumericFraction()) {
+    case FontVariantNumericFraction::Normal:
+        break;
+    case FontVariantNumericFraction::DiagonalFractions:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
+        break;
+    case FontVariantNumericFraction::StackedFractions:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
+        break;
+    }
+
+    switch (style.fontDescription().variantNumericOrdinal()) {
+    case FontVariantNumericOrdinal::Normal:
+        break;
+    case FontVariantNumericOrdinal::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
+        break;
+    }
+
+    switch (style.fontDescription().variantNumericSlashedZero()) {
+    case FontVariantNumericSlashedZero::Normal:
+        break;
+    case FontVariantNumericSlashedZero::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
+        break;
+    }
+
+    switch (style.fontDescription().variantAlternates()) {
+    case FontVariantAlternates::Normal:
+        break;
+    case FontVariantAlternates::HistoricalForms:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
+        break;
+    }
+
+    switch (style.fontDescription().variantEastAsianVariant()) {
+    case FontVariantEastAsianVariant::Normal:
+        break;
+    case FontVariantEastAsianVariant::Jis78:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
+        break;
+    case FontVariantEastAsianVariant::Jis83:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
+        break;
+    case FontVariantEastAsianVariant::Jis90:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
+        break;
+    case FontVariantEastAsianVariant::Jis04:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
+        break;
+    case FontVariantEastAsianVariant::Simplified:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
+        break;
+    case FontVariantEastAsianVariant::Traditional:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
+        break;
+    }
+
+    switch (style.fontDescription().variantEastAsianWidth()) {
+    case FontVariantEastAsianWidth::Normal:
+        break;
+    case FontVariantEastAsianWidth::Full:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
+        break;
+    case FontVariantEastAsianWidth::Proportional:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
+        break;
+    }
+
+    switch (style.fontDescription().variantEastAsianRuby()) {
+    case FontVariantEastAsianRuby::Normal:
+        break;
+    case FontVariantEastAsianRuby::Yes:
+        list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
+        break;
+    }
+
+    return WTF::move(list);
 }
 
-static Ref<CSSPrimitiveValue> fontWeightFromStyle(RenderStyle* style)
+static Ref<CSSPrimitiveValue> fontWeightFromStyle(RenderStyle& style)
 {
-    switch (style->fontDescription().weight()) {
+    switch (style.fontDescription().weight()) {
     case FontWeight100:
         return CSSValuePool::singleton().createIdentifierValue(CSSValue100);
     case FontWeight200:
@@ -2517,9 +2697,12 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
             return cssValuePool.createValue(style->floating());
         case CSSPropertyFont: {
             RefPtr<CSSFontValue> computedFont = CSSFontValue::create();
-            computedFont->style = fontStyleFromStyle(style.get());
-            computedFont->variant = fontVariantFromStyle(style.get());
-            computedFont->weight = fontWeightFromStyle(style.get());
+            computedFont->style = fontStyleFromStyle(*style);
+            if (style->fontDescription().variantCaps() == FontVariantCaps::Small)
+                computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
+            else
+                computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
+            computedFont->weight = fontWeightFromStyle(*style);
             computedFont->size = fontSizeFromStyle(*style);
             computedFont->lineHeight = lineHeightFromStyle(*style);
             computedFont->family = fontFamilyFromStyle(style.get());
@@ -2536,11 +2719,11 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
         case CSSPropertyFontSize:
             return fontSizeFromStyle(*style);
         case CSSPropertyFontStyle:
-            return fontStyleFromStyle(style.get());
+            return fontStyleFromStyle(*style);
         case CSSPropertyFontVariant:
-            return fontVariantFromStyle(style.get());
+            return fontVariantFromStyle(*style);
         case CSSPropertyFontWeight:
-            return fontWeightFromStyle(style.get());
+            return fontWeightFromStyle(*style);
         case CSSPropertyFontSynthesis:
             return fontSynthesisFromStyle(*style);
         case CSSPropertyFontFeatureSettings: {
index 2c298cb..ad2a981 100644 (file)
@@ -304,16 +304,16 @@ void CSSFontSelector::addFontFaceRule(const StyleRuleFontFace& fontFaceRule, boo
     if (variantLigatures)
         applyValueFontVariantLigatures(fontFace.get(), *variantLigatures);
 
-    if (variantPosition)
+    if (is<CSSPrimitiveValue>(variantPosition.get()))
         fontFace->setVariantPosition(downcast<CSSPrimitiveValue>(*variantPosition));
 
-    if (variantCaps)
+    if (is<CSSPrimitiveValue>(variantCaps.get()))
         fontFace->setVariantCaps(downcast<CSSPrimitiveValue>(*variantCaps));
 
     if (variantNumeric)
         applyValueFontVariantNumeric(fontFace.get(), *variantNumeric);
 
-    if (variantAlternates)
+    if (is<CSSPrimitiveValue>(variantAlternates.get()))
         fontFace->setVariantAlternates(downcast<CSSPrimitiveValue>(*variantAlternates));
 
     if (variantEastAsian)
index 6ed7ffe..4c28165 100644 (file)
@@ -1063,10 +1063,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
         if (valueID == CSSValueNormal || valueID == CSSValueHistoricalForms)
             return true;
         break;
-    case CSSPropertyFontVariant: // normal | small-caps
-        if (valueID == CSSValueNormal || valueID == CSSValueSmallCaps)
-            return true;
-        break;
     default:
         ASSERT_NOT_REACHED();
         return false;
@@ -1199,7 +1195,6 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
     case CSSPropertyFontVariantPosition:
     case CSSPropertyFontVariantCaps:
     case CSSPropertyFontVariantAlternates:
-    case CSSPropertyFontVariant:
         return true;
     default:
         return false;
@@ -3120,20 +3115,37 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
         if (id == CSSValueNormal || id == CSSValueNone)
             validPrimitive = true;
         else
-            return parseFontVariantLigatures(important);
+            return parseFontVariantLigatures(important, UnknownIsFailure::Yes);
         break;
     case CSSPropertyFontVariantNumeric:
         if (id == CSSValueNormal)
             validPrimitive = true;
         else
-            return parseFontVariantNumeric(important);
+            return parseFontVariantNumeric(important, UnknownIsFailure::Yes);
         break;
     case CSSPropertyFontVariantEastAsian:
         if (id == CSSValueNormal)
             validPrimitive = true;
         else
-            return parseFontVariantEastAsian(important);
+            return parseFontVariantEastAsian(important, UnknownIsFailure::Yes);
         break;
+    case CSSPropertyFontVariant:
+        if (id == CSSValueNormal) {
+            ShorthandScope scope(this, CSSPropertyFontVariant);
+            addProperty(CSSPropertyFontVariantLigatures, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            addProperty(CSSPropertyFontVariantPosition, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            addProperty(CSSPropertyFontVariantNumeric, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            addProperty(CSSPropertyFontVariantAlternates, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            addProperty(CSSPropertyFontVariantEastAsian, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+            return true;
+        }
+        if (id == CSSValueNone) {
+            ShorthandScope scope(this, CSSPropertyFontVariant);
+            addProperty(CSSPropertyFontVariantLigatures, CSSValuePool::singleton().createIdentifierValue(CSSValueNone), important, true);
+            return true;
+        }
+        return parseFontVariant(important);
 
     case CSSPropertyWebkitClipPath:
         parsedValue = parseClipPath();
@@ -6806,7 +6818,7 @@ bool CSSParser::parseFont(bool important)
             fontStyleParsed = true;
         } else if (!fontVariantParsed && (value->id == CSSValueNormal || value->id == CSSValueSmallCaps)) {
             // Font variant in the shorthand is particular, it only accepts normal or small-caps.
-            addProperty(CSSPropertyFontVariant, CSSValuePool::singleton().createIdentifierValue(value->id), important);
+            addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(value->id), important);
             fontVariantParsed = true;
         } else if (!fontWeightParsed && parseFontWeight(important))
             fontWeightParsed = true;
@@ -6821,7 +6833,7 @@ bool CSSParser::parseFont(bool important)
     if (!fontStyleParsed)
         addProperty(CSSPropertyFontStyle, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
     if (!fontVariantParsed)
-        addProperty(CSSPropertyFontVariant, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
     if (!fontWeightParsed)
         addProperty(CSSPropertyFontWeight, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important, true);
 
@@ -6880,7 +6892,7 @@ void CSSParser::parseSystemFont(bool important)
     Ref<CSSValueList> fontFamilyList = CSSValueList::createCommaSeparated();
     fontFamilyList->append(CSSValuePool::singleton().createFontFamilyValue(fontDescription.familyAt(0), FromSystemFontID::Yes));
     addProperty(CSSPropertyFontFamily, WTF::move(fontFamilyList), important);
-    addProperty(CSSPropertyFontVariant, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important);
     addProperty(CSSPropertyLineHeight, CSSValuePool::singleton().createIdentifierValue(CSSValueNormal), important);
 }
 
@@ -10607,13 +10619,13 @@ bool CSSParser::parseFontFeatureSettings(bool important)
     return false;
 }
 
-bool CSSParser::parseFontVariantLigatures(bool important)
+bool CSSParser::parseFontVariantLigatures(bool important, UnknownIsFailure unknownIsFailure)
 {
     auto values = CSSValueList::createSpaceSeparated();
-    bool sawCommonValue = false;
-    bool sawDiscretionaryValue = false;
-    bool sawHistoricalValue = false;
-    bool sawContextualValue = false;
+    FontVariantLigatures commonLigatures = FontVariantLigatures::Normal;
+    FontVariantLigatures discretionaryLigatures = FontVariantLigatures::Normal;
+    FontVariantLigatures historicalLigatures = FontVariantLigatures::Normal;
+    FontVariantLigatures contextualAlternates = FontVariantLigatures::Normal;
 
     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
         if (value->unit != CSSPrimitiveValue::CSS_IDENT)
@@ -10621,53 +10633,95 @@ bool CSSParser::parseFontVariantLigatures(bool important)
 
         switch (value->id) {
         case CSSValueNoCommonLigatures:
+            commonLigatures = FontVariantLigatures::No;
+            break;
         case CSSValueCommonLigatures:
-            if (sawCommonValue)
-                return false;
-            sawCommonValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            commonLigatures = FontVariantLigatures::Yes;
             break;
         case CSSValueNoDiscretionaryLigatures:
+            discretionaryLigatures = FontVariantLigatures::No;
+            break;
         case CSSValueDiscretionaryLigatures:
-            if (sawDiscretionaryValue)
-                return false;
-            sawDiscretionaryValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            discretionaryLigatures = FontVariantLigatures::Yes;
             break;
         case CSSValueNoHistoricalLigatures:
+            historicalLigatures = FontVariantLigatures::No;
+            break;
         case CSSValueHistoricalLigatures:
-            if (sawHistoricalValue)
-                return false;
-            sawHistoricalValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            historicalLigatures = FontVariantLigatures::Yes;
             break;
         case CSSValueContextual:
+            contextualAlternates = FontVariantLigatures::Yes;
+            break;
         case CSSValueNoContextual:
-            if (sawContextualValue)
-                return false;
-            sawContextualValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            contextualAlternates = FontVariantLigatures::No;
             break;
         default:
-            return false;
+            if (unknownIsFailure == UnknownIsFailure::Yes)
+                return false;
+            continue;
         }
     }
 
+    switch (commonLigatures) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
+        break;
+    case FontVariantLigatures::No:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
+        break;
+    }
+
+    switch (discretionaryLigatures) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
+        break;
+    case FontVariantLigatures::No:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
+        break;
+    }
+
+    switch (historicalLigatures) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
+        break;
+    case FontVariantLigatures::No:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
+        break;
+    }
+
+    switch (contextualAlternates) {
+    case FontVariantLigatures::Normal:
+        break;
+    case FontVariantLigatures::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
+        break;
+    case FontVariantLigatures::No:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
+        break;
+    }
+
     if (!values->length())
-        return false;
+        return unknownIsFailure == UnknownIsFailure::No;
 
-    addProperty(CSSPropertyFontVariantLigatures, WTF::move(values), important);
+    addProperty(CSSPropertyFontVariantLigatures, WTF::move(values), important, false);
     return true;
 }
 
-bool CSSParser::parseFontVariantNumeric(bool important)
+bool CSSParser::parseFontVariantNumeric(bool important, UnknownIsFailure unknownIsFailure)
 {
     auto values = CSSValueList::createSpaceSeparated();
-    bool sawFigureValue = false;
-    bool sawSpacingValue = false;
-    bool sawFractionValue = false;
-    bool sawOrdinal = false;
-    bool sawSlashedZero = false;
+    FontVariantNumericFigure figure = FontVariantNumericFigure::Normal;
+    FontVariantNumericSpacing spacing = FontVariantNumericSpacing::Normal;
+    FontVariantNumericFraction fraction = FontVariantNumericFraction::Normal;
+    FontVariantNumericOrdinal ordinal = FontVariantNumericOrdinal::Normal;
+    FontVariantNumericSlashedZero slashedZero = FontVariantNumericSlashedZero::Normal;
 
     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
         if (value->unit != CSSPrimitiveValue::CSS_IDENT)
@@ -10675,56 +10729,98 @@ bool CSSParser::parseFontVariantNumeric(bool important)
 
         switch (value->id) {
         case CSSValueLiningNums:
+            figure = FontVariantNumericFigure::LiningNumbers;
+            break;
         case CSSValueOldstyleNums:
-            if (sawFigureValue)
-                return false;
-            sawFigureValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            figure = FontVariantNumericFigure::OldStyleNumbers;
             break;
         case CSSValueProportionalNums:
+            spacing = FontVariantNumericSpacing::ProportionalNumbers;
+            break;
         case CSSValueTabularNums:
-            if (sawSpacingValue)
-                return false;
-            sawSpacingValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            spacing = FontVariantNumericSpacing::TabularNumbers;
             break;
         case CSSValueDiagonalFractions:
+            fraction = FontVariantNumericFraction::DiagonalFractions;
+            break;
         case CSSValueStackedFractions:
-            if (sawFractionValue)
-                return false;
-            sawFractionValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            fraction = FontVariantNumericFraction::StackedFractions;
             break;
         case CSSValueOrdinal:
-            if (sawOrdinal)
-                return false;
-            sawOrdinal = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            ordinal = FontVariantNumericOrdinal::Yes;
             break;
         case CSSValueSlashedZero:
-            if (sawSlashedZero)
-                return false;
-            sawSlashedZero = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            slashedZero = FontVariantNumericSlashedZero::Yes;
             break;
         default:
-            return false;
+            if (unknownIsFailure == UnknownIsFailure::Yes)
+                return false;
+            continue;
         }
     }
 
+    switch (figure) {
+    case FontVariantNumericFigure::Normal:
+        break;
+    case FontVariantNumericFigure::LiningNumbers:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
+        break;
+    case FontVariantNumericFigure::OldStyleNumbers:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
+        break;
+    }
+
+    switch (spacing) {
+    case FontVariantNumericSpacing::Normal:
+        break;
+    case FontVariantNumericSpacing::ProportionalNumbers:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
+        break;
+    case FontVariantNumericSpacing::TabularNumbers:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
+        break;
+    }
+
+    switch (fraction) {
+    case FontVariantNumericFraction::Normal:
+        break;
+    case FontVariantNumericFraction::DiagonalFractions:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
+        break;
+    case FontVariantNumericFraction::StackedFractions:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
+        break;
+    }
+
+    switch (ordinal) {
+    case FontVariantNumericOrdinal::Normal:
+        break;
+    case FontVariantNumericOrdinal::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
+        break;
+    }
+
+    switch (slashedZero) {
+    case FontVariantNumericSlashedZero::Normal:
+        break;
+    case FontVariantNumericSlashedZero::Yes:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
+        break;
+    }
+
     if (!values->length())
-        return false;
+        return unknownIsFailure == UnknownIsFailure::No;
 
-    addProperty(CSSPropertyFontVariantNumeric, WTF::move(values), important);
+    addProperty(CSSPropertyFontVariantNumeric, WTF::move(values), important, false);
     return true;
 }
 
-bool CSSParser::parseFontVariantEastAsian(bool important)
+bool CSSParser::parseFontVariantEastAsian(bool important, UnknownIsFailure unknownIsFailure)
 {
     auto values = CSSValueList::createSpaceSeparated();
-    bool sawVariantValue = false;
-    bool sawWidthValue = false;
-    bool sawRuby = false;
+    FontVariantEastAsianVariant variant = FontVariantEastAsianVariant::Normal;
+    FontVariantEastAsianWidth width = FontVariantEastAsianWidth::Normal;
+    FontVariantEastAsianRuby ruby = FontVariantEastAsianRuby::Normal;
 
     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
         if (value->unit != CSSPrimitiveValue::CSS_IDENT)
@@ -10732,38 +10828,209 @@ bool CSSParser::parseFontVariantEastAsian(bool important)
 
         switch (value->id) {
         case CSSValueJis78:
+            variant = FontVariantEastAsianVariant::Jis78;
+            break;
         case CSSValueJis83:
+            variant = FontVariantEastAsianVariant::Jis83;
+            break;
         case CSSValueJis90:
+            variant = FontVariantEastAsianVariant::Jis90;
+            break;
         case CSSValueJis04:
+            variant = FontVariantEastAsianVariant::Jis04;
+            break;
         case CSSValueSimplified:
+            variant = FontVariantEastAsianVariant::Simplified;
+            break;
         case CSSValueTraditional:
-            if (sawVariantValue)
-                return false;
-            sawVariantValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            variant = FontVariantEastAsianVariant::Traditional;
             break;
         case CSSValueFullWidth:
+            width = FontVariantEastAsianWidth::Full;
+            break;
         case CSSValueProportionalWidth:
-            if (sawWidthValue)
-                return false;
-            sawWidthValue = true;
-            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
+            width = FontVariantEastAsianWidth::Proportional;
             break;
         case CSSValueRuby:
-            sawRuby = true;
+            ruby = FontVariantEastAsianRuby::Yes;
             break;
         default:
-            return false;
+            if (unknownIsFailure == UnknownIsFailure::Yes)
+                return false;
+            continue;
         }
     }
 
-    if (sawRuby)
+    switch (variant) {
+    case FontVariantEastAsianVariant::Normal:
+        break;
+    case FontVariantEastAsianVariant::Jis78:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
+        break;
+    case FontVariantEastAsianVariant::Jis83:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
+        break;
+    case FontVariantEastAsianVariant::Jis90:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
+        break;
+    case FontVariantEastAsianVariant::Jis04:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
+        break;
+    case FontVariantEastAsianVariant::Simplified:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
+        break;
+    case FontVariantEastAsianVariant::Traditional:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
+        break;
+    }
+
+    switch (width) {
+    case FontVariantEastAsianWidth::Normal:
+        break;
+    case FontVariantEastAsianWidth::Full:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
+        break;
+    case FontVariantEastAsianWidth::Proportional:
+        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
+        break;
+    }
+
+    switch (ruby) {
+    case FontVariantEastAsianRuby::Normal:
+        break;
+    case FontVariantEastAsianRuby::Yes:
         values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
+    }
 
     if (!values->length())
+        return unknownIsFailure == UnknownIsFailure::No;
+
+    addProperty(CSSPropertyFontVariantEastAsian, WTF::move(values), important, false);
+    return true;
+}
+
+bool CSSParser::parseFontVariant(bool important)
+{
+    ShorthandScope scope(this, CSSPropertyFontVariant);
+    if (!parseFontVariantLigatures(important, UnknownIsFailure::No))
+        return false;
+    m_valueList->setCurrentIndex(0);
+    if (!parseFontVariantNumeric(important, UnknownIsFailure::No))
+        return false;
+    m_valueList->setCurrentIndex(0);
+    if (!parseFontVariantEastAsian(important, UnknownIsFailure::No))
         return false;
+    m_valueList->setCurrentIndex(0);
+
+    FontVariantPosition position = FontVariantPosition::Normal;
+    FontVariantCaps caps = FontVariantCaps::Normal;
+    FontVariantAlternates alternates = FontVariantAlternates::Normal;
+
+    for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+        if (value->unit != CSSPrimitiveValue::CSS_IDENT)
+            return false;
+
+        switch (value->id) {
+        case CSSValueNoCommonLigatures:
+        case CSSValueCommonLigatures:
+        case CSSValueNoDiscretionaryLigatures:
+        case CSSValueDiscretionaryLigatures:
+        case CSSValueNoHistoricalLigatures:
+        case CSSValueHistoricalLigatures:
+        case CSSValueContextual:
+        case CSSValueNoContextual:
+        case CSSValueLiningNums:
+        case CSSValueOldstyleNums:
+        case CSSValueProportionalNums:
+        case CSSValueTabularNums:
+        case CSSValueDiagonalFractions:
+        case CSSValueStackedFractions:
+        case CSSValueOrdinal:
+        case CSSValueSlashedZero:
+        case CSSValueJis78:
+        case CSSValueJis83:
+        case CSSValueJis90:
+        case CSSValueJis04:
+        case CSSValueSimplified:
+        case CSSValueTraditional:
+        case CSSValueFullWidth:
+        case CSSValueProportionalWidth:
+        case CSSValueRuby:
+            break;
+        case CSSValueSub:
+            position = FontVariantPosition::Subscript;
+            break;
+        case CSSValueSuper:
+            position = FontVariantPosition::Superscript;
+            break;
+        case CSSValueSmallCaps:
+            caps = FontVariantCaps::Small;
+            break;
+        case CSSValueAllSmallCaps:
+            caps = FontVariantCaps::AllSmall;
+            break;
+        case CSSValuePetiteCaps:
+            caps = FontVariantCaps::Petite;
+            break;
+        case CSSValueAllPetiteCaps:
+            caps = FontVariantCaps::AllPetite;
+            break;
+        case CSSValueUnicase:
+            caps = FontVariantCaps::Unicase;
+            break;
+        case CSSValueTitlingCaps:
+            caps = FontVariantCaps::Titling;
+            break;
+        case CSSValueHistoricalForms:
+            alternates = FontVariantAlternates::HistoricalForms;
+            break;
+        default:
+            return false;
+        }
+    }
+
+    switch (position) {
+    case FontVariantPosition::Normal:
+        break;
+    case FontVariantPosition::Subscript:
+        addProperty(CSSPropertyFontVariantPosition, CSSValuePool::singleton().createIdentifierValue(CSSValueSub), important, false);
+        break;
+    case FontVariantPosition::Superscript:
+        addProperty(CSSPropertyFontVariantPosition, CSSValuePool::singleton().createIdentifierValue(CSSValueSuper), important, false);
+        break;
+    }
+
+    switch (caps) {
+    case FontVariantCaps::Normal:
+        break;
+    case FontVariantCaps::Small:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps), important, false);
+        break;
+    case FontVariantCaps::AllSmall:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps), important, false);
+        break;
+    case FontVariantCaps::Petite:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps), important, false);
+        break;
+    case FontVariantCaps::AllPetite:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps), important, false);
+        break;
+    case FontVariantCaps::Unicase:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase), important, false);
+        break;
+    case FontVariantCaps::Titling:
+        addProperty(CSSPropertyFontVariantCaps, CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps), important, false);
+        break;
+    }
+
+    switch (alternates) {
+    case FontVariantAlternates::Normal:
+        break;
+    case FontVariantAlternates::HistoricalForms:
+        addProperty(CSSPropertyFontVariantAlternates, CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms), important, false);
+        break;
+    }
 
-    addProperty(CSSPropertyFontVariantEastAsian, WTF::move(values), important);
     return true;
 }
 
index 15bd544..ee39924 100644 (file)
@@ -348,9 +348,11 @@ public:
     bool parseFlowThread(CSSPropertyID, bool important);
     bool parseRegionThread(CSSPropertyID, bool important);
 
-    bool parseFontVariantLigatures(bool important);
-    bool parseFontVariantNumeric(bool important);
-    bool parseFontVariantEastAsian(bool important);
+    enum class UnknownIsFailure { Yes, No };
+    bool parseFontVariantLigatures(bool important, UnknownIsFailure);
+    bool parseFontVariantNumeric(bool important, UnknownIsFailure);
+    bool parseFontVariantEastAsian(bool important, UnknownIsFailure);
+    bool parseFontVariant(bool important);
 
     bool parseWillChange(bool important);
 
index 3599cb9..e2bd6a4 100644 (file)
@@ -102,7 +102,6 @@ display [Custom=Inherit|Value]
 font-family [Inherited, Custom=All]
 font-size [Inherited, Custom=All]
 font-style [Inherited, FontProperty, NameForMethods=Italic]
-font-variant [Inherited, FontProperty, NameForMethods=SmallCaps]
 font-weight [Inherited, Custom=All]
 text-rendering [Inherited, FontProperty, NameForMethods=TextRenderingMode]
 font-feature-settings [Inherited, FontProperty, Custom=Initial|Inherit, Converter=FontFeatureSettings, NameForMethods=FeatureSettings]
@@ -229,7 +228,8 @@ fill-rule [Inherited, SVG]
 float [NameForMethods=Floating]
 flood-color [SVG, Converter=SVGColor]
 flood-opacity [SVG, Converter=Opacity]
-font [Inherited, Longhands=font-family|font-size|font-style|font-variant|font-weight|line-height]
+font [Inherited, Longhands=font-family|font-size|font-style|font-variant-caps|font-weight|line-height]
+font-variant [Inherited, Longhands=font-variant-ligatures|font-variant-position|font-variant-caps|font-variant-numeric|font-variant-alternates|font-variant-east-asian]
 font-stretch [SkipBuilder]
 glyph-orientation-horizontal [Inherited, SVG, Converter=GlyphOrientation]
 glyph-orientation-vertical [Inherited, SVG, Converter=GlyphOrientationOrAuto]
index 2980d7a..fa82429 100644 (file)
@@ -68,7 +68,7 @@ inline void applyValueFontVariantLigatures(T& receiver, CSSValue& value)
                 break;
             }
         }
-    } else {
+    } else if (is<CSSPrimitiveValue>(value)) {
         switch (downcast<CSSPrimitiveValue>(value).getValueID()) {
         case CSSValueNormal:
             break;
@@ -131,7 +131,7 @@ inline void applyValueFontVariantNumeric(T& receiver, CSSValue& value)
                 break;
             }
         }
-    } else
+    } else if (is<CSSPrimitiveValue>(value))
         ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNormal);
 
     receiver.setVariantNumericFigure(figure);
@@ -170,10 +170,10 @@ inline void applyValueFontVariantEastAsian(T& receiver, CSSValue& value)
                 variant = FontVariantEastAsianVariant::Traditional;
                 break;
             case CSSValueFullWidth:
-                width = FontVariantEastAsianWidth::FullWidth;
+                width = FontVariantEastAsianWidth::Full;
                 break;
             case CSSValueProportionalWidth:
-                width = FontVariantEastAsianWidth::ProportionalWidth;
+                width = FontVariantEastAsianWidth::Proportional;
                 break;
             case CSSValueRuby:
                 ruby = FontVariantEastAsianRuby::Yes;
@@ -183,7 +183,7 @@ inline void applyValueFontVariantEastAsian(T& receiver, CSSValue& value)
                 break;
             }
         }
-    } else
+    } else if (is<CSSPrimitiveValue>(value))
         ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNormal);
 
     receiver.setVariantEastAsianVariant(variant);
index f273951..14f7ac7 100644 (file)
@@ -269,7 +269,7 @@ void StyleProperties::appendFontLonghandValueIfExplicit(CSSPropertyID propertyID
     case CSSPropertyFontStyle:
         break; // No prefix.
     case CSSPropertyFontFamily:
-    case CSSPropertyFontVariant:
+    case CSSPropertyFontVariantCaps:
     case CSSPropertyFontWeight:
         prefix = ' ';
         break;
@@ -303,7 +303,7 @@ String StyleProperties::fontValue() const
     String commonValue = fontSizeProperty.value()->cssText();
     StringBuilder result;
     appendFontLonghandValueIfExplicit(CSSPropertyFontStyle, result, commonValue);
-    appendFontLonghandValueIfExplicit(CSSPropertyFontVariant, result, commonValue);
+    appendFontLonghandValueIfExplicit(CSSPropertyFontVariantCaps, result, commonValue);
     appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result, commonValue);
     if (!result.isEmpty())
         result.append(' ');
@@ -973,7 +973,7 @@ String StyleProperties::asText() const
             case CSSPropertyLineHeight:
             case CSSPropertyFontSize:
             case CSSPropertyFontStyle:
-            case CSSPropertyFontVariant:
+            case CSSPropertyFontVariantCaps:
             case CSSPropertyFontWeight:
                 // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing.
                 break;
index e3b0f68..1a73210 100644 (file)
@@ -1805,7 +1805,7 @@ inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
     case CSSPropertyFontFamily:
     case CSSPropertyFontSize:
     case CSSPropertyFontStyle:
-    case CSSPropertyFontVariant:
+    case CSSPropertyFontVariantCaps:
     case CSSPropertyFontWeight:
     case CSSPropertyLineHeight:
     case CSSPropertyOpacity:
index 12e9d52..1109eb5 100644 (file)
@@ -60,7 +60,7 @@ static const CSSPropertyID editingProperties[] = {
     CSSPropertyFontFamily,
     CSSPropertyFontSize,
     CSSPropertyFontStyle,
-    CSSPropertyFontVariant,
+    CSSPropertyFontVariantCaps,
     CSSPropertyFontWeight,
     CSSPropertyLetterSpacing,
     CSSPropertyOrphans,
index 75db71d..716f34c 100644 (file)
@@ -757,7 +757,7 @@ String HTMLConverterCaches::propertyValueForNode(Node& node, CSSPropertyID prope
             inherit = true;
         break;
     case CSSPropertyFontFamily:
-    case CSSPropertyFontVariant:
+    case CSSPropertyFontVariantCaps:
     case CSSPropertyTextTransform:
     case CSSPropertyTextShadow:
     case CSSPropertyVisibility:
@@ -1118,7 +1118,7 @@ NSDictionary *HTMLConverter::computedAttributesForElement(Element& element)
                 font = originalFont;
         }
 #if !PLATFORM(IOS) // IJB: No small caps support on iOS
-        if (_caches->propertyValueForNode(element, CSSPropertyFontVariant) == "small-caps") {
+        if (_caches->propertyValueForNode(element, CSSPropertyFontVariantCaps) == "small-caps") {
             // ??? synthesize small-caps if [font isEqual:originalFont]
             NSFont *originalFont = font;
             font = [fontManager convertFont:font toHaveTrait:NSSmallCapsFontMask];
index 22f75bc..5ce98bb 100644 (file)
@@ -261,7 +261,7 @@ void Editor::removeUnchangeableStyles()
     // FIXME: it'd be nice if knowledge about which styles were unchangeable was not hard-coded here.
     defaultStyle->removeProperty(CSSPropertyFontWeight);
     defaultStyle->removeProperty(CSSPropertyFontStyle);
-    defaultStyle->removeProperty(CSSPropertyFontVariant);
+    defaultStyle->removeProperty(CSSPropertyFontVariantCaps);
     // FIXME: we should handle also pasted quoted text, strikethrough, etc. <rdar://problem/9255115>
     defaultStyle->removeProperty(CSSPropertyTextDecoration);
     defaultStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect); // implements underline
index d2bdd0b..043a4e3 100644 (file)
@@ -2118,7 +2118,7 @@ String CanvasRenderingContext2D::font() const
 
     if (fontDescription.italic())
         serializedFont.appendLiteral("italic ");
-    if (fontDescription.smallCaps() == FontSmallCapsOn)
+    if (fontDescription.variantCaps() == FontVariantCaps::Small)
         serializedFont.appendLiteral("small-caps ");
 
     serializedFont.appendNumber(fontDescription.computedPixelSize());
@@ -2187,7 +2187,7 @@ void CanvasRenderingContext2D::setFont(const String& newFont)
     StyleResolver& styleResolver = canvas()->styleResolver();
     styleResolver.applyPropertyToStyle(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get(), &newStyle.get());
     styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontStyle, parsedStyle->getPropertyCSSValue(CSSPropertyFontStyle).get());
-    styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontVariant, parsedStyle->getPropertyCSSValue(CSSPropertyFontVariant).get());
+    styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontVariantCaps, parsedStyle->getPropertyCSSValue(CSSPropertyFontVariantCaps).get());
     styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontWeight, parsedStyle->getPropertyCSSValue(CSSPropertyFontWeight).get());
 
     // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
index f9cfffb..cf48bc6 100644 (file)
@@ -110,9 +110,8 @@ private:
     static std::array<unsigned, 2> makeFlagsKey(const FontDescription& description)
     {
         static_assert(USCRIPT_CODE_LIMIT < 0x1000, "Script code must fit in an unsigned along with the other flags");
-        unsigned first = static_cast<unsigned>(description.script()) << 11
-            | static_cast<unsigned>(description.textRenderingMode()) << 9
-            | static_cast<unsigned>(description.smallCaps()) << 8
+        unsigned first = static_cast<unsigned>(description.script()) << 10
+            | static_cast<unsigned>(description.textRenderingMode()) << 8
             | static_cast<unsigned>(description.fontSynthesis()) << 6
             | static_cast<unsigned>(description.widthVariant()) << 4
             | static_cast<unsigned>(description.nonCJKGlyphOrientation()) << 3
index 993a006..c6457fa 100644 (file)
@@ -393,7 +393,7 @@ float FontCascade::width(const TextRun& run, int& charsConsumed, String& glyphNa
 GlyphData FontCascade::glyphDataForCharacter(UChar32 c, bool mirror, FontVariant variant) const
 {
     if (variant == AutoVariant) {
-        if (m_fontDescription.smallCaps() && !primaryFont().isSVGFont()) {
+        if (m_fontDescription.variantCaps() == FontVariantCaps::Small && !primaryFont().isSVGFont()) {
             UChar32 upperC = u_toupper(c);
             if (upperC != c) {
                 c = upperC;
index 87b141a..f8dad60 100644 (file)
@@ -148,7 +148,7 @@ public:
     int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const;
     void adjustSelectionRectForText(const TextRun&, LayoutRect& selectionRect, int from = 0, int to = -1) const;
 
-    bool isSmallCaps() const { return m_fontDescription.smallCaps(); }
+    bool isSmallCaps() const { return m_fontDescription.variantCaps() == FontVariantCaps::Small; }
 
     float wordSpacing() const { return m_wordSpacing; }
     float letterSpacing() const { return m_letterSpacing; }
index f5148da..5586ddb 100644 (file)
@@ -52,7 +52,6 @@ FontDescription::FontDescription()
     , m_nonCJKGlyphOrientation(static_cast<unsigned>(NonCJKGlyphOrientation::Mixed))
     , m_widthVariant(RegularWidth)
     , m_italic(FontItalicOff)
-    , m_smallCaps(FontSmallCapsOff)
     , m_weight(FontWeightNormal)
     , m_renderingMode(static_cast<unsigned>(FontRenderingMode::Normal))
     , m_textRendering(AutoTextRendering)
index 85acfc0..aaac13d 100644 (file)
@@ -48,7 +48,6 @@ public:
     float computedSize() const { return m_computedSize; }
     FontItalic italic() const { return static_cast<FontItalic>(m_italic); }
     int computedPixelSize() const { return int(m_computedSize + 0.5f); }
-    FontSmallCaps smallCaps() const { return static_cast<FontSmallCaps>(m_smallCaps); }
     FontWeight weight() const { return static_cast<FontWeight>(m_weight); }
     FontWeight lighterWeight() const;
     FontWeight bolderWeight() const;
@@ -99,8 +98,6 @@ public:
     void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
     void setItalic(FontItalic i) { m_italic = i; }
     void setIsItalic(bool i) { setItalic(i ? FontItalicOn : FontItalicOff); }
-    void setSmallCaps(FontSmallCaps c) { m_smallCaps = c; }
-    void setIsSmallCaps(bool c) { setSmallCaps(c ? FontSmallCapsOn : FontSmallCapsOff); }
     void setWeight(FontWeight w) { m_weight = w; }
     void setRenderingMode(FontRenderingMode mode) { m_renderingMode = static_cast<unsigned>(mode); }
     void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
@@ -137,7 +134,6 @@ private:
     unsigned m_nonCJKGlyphOrientation : 1; // NonCJKGlyphOrientation - Only used by vertical text. Determines the default orientation for non-ideograph glyphs.
     unsigned m_widthVariant : 2; // FontWidthVariant
     unsigned m_italic : 1; // FontItalic
-    unsigned m_smallCaps : 1; // FontSmallCaps
     unsigned m_weight : 8; // FontWeight
     unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
     unsigned m_textRendering : 2; // TextRenderingMode
@@ -164,7 +160,6 @@ inline bool FontDescription::operator==(const FontDescription& other) const
 {
     return m_computedSize == other.m_computedSize
         && m_italic == other.m_italic
-        && m_smallCaps == other.m_smallCaps
         && m_weight == other.m_weight
         && m_renderingMode == other.m_renderingMode
         && m_textRendering == other.m_textRendering
@@ -251,7 +246,7 @@ public:
     {
         return familiesEqualForTextAutoSizing(other)
             && m_specifiedSize == other.m_specifiedSize
-            && smallCaps() == other.smallCaps()
+            && variantSettings() == other.variantSettings()
             && m_isAbsoluteSize == other.m_isAbsoluteSize;
     }
 #endif
index 7473270..9e3f2f8 100644 (file)
@@ -342,10 +342,10 @@ static FeaturesMap computeFeatureSettingsFromVariants(const FontVariantSettings&
     switch (variantSettings.eastAsianWidth) {
     case FontVariantEastAsianWidth::Normal:
         break;
-    case FontVariantEastAsianWidth::FullWidth:
+    case FontVariantEastAsianWidth::Full:
         result.add(fontFeatureTag("fwid"), 1);
         break;
-    case FontVariantEastAsianWidth::ProportionalWidth:
+    case FontVariantEastAsianWidth::Proportional:
         result.add(fontFeatureTag("pwid"), 1);
         break;
     default:
index 670f7f3..a31cd28 100644 (file)
@@ -139,8 +139,8 @@ enum class FontVariantEastAsianVariant {
 
 enum class FontVariantEastAsianWidth {
     Normal,
-    FullWidth,
-    ProportionalWidth
+    Full,
+    Proportional
 };
 
 enum class FontVariantEastAsianRuby {
@@ -221,6 +221,25 @@ struct FontVariantSettings {
             && eastAsianRuby == FontVariantEastAsianRuby::Normal;
     }
 
+    bool operator==(const FontVariantSettings& other)
+    {
+        return commonLigatures == other.commonLigatures
+            && discretionaryLigatures == other.discretionaryLigatures
+            && historicalLigatures == other.historicalLigatures
+            && contextualAlternates == other.contextualAlternates
+            && position == other.position
+            && caps == other.caps
+            && numericFigure == other.numericFigure
+            && numericSpacing == other.numericSpacing
+            && numericFraction == other.numericFraction
+            && numericOrdinal == other.numericOrdinal
+            && numericSlashedZero == other.numericSlashedZero
+            && alternates == other.alternates
+            && eastAsianVariant == other.eastAsianVariant
+            && eastAsianWidth == other.eastAsianWidth
+            && eastAsianRuby == other.eastAsianRuby;
+    }
+
     FontVariantLigatures commonLigatures;
     FontVariantLigatures discretionaryLigatures;
     FontVariantLigatures historicalLigatures;
index fd0579c..ff0e8d4 100644 (file)
@@ -460,7 +460,7 @@ ALWAYS_INLINE float RenderText::widthFromCache(const FontCascade& f, int start,
             return combineText.combinedTextWidth(f);
     }
 
-    if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
+    if (f.isFixedPitch() && f.fontDescription().variantSettings().isAllNormal() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
         float monospaceCharacterWidth = f.spaceWidth();
         float w = 0;
         bool isSpace;