[Web Animations] Interpolation between font-styles with a keyword value should be...
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Jul 2018 22:23:25 +0000 (22:23 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Jul 2018 22:23:25 +0000 (22:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187722

Reviewed by Myles Maxfield.

LayoutTests/imported/w3c:

Mark some WPT progressions.

* web-platform-tests/web-animations/animation-model/animation-types/discrete-expected.txt:

Source/WebCore:

Animating between "font-style: normal" or "font-style: oblique" and any another value should yield a discrete
interpolation where the from-value is used from 0 and up to (but excluding) 0.5, and the to-value from 0.5 to 1.

In order to be able to detect the "normal" value, we make the "slope" of a FontSelectionRequest an optional type
where the std::nullopt value indicates "normal" and other values an "oblique" value. Since we also need to
distinguish the "italic" value from an "oblique" value, we implement a custom PropertyWrapper for the "font-style"
property where we ensure the fontStyleAxis property of the font description matches the value we're blending to.
Indeed, in the case where we may animate from "normal" to "italic", the fontStyleAxis on the blended style would
remain "slnt" since it is the base value for "normal".

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::hasPlainText const):
* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::fontStyleFromStyleValue):
* css/CSSComputedStyleDeclaration.h:
* css/CSSFontFace.cpp:
(WebCore::calculateItalicRange):
* css/CSSFontFaceSet.cpp:
(WebCore::computeFontSelectionRequest):
* css/FontSelectionValueInlines.h:
(WebCore::fontStyleKeyword):
(WebCore::fontStyleValue): Deleted.
* css/StyleBuilderConverter.h:
(WebCore::StyleBuilderConverter::convertFontStyleFromValue):
* page/animation/CSSPropertyAnimation.cpp:
(WebCore::blendFunc):
(WebCore::PropertyWrapperFontStyle::PropertyWrapperFontStyle):
(WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):
* platform/graphics/FontCache.h:
(WebCore::FontDescriptionKey::computeHash const):
* platform/graphics/FontCascade.h:
(WebCore::FontCascade::italic const):
* platform/graphics/FontDescription.h:
(WebCore::FontDescription::italic const):
(WebCore::FontDescription::setItalic):
(WebCore::FontDescription::setIsItalic):
(WebCore::FontCascadeDescription::initialItalic):
* platform/graphics/FontSelectionAlgorithm.cpp:
(WebCore::FontSelectionAlgorithm::styleDistance const):
* platform/graphics/FontSelectionAlgorithm.h:
(WebCore::isItalic):
(WebCore::FontSelectionRequest::tied const):
(WebCore::operator<<): Implement the required stream operator.
(WebCore::operator==): Mark this function as inline instead of constexpr since tied() is no longer constexpr
due to taking an std::optional<>.
(WebCore::operator!=):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::preparePlatformFont):
* platform/graphics/win/FontCacheWin.cpp:
(WebCore::FontCache::createFontPlatformData):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::setFontItalic):
* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::fontItalic const):

Source/WebKitLegacy/win:

Use isItalic() since that function knows how to handle an std::optional<FontSelectionValue>.

* DOMCoreClasses.cpp:
(DOMElement::font):

LayoutTests:

Mark some WPT progressions.

* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:

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

32 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/discrete-expected.txt
LayoutTests/platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt
LayoutTests/platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt
LayoutTests/platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
LayoutTests/platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt
LayoutTests/platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt
LayoutTests/platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
LayoutTests/platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt
LayoutTests/platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt
LayoutTests/platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSComputedStyleDeclaration.h
Source/WebCore/css/CSSFontFace.cpp
Source/WebCore/css/CSSFontFaceSet.cpp
Source/WebCore/css/FontSelectionValueInlines.h
Source/WebCore/css/StyleBuilderConverter.h
Source/WebCore/page/animation/CSSPropertyAnimation.cpp
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/FontCascade.h
Source/WebCore/platform/graphics/FontDescription.h
Source/WebCore/platform/graphics/FontSelectionAlgorithm.cpp
Source/WebCore/platform/graphics/FontSelectionAlgorithm.h
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp
Source/WebCore/platform/graphics/win/FontCacheWin.cpp
Source/WebCore/rendering/style/RenderStyle.cpp
Source/WebCore/rendering/style/RenderStyle.h
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/DOMCoreClasses.cpp

index ae9c3a0..69af074 100644 (file)
@@ -1,3 +1,19 @@
+2018-07-18  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Interpolation between font-styles with a keyword value should be discrete
+        https://bugs.webkit.org/show_bug.cgi?id=187722
+
+        Reviewed by Myles Maxfield.
+
+        Mark some WPT progressions.
+
+        * platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
+        * platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
+        * platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
+        * platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
+        * platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
+        * platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
+
 2018-07-18  Jer Noble  <jer.noble@apple.com>
 
         PiP from Element Fullscreen should match AVKit's behavior
index 25d2e59..e745f02 100644 (file)
@@ -1,3 +1,14 @@
+2018-07-18  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Interpolation between font-styles with a keyword value should be discrete
+        https://bugs.webkit.org/show_bug.cgi?id=187722
+
+        Reviewed by Myles Maxfield.
+
+        Mark some WPT progressions.
+
+        * web-platform-tests/web-animations/animation-model/animation-types/discrete-expected.txt:
+
 2018-07-17  Antoine Quint  <graouts@apple.com>
 
         [Web Animations] Interpolation between lengths with an "auto" value should be discrete
index 6522d46..1645c61 100644 (file)
@@ -1,7 +1,7 @@
 
-FAIL Test animating discrete values assert_equals: Animation produces 'from' value just before the middle of the interval expected "normal" but got "oblique 9.75deg"
+PASS Test animating discrete values 
 PASS Test discrete animation is used when interpolation fails 
 PASS Test discrete animation is used only for pairs of values that cannot be interpolated 
-FAIL Test the 50% switch point for discrete animation is based on the effect easing assert_equals: Animation produces 'from' value at 94% of the iteration time expected "normal" but got "oblique 8.5deg"
-FAIL Test the 50% switch point for discrete animation is based on the keyframe easing assert_equals: Animation produces 'from' value at 94% of the iteration time expected "normal" but got "oblique 8.5deg"
+PASS Test the 50% switch point for discrete animation is based on the effect easing 
+PASS Test the 50% switch point for discrete animation is based on the keyframe easing 
 
index d59152b..10db350 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAccumulation function
 FAIL font-stretch uses font-stretch behavior for composite type accumulate assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAccumulation function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS font-variation-settings (type: fontVariationSettings) has testAccumulation function 
 FAIL font-variation-settings with composite type accumulate assert_equals: The value should be "wght" 2.2 at 250ms expected "\"wght\" 2.2" but got "\"wght\" 1.2"
 PASS font-variation-settings (type: discrete) has testAccumulation function 
index d2e6813..db49bb3 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAddition function
 FAIL font-stretch uses font-stretch behavior for composite type add assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAddition function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS font-variation-settings (type: fontVariationSettings) has testAddition function 
 FAIL font-variation-settings with composite type add assert_equals: The value should be "wght" 2.2 at 250ms expected "\"wght\" 2.2" but got "\"wght\" 1.2"
 PASS font-variation-settings (type: discrete) has testAddition function 
index ebc8a58..c1b5113 100644 (file)
@@ -157,9 +157,9 @@ PASS font-stretch (type: fontStretch) has testInterpolation function
 FAIL font-stretch supports animating as a font-stretch (adjacent values) assert_equals: The value should be ultra-condensed at 499ms expected "ultra-condensed" but got "56%"
 PASS font-stretch supports animating as a font-stretch (between value) 
 PASS font-style (type: discrete) has testInterpolation function 
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with linear easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with effect easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with linear easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with effect easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing 
 PASS font-variation-settings (type: fontVariationSettings) has testInterpolation function 
 PASS font-variation-settings supports animation as float 
 PASS font-variation-settings supports animation as float with multiple tags 
index 0b8a9b8..94d595e 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAccumulation function
 FAIL font-stretch uses font-stretch behavior for composite type accumulate assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAccumulation function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS letter-spacing (type: length) has testAccumulation function 
 FAIL letter-spacing: length assert_equals: The value should be 20px at 0ms expected "20px" but got "10px"
 FAIL letter-spacing: length of rem assert_equals: The value should be 20px at 0ms expected "20px" but got "10px"
index 0134514..39ae612 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAddition function
 FAIL font-stretch uses font-stretch behavior for composite type add assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAddition function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS letter-spacing (type: length) has testAddition function 
 FAIL letter-spacing: length assert_equals: The value should be 20px at 0ms expected "20px" but got "10px"
 FAIL letter-spacing: length of rem assert_equals: The value should be 20px at 0ms expected "20px" but got "10px"
index 6b3ff75..8cff185 100644 (file)
@@ -157,9 +157,9 @@ PASS font-stretch (type: fontStretch) has testInterpolation function
 FAIL font-stretch supports animating as a font-stretch (adjacent values) assert_equals: The value should be ultra-condensed at 499ms expected "ultra-condensed" but got "56%"
 PASS font-stretch supports animating as a font-stretch (between value) 
 PASS font-style (type: discrete) has testInterpolation function 
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with linear easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with effect easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with linear easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with effect easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing 
 PASS letter-spacing (type: length) has testInterpolation function 
 PASS letter-spacing supports animating as a length 
 PASS letter-spacing supports animating as a length of rem 
index d59152b..10db350 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAccumulation function
 FAIL font-stretch uses font-stretch behavior for composite type accumulate assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAccumulation function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS font-variation-settings (type: fontVariationSettings) has testAccumulation function 
 FAIL font-variation-settings with composite type accumulate assert_equals: The value should be "wght" 2.2 at 250ms expected "\"wght\" 2.2" but got "\"wght\" 1.2"
 PASS font-variation-settings (type: discrete) has testAccumulation function 
index d2e6813..db49bb3 100644 (file)
@@ -134,7 +134,7 @@ PASS font-stretch (type: fontStretch) has testAddition function
 FAIL font-stretch uses font-stretch behavior for composite type add assert_equals: The value should be normal at 0ms expected "normal" but got "expanded"
 PASS font-style (type: discrete) has testAddition function 
 PASS font-style: "oblique" onto "italic" 
-FAIL font-style: "italic" onto "oblique" assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style: "italic" onto "oblique" 
 PASS font-variation-settings (type: fontVariationSettings) has testAddition function 
 FAIL font-variation-settings with composite type add assert_equals: The value should be "wght" 2.2 at 250ms expected "\"wght\" 2.2" but got "\"wght\" 1.2"
 PASS font-variation-settings (type: discrete) has testAddition function 
index ebc8a58..c1b5113 100644 (file)
@@ -157,9 +157,9 @@ PASS font-stretch (type: fontStretch) has testInterpolation function
 FAIL font-stretch supports animating as a font-stretch (adjacent values) assert_equals: The value should be ultra-condensed at 499ms expected "ultra-condensed" but got "56%"
 PASS font-stretch supports animating as a font-stretch (between value) 
 PASS font-style (type: discrete) has testInterpolation function 
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with linear easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with effect easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
-FAIL font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing assert_equals: The value should be italic at 0ms expected "italic" but got "oblique"
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with linear easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with effect easing 
+PASS font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing 
 PASS font-variation-settings (type: fontVariationSettings) has testInterpolation function 
 PASS font-variation-settings supports animation as float 
 PASS font-variation-settings supports animation as float with multiple tags 
index 35ca59f..4baae56 100644 (file)
@@ -1,3 +1,65 @@
+2018-07-18  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Interpolation between font-styles with a keyword value should be discrete
+        https://bugs.webkit.org/show_bug.cgi?id=187722
+
+        Reviewed by Myles Maxfield.
+
+        Animating between "font-style: normal" or "font-style: oblique" and any another value should yield a discrete
+        interpolation where the from-value is used from 0 and up to (but excluding) 0.5, and the to-value from 0.5 to 1.
+
+        In order to be able to detect the "normal" value, we make the "slope" of a FontSelectionRequest an optional type
+        where the std::nullopt value indicates "normal" and other values an "oblique" value. Since we also need to
+        distinguish the "italic" value from an "oblique" value, we implement a custom PropertyWrapper for the "font-style"
+        property where we ensure the fontStyleAxis property of the font description matches the value we're blending to.
+        Indeed, in the case where we may animate from "normal" to "italic", the fontStyleAxis on the blended style would
+        remain "slnt" since it is the base value for "normal".
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::hasPlainText const):
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::fontStyleFromStyleValue):
+        * css/CSSComputedStyleDeclaration.h:
+        * css/CSSFontFace.cpp:
+        (WebCore::calculateItalicRange):
+        * css/CSSFontFaceSet.cpp:
+        (WebCore::computeFontSelectionRequest):
+        * css/FontSelectionValueInlines.h:
+        (WebCore::fontStyleKeyword):
+        (WebCore::fontStyleValue): Deleted.
+        * css/StyleBuilderConverter.h:
+        (WebCore::StyleBuilderConverter::convertFontStyleFromValue):
+        * page/animation/CSSPropertyAnimation.cpp:
+        (WebCore::blendFunc):
+        (WebCore::PropertyWrapperFontStyle::PropertyWrapperFontStyle):
+        (WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):
+        * platform/graphics/FontCache.h:
+        (WebCore::FontDescriptionKey::computeHash const):
+        * platform/graphics/FontCascade.h:
+        (WebCore::FontCascade::italic const):
+        * platform/graphics/FontDescription.h:
+        (WebCore::FontDescription::italic const):
+        (WebCore::FontDescription::setItalic):
+        (WebCore::FontDescription::setIsItalic):
+        (WebCore::FontCascadeDescription::initialItalic):
+        * platform/graphics/FontSelectionAlgorithm.cpp:
+        (WebCore::FontSelectionAlgorithm::styleDistance const):
+        * platform/graphics/FontSelectionAlgorithm.h:
+        (WebCore::isItalic):
+        (WebCore::FontSelectionRequest::tied const):
+        (WebCore::operator<<): Implement the required stream operator.
+        (WebCore::operator==): Mark this function as inline instead of constexpr since tied() is no longer constexpr
+        due to taking an std::optional<>.
+        (WebCore::operator!=):
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::preparePlatformFont):
+        * platform/graphics/win/FontCacheWin.cpp:
+        (WebCore::FontCache::createFontPlatformData):
+        * rendering/style/RenderStyle.cpp:
+        (WebCore::RenderStyle::setFontItalic):
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::fontItalic const):
+
 2018-07-18  Jer Noble  <jer.noble@apple.com>
 
         Unreviewed build fix after r233926; BOOL !== bool.
index 2859b60..aed3ec9 100644 (file)
@@ -3598,7 +3598,7 @@ bool AccessibilityRenderObject::hasPlainText() const
 
     const RenderStyle& style = m_renderer->style();
     return style.fontDescription().weight() == normalWeightValue()
-        && style.fontDescription().italic() == normalItalicValue()
+        && !isItalic(style.fontDescription().italic())
         && style.textDecorationsInEffect().isEmpty();
 }
 
index feac687..74bcc81 100644 (file)
@@ -2036,11 +2036,11 @@ Ref<CSSFontStyleValue> ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue
     return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), CSSValuePool::singleton().createValue(static_cast<float>(italic), CSSPrimitiveValue::CSS_DEG));
 }
 
-Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(FontSelectionValue italic, FontStyleAxis fontStyleAxis)
+Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(std::optional<FontSelectionValue> italic, FontStyleAxis fontStyleAxis)
 {
     if (auto keyword = fontStyleKeyword(italic, fontStyleAxis))
         return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(keyword.value()));
-    return fontNonKeywordStyleFromStyleValue(italic);
+    return fontNonKeywordStyleFromStyleValue(italic.value());
 }
 
 static Ref<CSSFontStyleValue> fontStyleFromStyle(const RenderStyle& style)
index 3916182..bdf3432 100644 (file)
@@ -73,7 +73,7 @@ public:
     static Ref<CSSPrimitiveValue> fontNonKeywordStretchFromStyleValue(FontSelectionValue);
     static Ref<CSSPrimitiveValue> fontStretchFromStyleValue(FontSelectionValue);
     static Ref<CSSFontStyleValue> fontNonKeywordStyleFromStyleValue(FontSelectionValue);
-    static Ref<CSSFontStyleValue> fontStyleFromStyleValue(FontSelectionValue, FontStyleAxis);
+    static Ref<CSSFontStyleValue> fontStyleFromStyleValue(std::optional<FontSelectionValue>, FontStyleAxis);
 
 private:
     // The styled element is either the element passed into
index 5b5a521..54a4048 100644 (file)
@@ -202,7 +202,7 @@ static FontSelectionRange calculateItalicRange(CSSValue& value)
 {
     if (value.isFontStyleValue()) {
         auto result = StyleBuilderConverter::convertFontStyleFromValue(value);
-        return { result, result };
+        return { result.value_or(normalItalicValue()), result.value_or(normalItalicValue()) };
     }
 
     ASSERT(value.isFontStyleRangeValue());
index 66c78d5..e1c831e 100644 (file)
@@ -312,9 +312,9 @@ static FontSelectionRequest computeFontSelectionRequest(MutableStyleProperties&
     if (!styleValue)
         styleValue = CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueNormal));
 
-    FontSelectionValue weightSelectionValue = StyleBuilderConverter::convertFontWeightFromValue(*weightValue);
-    FontSelectionValue stretchSelectionValue = StyleBuilderConverter::convertFontStretchFromValue(*stretchValue);
-    FontSelectionValue styleSelectionValue = StyleBuilderConverter::convertFontStyleFromValue(*styleValue);
+    auto weightSelectionValue = StyleBuilderConverter::convertFontWeightFromValue(*weightValue);
+    auto stretchSelectionValue = StyleBuilderConverter::convertFontStretchFromValue(*stretchValue);
+    auto styleSelectionValue = StyleBuilderConverter::convertFontStyleFromValue(*styleValue);
 
     return { weightSelectionValue, stretchSelectionValue, styleSelectionValue };
 }
index 0df020b..fd87c90 100644 (file)
@@ -121,26 +121,13 @@ inline std::optional<FontSelectionValue> fontStretchValue(CSSValueID value)
     }
 }
 
-inline std::optional<CSSValueID> fontStyleKeyword(FontSelectionValue style, FontStyleAxis axis)
+inline std::optional<CSSValueID> fontStyleKeyword(std::optional<FontSelectionValue> style, FontStyleAxis axis)
 {
-    if (style == normalItalicValue())
+    if (!style || style.value() == normalItalicValue())
         return CSSValueNormal;
-    if (style == italicValue())
+    if (style.value() == italicValue())
         return axis == FontStyleAxis::ital ? CSSValueItalic : CSSValueOblique;
     return std::nullopt;
 }
 
-inline std::optional<FontSelectionValue> fontStyleValue(CSSValueID value)
-{
-    switch (value) {
-    case CSSValueNormal:
-        return normalItalicValue();
-    case CSSValueOblique:
-    case CSSValueItalic:
-        return italicValue();
-    default:
-        return std::nullopt;
-    }
-}
-
 }
index 2450c55..481c458 100644 (file)
@@ -118,7 +118,7 @@ public:
     static FontFeatureSettings convertFontFeatureSettings(StyleResolver&, const CSSValue&);
     static FontSelectionValue convertFontWeightFromValue(const CSSValue&);
     static FontSelectionValue convertFontStretchFromValue(const CSSValue&);
-    static FontSelectionValue convertFontStyleFromValue(const CSSValue&);
+    static std::optional<FontSelectionValue> convertFontStyleFromValue(const CSSValue&);
     static FontSelectionValue convertFontWeight(StyleResolver&, const CSSValue&);
     static FontSelectionValue convertFontStretch(StyleResolver&, const CSSValue&);
     static FontSelectionValue convertFontStyle(StyleResolver&, const CSSValue&);
@@ -1202,14 +1202,15 @@ inline FontSelectionValue StyleBuilderConverter::convertFontStretchFromValue(con
     return normalStretchValue();
 }
 
-inline FontSelectionValue StyleBuilderConverter::convertFontStyleFromValue(const CSSValue& value)
+// The input value needs to parsed and valid, this function returns std::nullopt if the input was "normal".
+inline std::optional<FontSelectionValue> StyleBuilderConverter::convertFontStyleFromValue(const CSSValue& value)
 {
     ASSERT(is<CSSFontStyleValue>(value));
     const auto& fontStyleValue = downcast<CSSFontStyleValue>(value);
 
     auto valueID = fontStyleValue.fontStyleValue->valueID();
     if (valueID == CSSValueNormal)
-        return normalItalicValue();
+        return std::nullopt;
     if (valueID == CSSValueItalic)
         return italicValue();
     ASSERT(valueID == CSSValueOblique);
index 86d9dba..d651d56 100644 (file)
@@ -42,6 +42,7 @@
 #include "CalculationValue.h"
 #include "ClipPathOperation.h"
 #include "FloatConversion.h"
+#include "FontCascade.h"
 #include "FontSelectionAlgorithm.h"
 #include "FontTaggedSettings.h"
 #include "GapLength.h"
@@ -414,6 +415,11 @@ static inline FontSelectionValue blendFunc(const CSSPropertyBlendingClient* anim
     return FontSelectionValue(blendFunc(anim, static_cast<float>(from), static_cast<float>(to), progress));
 }
 
+static inline std::optional<FontSelectionValue> blendFunc(const CSSPropertyBlendingClient* anim, std::optional<FontSelectionValue> from, std::optional<FontSelectionValue> to, double progress)
+{
+    return FontSelectionValue(blendFunc(anim, static_cast<float>(from.value()), static_cast<float>(to.value()), progress));
+}
+
 class AnimationPropertyWrapperBase {
     WTF_MAKE_NONCOPYABLE(AnimationPropertyWrapperBase);
     WTF_MAKE_FAST_ALLOCATED;
@@ -1439,6 +1445,42 @@ private:
     void (RenderStyle::*m_setter)(const Color&);
 };
 
+class PropertyWrapperFontStyle : public PropertyWrapper<std::optional<FontSelectionValue>> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    PropertyWrapperFontStyle()
+        : PropertyWrapper<std::optional<FontSelectionValue>>(CSSPropertyFontStyle, &RenderStyle::fontItalic, &RenderStyle::setFontItalic)
+    {
+    }
+
+    bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const override
+    {
+        return from->fontItalic() && to->fontItalic() && from->fontDescription().fontStyleAxis() == FontStyleAxis::slnt && to->fontDescription().fontStyleAxis() == FontStyleAxis::slnt;
+    }
+
+    void blend(const CSSPropertyBlendingClient* anim, RenderStyle* dst, const RenderStyle* from, const RenderStyle* to, double progress) const override
+    {
+        auto discrete = !canInterpolate(from, to);
+
+        auto blendedStyleAxis = FontStyleAxis::slnt;
+        if (discrete)
+            blendedStyleAxis = (progress < 0.5 ? from : to)->fontDescription().fontStyleAxis();
+
+        auto fromFontItalic = from->fontItalic();
+        auto toFontItalic = to->fontItalic();
+        auto blendedFontItalic = progress < 0.5 ? fromFontItalic : toFontItalic;
+        if (!discrete)
+            blendedFontItalic = blendFunc(anim, fromFontItalic, toFontItalic, progress);
+
+        FontSelector* currentFontSelector = dst->fontCascade().fontSelector();
+        auto description = dst->fontDescription();
+        description.setItalic(blendedFontItalic);
+        description.setFontStyleAxis(blendedStyleAxis);
+        dst->setFontDescription(WTFMove(description));
+        dst->fontCascade().update(currentFontSelector);
+    }
+};
+
 class CSSPropertyAnimationWrapperMap {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -1642,7 +1684,7 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap()
 #endif
         new PropertyWrapper<FontSelectionValue>(CSSPropertyFontWeight, &RenderStyle::fontWeight, &RenderStyle::setFontWeight),
         new PropertyWrapper<FontSelectionValue>(CSSPropertyFontStretch, &RenderStyle::fontStretch, &RenderStyle::setFontStretch),
-        new PropertyWrapper<FontSelectionValue>(CSSPropertyFontStyle, &RenderStyle::fontItalic, &RenderStyle::setFontItalic),
+        new PropertyWrapperFontStyle(),
     };
     const unsigned animatableLonghandPropertiesCount = WTF_ARRAY_LENGTH(animatableLonghandPropertyWrappers);
 
index 5cd7b68..8564db9 100644 (file)
@@ -110,7 +110,7 @@ struct FontDescriptionKey {
         hasher.add(m_size);
         hasher.add(m_fontSelectionRequest.weight);
         hasher.add(m_fontSelectionRequest.width);
-        hasher.add(m_fontSelectionRequest.slope);
+        hasher.add(m_fontSelectionRequest.slope.value_or(normalItalicValue()));
         hasher.add(m_locale.existingHash());
         for (unsigned flagItem : m_flags)
             hasher.add(flagItem);
index 58c0a89..eaa08e0 100644 (file)
@@ -152,7 +152,8 @@ public:
     unsigned familyCount() const { return m_fontDescription.familyCount(); }
     const AtomicString& familyAt(unsigned i) const { return m_fontDescription.familyAt(i); }
 
-    FontSelectionValue italic() const { return m_fontDescription.italic(); }
+    // A std::nullopt return value indicates "font-style: normal".
+    std::optional<FontSelectionValue> italic() const { return m_fontDescription.italic(); }
     FontSelectionValue weight() const { return m_fontDescription.weight(); }
     FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); }
 
index 62befa9..13fcdb3 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     float computedSize() const { return m_computedSize; }
     unsigned computedPixelSize() const { return unsigned(m_computedSize + 0.5f); }
-    FontSelectionValue italic() const { return m_fontSelectionRequest.slope; }
+    std::optional<FontSelectionValue> italic() const { return m_fontSelectionRequest.slope; }
     FontSelectionValue stretch() const { return m_fontSelectionRequest.width; }
     FontSelectionValue weight() const { return m_fontSelectionRequest.weight; }
     FontSelectionRequest fontSelectionRequest() const { return m_fontSelectionRequest; }
@@ -117,9 +117,9 @@ public:
     AllowUserInstalledFonts shouldAllowUserInstalledFonts() const { return static_cast<AllowUserInstalledFonts>(m_shouldAllowUserInstalledFonts); }
 
     void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
-    void setItalic(FontSelectionValue italic) { m_fontSelectionRequest.slope = italic; }
+    void setItalic(std::optional<FontSelectionValue> italic) { m_fontSelectionRequest.slope = italic; }
     void setStretch(FontSelectionValue stretch) { m_fontSelectionRequest.width = stretch; }
-    void setIsItalic(bool i) { setItalic(i ? italicValue() : normalItalicValue()); }
+    void setIsItalic(bool isItalic) { setItalic(isItalic ? std::optional<FontSelectionValue> { italicValue() } : std::optional<FontSelectionValue> { }); }
     void setWeight(FontSelectionValue weight) { m_fontSelectionRequest.weight = weight; }
     void setRenderingMode(FontRenderingMode mode) { m_renderingMode = static_cast<unsigned>(mode); }
     void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = static_cast<unsigned>(rendering); }
@@ -298,7 +298,7 @@ public:
 #endif
 
     // Initial values for font properties.
-    static FontSelectionValue initialItalic() { return normalItalicValue(); }
+    static std::optional<FontSelectionValue> initialItalic() { return std::nullopt; }
     static FontStyleAxis initialFontStyleAxis() { return FontStyleAxis::slnt; }
     static FontSelectionValue initialWeight() { return normalWeightValue(); }
     static FontSelectionValue initialStretch() { return normalStretchValue(); }
index 9979aca..33dc429 100644 (file)
@@ -66,42 +66,43 @@ auto FontSelectionAlgorithm::stretchDistance(Capabilities capabilities) const ->
 auto FontSelectionAlgorithm::styleDistance(Capabilities capabilities) const -> DistanceResult
 {
     auto slope = capabilities.slope;
+    auto requestSlope = m_request.slope.value_or(normalItalicValue());
     ASSERT(slope.isValid());
-    if (slope.includes(m_request.slope))
-        return { FontSelectionValue(), m_request.slope };
-
-    if (m_request.slope >= italicThreshold()) {
-        if (slope.minimum > m_request.slope)
-            return { slope.minimum - m_request.slope, slope.minimum };
-        ASSERT(m_request.slope > slope.maximum);
-        auto threshold = std::max(m_request.slope, m_capabilitiesBounds.slope.maximum);
+    if (slope.includes(requestSlope))
+        return { FontSelectionValue(), requestSlope };
+
+    if (requestSlope >= italicThreshold()) {
+        if (slope.minimum > requestSlope)
+            return { slope.minimum - requestSlope, slope.minimum };
+        ASSERT(requestSlope > slope.maximum);
+        auto threshold = std::max(requestSlope, m_capabilitiesBounds.slope.maximum);
         return { threshold - slope.maximum, slope.maximum };
     }
 
-    if (m_request.slope >= FontSelectionValue()) {
-        if (slope.maximum >= FontSelectionValue() && slope.maximum < m_request.slope)
-            return { m_request.slope - slope.maximum, slope.maximum };
-        if (slope.minimum > m_request.slope)
+    if (requestSlope >= FontSelectionValue()) {
+        if (slope.maximum >= FontSelectionValue() && slope.maximum < requestSlope)
+            return { requestSlope - slope.maximum, slope.maximum };
+        if (slope.minimum > requestSlope)
             return { slope.minimum, slope.minimum };
         ASSERT(slope.maximum < FontSelectionValue());
-        auto threshold = std::max(m_request.slope, m_capabilitiesBounds.slope.maximum);
+        auto threshold = std::max(requestSlope, m_capabilitiesBounds.slope.maximum);
         return { threshold - slope.maximum, slope.maximum };
     }
 
-    if (m_request.slope > -italicThreshold()) {
-        if (slope.minimum > m_request.slope && slope.minimum <= FontSelectionValue())
-            return { slope.minimum - m_request.slope, slope.minimum };
-        if (slope.maximum < m_request.slope)
+    if (requestSlope > -italicThreshold()) {
+        if (slope.minimum > requestSlope && slope.minimum <= FontSelectionValue())
+            return { slope.minimum - requestSlope, slope.minimum };
+        if (slope.maximum < requestSlope)
             return { -slope.maximum, slope.maximum };
         ASSERT(slope.minimum > FontSelectionValue());
-        auto threshold = std::min(m_request.slope, m_capabilitiesBounds.slope.minimum);
+        auto threshold = std::min(requestSlope, m_capabilitiesBounds.slope.minimum);
         return { slope.minimum - threshold, slope.minimum };
     }
 
-    if (slope.maximum < m_request.slope)
-        return { m_request.slope - slope.maximum, slope.maximum };
-    ASSERT(slope.minimum > m_request.slope);
-    auto threshold = std::min(m_request.slope, m_capabilitiesBounds.slope.minimum);
+    if (slope.maximum < requestSlope)
+        return { requestSlope - slope.maximum, slope.maximum };
+    ASSERT(slope.minimum > requestSlope);
+    auto threshold = std::min(requestSlope, m_capabilitiesBounds.slope.minimum);
     return { slope.minimum - threshold, slope.minimum };
 }
 
index b2a582a..bc8bd02 100644 (file)
@@ -30,6 +30,7 @@
 #include <tuple>
 #include <wtf/Hasher.h>
 #include <wtf/Optional.h>
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 
@@ -170,9 +171,9 @@ constexpr FontSelectionValue italicThreshold()
     return FontSelectionValue { 20 };
 }
 
-constexpr bool isItalic(FontSelectionValue fontWeight)
+constexpr bool isItalic(std::optional<FontSelectionValue> fontWeight)
 {
-    return fontWeight >= italicThreshold();
+    return fontWeight && fontWeight.value() >= italicThreshold();
 }
 
 constexpr FontSelectionValue normalItalicValue()
@@ -330,20 +331,38 @@ struct FontSelectionRequest {
 
     Value weight;
     Value width;
-    Value slope;
-
-    constexpr std::tuple<Value, Value, Value> tied() const
+    // FIXME: We are using an optional here to be able to distinguish between an explicit
+    // or implicit slope (for "italic" and "oblique") and the "normal" value which has no
+    // slope. The "italic" and "oblique" values can be distinguished by looking at the
+    // "fontStyleAxis" on the FontDescription. We should come up with a tri-state member
+    // so that it's a lot clearer whether we're dealing with a "normal", "italic" or explicit
+    // "oblique" font style. See webkit.org/b/187774.
+    std::optional<Value> slope;
+
+    std::tuple<Value, Value, std::optional<Value>> tied() const
     {
         return WTF::tie(weight, width, slope);
     }
 };
 
-constexpr bool operator==(const FontSelectionRequest& a, const FontSelectionRequest& b)
+inline TextStream& operator<<(TextStream& ts, const FontSelectionValue& fontSelectionValue)
+{
+    ts << TextStream::FormatNumberRespectingIntegers(fontSelectionValue.rawValue());
+    return ts;
+}
+
+inline TextStream& operator<<(TextStream& ts, const std::optional<FontSelectionValue>& optionalFontSelectionValue)
+{
+    ts << optionalFontSelectionValue.value_or(normalItalicValue());
+    return ts;
+}
+
+inline bool operator==(const FontSelectionRequest& a, const FontSelectionRequest& b)
 {
     return a.tied() == b.tied();
 }
 
-constexpr bool operator!=(const FontSelectionRequest& a, const FontSelectionRequest& b)
+inline bool operator!=(const FontSelectionRequest& a, const FontSelectionRequest& b)
 {
     return !(a == b);
 }
index ff3f87f..0301fd0 100644 (file)
@@ -597,7 +597,7 @@ RetainPtr<CTFontRef> preparePlatformFont(CTFontRef originalFont, const FontDescr
     if (applyWeightWidthSlopeVariations && !fontIsSystemFont(originalFont)) {
         float weight = fontSelectionRequest.weight;
         float width = fontSelectionRequest.width;
-        float slope = fontSelectionRequest.slope;
+        float slope = fontSelectionRequest.slope.value_or(normalItalicValue());
         if (auto weightValue = fontFaceCapabilities.weight)
             weight = std::max(std::min(weight, static_cast<float>(weightValue->maximum)), static_cast<float>(weightValue->minimum));
         if (auto widthValue = fontFaceCapabilities.width)
index e76f46f..bd34253 100644 (file)
@@ -623,7 +623,7 @@ std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDe
     // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't
     // look as nice. That may be solvable though.
     LONG weight = adjustedGDIFontWeight(toGDIFontWeight(fontDescription.weight()), family);
-    auto hfont = createGDIFont(family, weight, fontDescription.italic(),
+    auto hfont = createGDIFont(family, weight, isItalic(fontDescription.italic()),
         fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI);
 
     if (!hfont)
@@ -636,7 +636,7 @@ std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDe
     GetObject(hfont.get(), sizeof(LOGFONT), &logFont);
 
     bool synthesizeBold = isGDIFontWeightBold(weight) && !isGDIFontWeightBold(logFont.lfWeight);
-    bool synthesizeItalic = fontDescription.italic() && !logFont.lfItalic;
+    bool synthesizeItalic = isItalic(fontDescription.italic()) && !logFont.lfItalic;
 
     auto result = std::make_unique<FontPlatformData>(WTFMove(hfont), fontDescription.computedPixelSize(), synthesizeBold, synthesizeItalic, useGDI);
 
index 6623c15..cdd2300 100644 (file)
@@ -1678,7 +1678,7 @@ void RenderStyle::setFontStretch(FontSelectionValue value)
     fontCascade().update(currentFontSelector);
 }
 
-void RenderStyle::setFontItalic(FontSelectionValue value)
+void RenderStyle::setFontItalic(std::optional<FontSelectionValue> value)
 {
     FontSelector* currentFontSelector = fontCascade().fontSelector();
     auto description = fontDescription();
index a10462c..0ce33cd 100644 (file)
@@ -361,7 +361,7 @@ public:
 #endif
     FontSelectionValue fontWeight() const { return fontDescription().weight(); }
     FontSelectionValue fontStretch() const { return fontDescription().stretch(); }
-    FontSelectionValue fontItalic() const { return fontDescription().italic(); }
+    std::optional<FontSelectionValue> fontItalic() const { return fontDescription().italic(); }
 
     const Length& textIndent() const { return m_rareInheritedData->indent; }
     TextAlignMode textAlign() const { return static_cast<TextAlignMode>(m_inheritedFlags.textAlign); }
@@ -910,7 +910,7 @@ public:
 #endif
     void setFontWeight(FontSelectionValue);
     void setFontStretch(FontSelectionValue);
-    void setFontItalic(FontSelectionValue);
+    void setFontItalic(std::optional<FontSelectionValue>);
 
     void setColor(const Color&);
     void setTextIndent(Length&& length) { SET_VAR(m_rareInheritedData, indent, WTFMove(length)); }
index 3ff42f3..49e1ef5 100644 (file)
@@ -1,3 +1,15 @@
+2018-07-18  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Interpolation between font-styles with a keyword value should be discrete
+        https://bugs.webkit.org/show_bug.cgi?id=187722
+
+        Reviewed by Myles Maxfield.
+
+        Use isItalic() since that function knows how to handle an std::optional<FontSelectionValue>.
+
+        * DOMCoreClasses.cpp:
+        (DOMElement::font):
+
 2018-07-10  Ryosuke Niwa  <rniwa@webkit.org>
 
         Disable cross-origin-window-policy by default
index b25261f..6e4016c 100644 (file)
@@ -1295,7 +1295,7 @@ HRESULT DOMElement::font(_Out_ WebFontDescription* webFontDescription)
     webFontDescription->familyLength = family.length();
     webFontDescription->size = fontDescription.computedSize();
     webFontDescription->bold = isFontWeightBold(fontDescription.weight());
-    webFontDescription->italic = fontDescription.italic();
+    webFontDescription->italic = isItalic(fontDescription.italic());
 
     return S_OK;
 }