Changeset 190192 in webkit


Ignore:
Timestamp:
Sep 23, 2015 5:40:53 PM (9 years ago)
Author:
mmaxfield@apple.com
Message:

[Cocoa] [Font Features] Implement font-variant-*
https://bugs.webkit.org/show_bug.cgi?id=148413

Reviewed by Darin Adler.

Source/WebCore:

This patch is the first pass of implementing of the font-variant-* properties. Specifically,
these properties are:
font-variant-ligatures
font-variant-position
font-variant-caps
font-variant-numeric
font-variant-alternates
font-variant-east-asian

These new properties are held inside FontDescription as bit fields. At font creation time,
we consult with the FontDescription to figure out which variants are specified. We then
convert those variants to font features, and resolve these font features with the additional
features specified by font-feature-settings (as the spec requires). This patch also makes
our caches sensitive to these new properties of FontDescription so we don't look up cached,
stale fonts.

The implementation has some caveats, however. They are listed here:

  1. These new properties need to interact correctly with @font-face declarations. In

particular, only certain properties of the FontDescription should be considered when
detecting if a @font-face declaration applies to a particular element. This discrimination
does not happen correctly. In addition, any feature-specific CSS properties inside the
@font-face declaration need to be consulted at a particular point during the feature
resolve. This does not currently occur.

  1. One of the properties, font-variant-alternates, has a few values which require custom

CSS functions, which makes modeling the properties as bit fields tricky. These extra values
need to be implemented. This patch implements all the values which do not require extra CSS
features.

  1. These new properties have a shorthand, font-variant, which is designed to be backward-

compatible with CSS 2.1's concept of font-variant. In particular, CSS 2.1 allows you to use
"normal" and "small-caps" with font-variant. Both of these values are values of the new
property font-variant-caps. However, our existing implementation of small-caps does not
use font features when they exist; instead, it simply draws text at a smaller font size and
uses (effectively) text-transform to force capital letters. This implementation needs to be
unified with the new font-variant-caps property so that we can expand font-variant to be
a shorthand for the new properties.

  1. font-variant-position and font-variant-caps should provide appropriate synthesis if no

matching font-feature exists.

  1. FontCascade::typesettingFeatures() is now no-longer accurate. Fixing this would be large

enough to warrant its own patch.

  1. These properties are not tested with TrueType fonts.

Tests: css3/font-variant-all-webfont.html

css3/font-variant-parsing.html

  • css/CSSComputedStyleDeclaration.cpp: Reconstruct StyleProperties from a RenderStyle.

(WebCore::appendLigaturesValue):
(WebCore::fontVariantLigaturesPropertyValue):
(WebCore::fontVariantPositionPropertyValue):
(WebCore::fontVariantCapsPropertyValue):
(WebCore::fontVariantNumericPropertyValue):
(WebCore::fontVariantAlternatesPropertyValue):
(WebCore::fontVariantEastAsianPropertyValue):
(WebCore::ComputedStyleExtractor::propertyValue):

  • css/CSSFontFeatureValue.cpp: Update to FontFeatureTag instead of WTF::String.

(WebCore::CSSFontFeatureValue::CSSFontFeatureValue):
(WebCore::CSSFontFeatureValue::customCSSText):

  • css/CSSFontFeatureValue.h: Ditto.

(WebCore::CSSFontFeatureValue::create):
(WebCore::CSSFontFeatureValue::tag):

  • css/CSSParser.cpp: Parse the new properties according to the CSS3 fonts spec.

(WebCore::isValidKeywordPropertyAndValue):
(WebCore::isKeywordPropertyID):
(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseFontFeatureTag):
(WebCore::CSSParser::parseFontVariantLigatures):
(WebCore::CSSParser::parseFontVariantNumeric):
(WebCore::CSSParser::parseFontVariantEastAsian):

  • css/CSSParser.h:
  • css/CSSPrimitiveValueMappings.h: For the three properties which are simple keyword value

properties, implement casting operators to automatically convert between RenderStyle
objects and CSS property objects.
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
(WebCore::CSSPrimitiveValue::operator FontVariantPosition):
(WebCore::CSSPrimitiveValue::operator FontVariantCaps):
(WebCore::CSSPrimitiveValue::operator FontVariantAlternates):

  • css/CSSPropertyNames.in: New properties.
  • css/CSSValueKeywords.in: New values.
  • css/StyleBuilderConverter.h:

(WebCore::StyleBuilderConverter::convertFontFeatureSettings): Update to not use
RefPtrs.

  • css/StyleBuilderCustom.h: Properties which are not simple keyword value properties are

decomposed into multiple members of FontDescription. These properties exist to convert
between these aggregate members and the CSS properties.
(WebCore::StyleBuilderCustom::applyInheritFontVariantLigatures):
(WebCore::StyleBuilderCustom::applyInitialFontVariantLigatures):
(WebCore::StyleBuilderCustom::applyValueFontVariantLigatures):
(WebCore::StyleBuilderCustom::applyInheritFontVariantNumeric):
(WebCore::StyleBuilderCustom::applyInitialFontVariantNumeric):
(WebCore::StyleBuilderCustom::applyValueFontVariantNumeric):
(WebCore::StyleBuilderCustom::applyInheritFontVariantEastAsian):
(WebCore::StyleBuilderCustom::applyInitialFontVariantEastAsian):
(WebCore::StyleBuilderCustom::applyValueFontVariantEastAsian):
(WebCore::StyleBuilderCustom::applyInitialWebkitFontVariantLigatures): Deleted.
(WebCore::StyleBuilderCustom::applyInheritWebkitFontVariantLigatures): Deleted.
(WebCore::StyleBuilderCustom::applyValueWebkitFontVariantLigatures): Deleted.

  • editing/cocoa/HTMLConverter.mm:

(HTMLConverter::computedAttributesForElement): Unprefix font-variant-ligatures.

  • platform/graphics/FontCache.h: Update cache to be sensitive to new state in

FontDescription.
(WebCore::FontDescriptionKey::FontDescriptionKey):
(WebCore::FontDescriptionKey::operator==):
(WebCore::FontDescriptionKey::computeHash):
(WebCore::FontDescriptionKey::makeFlagsKey):
(WebCore::FontDescriptionKey::makeFlagKey): Deleted.

  • platform/graphics/FontCascade.cpp:

(WebCore::FontCascade::codePath): These new variants should trigger the complex text
codepath.

  • platform/graphics/FontCascade.h:

(WebCore::FontCascade::computeTypesettingFeatures): Update to use new state enum.

  • platform/graphics/FontDescription.cpp: Add state to hold new property values.

(WebCore::FontDescription::FontDescription):
(WebCore::FontCascadeDescription::FontCascadeDescription): Deleted.

  • platform/graphics/FontDescription.h: Add state to hold new property values.

(WebCore::FontDescription::featureSettings):
(WebCore::FontDescription::variantCommonLigatures):
(WebCore::FontDescription::variantDiscretionaryLigatures):
(WebCore::FontDescription::variantHistoricalLigatures):
(WebCore::FontDescription::variantContextualAlternates):
(WebCore::FontDescription::variantPosition):
(WebCore::FontDescription::variantCaps):
(WebCore::FontDescription::variantNumericFigure):
(WebCore::FontDescription::variantNumericSpacing):
(WebCore::FontDescription::variantNumericFraction):
(WebCore::FontDescription::variantNumericOrdinal):
(WebCore::FontDescription::variantNumericSlashedZero):
(WebCore::FontDescription::variantAlternates):
(WebCore::FontDescription::variantEastAsianVariant):
(WebCore::FontDescription::variantEastAsianWidth):
(WebCore::FontDescription::variantEastAsianRuby):
(WebCore::FontDescription::variantSettings):
(WebCore::FontDescription::setFeatureSettings):
(WebCore::FontDescription::setVariantCommonLigatures):
(WebCore::FontDescription::setVariantDiscretionaryLigatures):
(WebCore::FontDescription::setVariantHistoricalLigatures):
(WebCore::FontDescription::setVariantContextualAlternates):
(WebCore::FontDescription::setVariantPosition):
(WebCore::FontDescription::setVariantCaps):
(WebCore::FontDescription::setVariantNumericFigure):
(WebCore::FontDescription::setVariantNumericSpacing):
(WebCore::FontDescription::setVariantNumericFraction):
(WebCore::FontDescription::setVariantNumericOrdinal):
(WebCore::FontDescription::setVariantNumericSlashedZero):
(WebCore::FontDescription::setVariantAlternates):
(WebCore::FontDescription::setVariantEastAsianVariant):
(WebCore::FontDescription::setVariantEastAsianWidth):
(WebCore::FontDescription::setVariantEastAsianRuby):
(WebCore::FontDescription::operator==):
(WebCore::FontCascadeDescription::initialVariantPosition):
(WebCore::FontCascadeDescription::initialVariantCaps):
(WebCore::FontCascadeDescription::initialVariantAlternates):
(WebCore::FontCascadeDescription::commonLigaturesState): Deleted.
(WebCore::FontCascadeDescription::discretionaryLigaturesState): Deleted.
(WebCore::FontCascadeDescription::historicalLigaturesState): Deleted.
(WebCore::FontCascadeDescription::setCommonLigaturesState): Deleted.
(WebCore::FontCascadeDescription::setDiscretionaryLigaturesState): Deleted.
(WebCore::FontCascadeDescription::setHistoricalLigaturesState): Deleted.
(WebCore::FontCascadeDescription::operator==): Deleted.

  • platform/graphics/FontFeatureSettings.cpp: Update to use FontFeatureTag instead of

WTF::String.
(WebCore::FontFeature::FontFeature):
(WebCore::FontFeature::operator==):
(WebCore::FontFeature::operator<):
(WebCore::FontFeatureSettings::hash):
(WebCore::FontFeatureSettings::create): Deleted.

  • platform/graphics/FontFeatureSettings.h: Update to use FontFeatureTag instead of

WTF::String.
(WebCore::fontFeatureTag):
(WebCore::FontFeatureTagHash::hash):
(WebCore::FontFeatureTagHash::equal):
(WebCore::FontFeatureTagHashTraits::constructDeletedValue):
(WebCore::FontFeatureTagHashTraits::isDeletedValue):
(WebCore::FontFeature::tag):
(WebCore::FontFeatureSettings::operator==):
(WebCore::FontFeatureSettings::begin):
(WebCore::FontFeatureSettings::end):
(WebCore::FontFeatureSettings::FontFeatureSettings): Deleted.

  • platform/graphics/cocoa/FontCacheCoreText.cpp: Ditto. Also, when computing font

features, consult with the state inside FontDescription.
(WebCore::tagEquals):
(WebCore::appendTrueTypeFeature):
(WebCore::appendOpenTypeFeature):
(WebCore::computeFeatureSettingsFromVariants):
(WebCore::preparePlatformFont):
(WebCore::platformFontLookupWithFamily):
(WebCore::fontWithFamily):
(WebCore::FontCache::createFontPlatformData):
(WebCore::FontCache::systemFallbackForCharacters):

  • platform/graphics/harfbuzz/HarfBuzzShaper.cpp: Update to use references instead of

pointers.
(WebCore::HarfBuzzShaper::setFontFeatures):

  • platform/graphics/mac/FontCacheMac.mm:

(WebCore::platformFontWithFamily): Ditto.

  • platform/graphics/mac/FontCustomPlatformData.cpp:

(WebCore::FontCustomPlatformData::fontPlatformData): Be sensitive to new state inside FontDescription.

  • platform/text/TextFlags.h:

(WebCore::FontVariantSettings::isAllNormal): New state enums.

  • rendering/RenderThemeIOS.mm:

(WebCore::RenderThemeIOS::updateCachedSystemFontDescription): Be sensitive to new state inside
FontDescription.

  • rendering/line/BreakingContext.h:

Tools:

Update test font to use "lnum" feature.

  • FontWithFeatures/FontWithFeatures/FontCreator.cpp:

(Generator::appendGSUBTable):

LayoutTests:

Updating tests because font-variant-ligatures is being unprefixed.

Also, update css3/resources/FontWithFeatures.otf to support "lnum" feature.

  • css3/font-feature-settings-rendering-2-expected.html:
  • css3/font-feature-settings-rendering-2.html:
  • css3/font-variant-all-webfont-expected.html: Added.
  • css3/font-variant-all-webfont.html: Added.
  • css3/font-variant-parsing-expected.txt: Added.
  • css3/font-variant-parsing.html: Added.
  • css3/resources/FontWithFeatures.otf:
  • fast/css/getComputedStyle/computed-style-expected.txt:
  • fast/css/getComputedStyle/computed-style-font-family-expected.txt:
  • fast/css/getComputedStyle/computed-style-without-renderer-expected.txt:
  • fast/css/getComputedStyle/resources/property-names.js:
  • fast/css/parsing-font-variant-ligatures.html:
  • fast/text/font-variant-ligatures.html:
  • platform/mac/TestExpectations:
  • svg/css/getComputedStyle-basic-expected.txt:
Location:
trunk
Files:
4 added
40 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r190190 r190192  
     12015-09-23  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] [Font Features] Implement font-variant-*
     4        https://bugs.webkit.org/show_bug.cgi?id=148413
     5
     6        Reviewed by Darin Adler.
     7
     8        Updating tests because font-variant-ligatures is being unprefixed.
     9
     10        Also, update css3/resources/FontWithFeatures.otf to support "lnum" feature.
     11
     12        * css3/font-feature-settings-rendering-2-expected.html:
     13        * css3/font-feature-settings-rendering-2.html:
     14        * css3/font-variant-all-webfont-expected.html: Added.
     15        * css3/font-variant-all-webfont.html: Added.
     16        * css3/font-variant-parsing-expected.txt: Added.
     17        * css3/font-variant-parsing.html: Added.
     18        * css3/resources/FontWithFeatures.otf:
     19        * fast/css/getComputedStyle/computed-style-expected.txt:
     20        * fast/css/getComputedStyle/computed-style-font-family-expected.txt:
     21        * fast/css/getComputedStyle/computed-style-without-renderer-expected.txt:
     22        * fast/css/getComputedStyle/resources/property-names.js:
     23        * fast/css/parsing-font-variant-ligatures.html:
     24        * fast/text/font-variant-ligatures.html:
     25        * platform/mac/TestExpectations:
     26        * svg/css/getComputedStyle-basic-expected.txt:
     27
    1282015-09-23  Chris Dumez  <cdumez@apple.com>
    229
  • trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html

    r189890 r190192  
    4242<span style="font-family: FontFeaturesTest;">BA</span>
    4343<span style="font-family: FontFeaturesTest;">BA</span>
     44<span style="font-family: FontFeaturesTest;">BA</span>
    4445</div>
    4546</body>
  • trunk/LayoutTests/css3/font-feature-settings-rendering-2.html

    r189890 r190192  
    3939addElement("unic", "N");
    4040addElement("titl", "O");
    41 addElement("onum", "P");
    42 addElement("pnum", "Q");
    43 addElement("tnum", "R");
    44 addElement("frac", "S");
    45 //addElement("afrc", "T");
    46 addElement("ordn", "U");
    47 addElement("zero", "V");
    48 addElement("hist", "W");
    49 addElement("jp78", "X");
    50 addElement("jp83", "Y");
    51 addElement("jp90", "Z");
    52 addElement("jp04", "a");
    53 addElement("smpl", "b");
    54 addElement("trad", "c");
    55 addElement("fwid", "d");
    56 addElement("pwid", "e");
    57 addElement("ruby", "f");
     41addElement("lnum", "P");
     42addElement("onum", "Q");
     43addElement("pnum", "R");
     44addElement("tnum", "S");
     45addElement("frac", "T");
     46//addElement("afrc", "U");
     47addElement("ordn", "V");
     48addElement("zero", "W");
     49addElement("hist", "X");
     50addElement("jp78", "Y");
     51addElement("jp83", "Z");
     52addElement("jp90", "a");
     53addElement("jp04", "b");
     54addElement("smpl", "c");
     55addElement("trad", "d");
     56addElement("fwid", "e");
     57addElement("pwid", "f");
     58addElement("ruby", "g");
    5859</script>
    5960</body>
  • trunk/LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt

    r189646 r190192  
    160160-webkit-font-kerning: auto;
    161161-webkit-font-smoothing: auto;
    162 -webkit-font-variant-ligatures: normal;
     162font-variant-ligatures: normal;
     163font-variant-position: normal;
     164font-variant-caps: normal;
     165font-variant-numeric: normal;
     166font-variant-alternates: normal;
     167font-variant-east-asian: normal;
    163168-webkit-grid-auto-columns: auto;
    164169-webkit-grid-auto-flow: row;
  • trunk/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt

    r184869 r190192  
    77font-variant: normal;
    88font-weight: normal;
     9font-variant-ligatures: normal;
     10font-variant-position: normal;
     11font-variant-caps: normal;
     12font-variant-numeric: normal;
     13font-variant-alternates: normal;
     14font-variant-east-asian: normal;
    915
  • trunk/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-expected.txt

    r189646 r190192  
    159159-webkit-font-kerning: auto
    160160-webkit-font-smoothing: auto
    161 -webkit-font-variant-ligatures: normal
     161font-variant-ligatures: normal
     162font-variant-position: normal
     163font-variant-caps: normal
     164font-variant-numeric: normal
     165font-variant-alternates: normal
     166font-variant-east-asian: normal
    162167-webkit-grid-auto-columns: auto
    163168-webkit-grid-auto-flow: row
  • trunk/LayoutTests/fast/css/getComputedStyle/resources/property-names.js

    r188202 r190192  
    4949    "-webkit-font-kerning": true,
    5050    "-webkit-font-smoothing": true,
    51     "-webkit-font-variant-ligatures": true,
    5251    "-webkit-grid-auto-columns": true,
    5352    "-webkit-grid-auto-flow": true,
     
    185184    "font-synthesis": true,
    186185    "font-variant": true,
     186    "font-variant-ligatures": true,
     187    "font-variant-position": true,
     188    "font-variant-caps": true,
     189    "font-variant-numeric": true,
     190    "font-variant-alternates": true,
     191    "font-variant-east-asian": true,
    187192    "font-weight": true,
    188193    "glyph-orientation-horizontal": true,
  • trunk/LayoutTests/fast/css/parsing-font-variant-ligatures.html

    r120683 r190192  
    1212    {
    1313        var element = document.createElement("div");
    14         element.style.setProperty("-webkit-font-variant-ligatures", value);
    15         var cssText = element.style.webkitFontVariantLigatures;
     14        element.style.setProperty("font-variant-ligatures", value);
     15        var cssText = element.style.fontVariantLigatures;
    1616        document.body.appendChild(element);
    17         var computedCSSText = getComputedStyle(element).webkitFontVariantLigatures;
     17        var computedCSSText = getComputedStyle(element).fontVariantLigatures;
    1818        document.body.removeChild(element);
    1919        if (cssText === expectedCSSText && computedCSSText == expectedComputedCSSText)
  • trunk/LayoutTests/fast/text/font-variant-ligatures.html

    r104786 r190192  
    11<style>
    2     .common-ligatures-disabled { -webkit-font-variant-ligatures: no-common-ligatures; }
    3     .common-ligatures-enabled { -webkit-font-variant-ligatures: common-ligatures; }
    4     .common-ligatures-normal { -webkit-font-variant-ligatures: normal; }
     2    .common-ligatures-disabled { font-variant-ligatures: no-common-ligatures; }
     3    .common-ligatures-enabled { font-variant-ligatures: common-ligatures; }
     4    .common-ligatures-normal { font-variant-ligatures: normal; }
    55</style>
    66<body style="font-size: 36px;">
  • trunk/LayoutTests/platform/mac/TestExpectations

    r190183 r190192  
    263263
    264264webkit.org/b/149246 [ Mavericks ] css3/font-feature-settings-rendering-2.html
     265webkit.org/b/149246 [ Mavericks ] css3/font-variant-all-webfont.html
     266webkit.org/b/149246 [ Mavericks ] css3/font-variant-parsing.html
    265267
    266268# This feature is disabled on Mavericks.
  • trunk/LayoutTests/svg/css/getComputedStyle-basic-expected.txt

    r189646 r190192  
    317317rect: style.getPropertyValue(-webkit-font-smoothing) : auto
    318318rect: style.getPropertyCSSValue(-webkit-font-smoothing) : [object CSSPrimitiveValue]
    319 rect: style.getPropertyValue(-webkit-font-variant-ligatures) : normal
    320 rect: style.getPropertyCSSValue(-webkit-font-variant-ligatures) : [object CSSPrimitiveValue]
     319rect: style.getPropertyValue(font-variant-ligatures) : normal
     320rect: style.getPropertyCSSValue(font-variant-ligatures) : [object CSSPrimitiveValue]
     321rect: style.getPropertyValue(font-variant-position) : normal
     322rect: style.getPropertyCSSValue(font-variant-position) : [object CSSPrimitiveValue]
     323rect: style.getPropertyValue(font-variant-caps) : normal
     324rect: style.getPropertyCSSValue(font-variant-caps) : [object CSSPrimitiveValue]
     325rect: style.getPropertyValue(font-variant-numeric) : normal
     326rect: style.getPropertyCSSValue(font-variant-numeric) : [object CSSPrimitiveValue]
     327rect: style.getPropertyValue(font-variant-alternates) : normal
     328rect: style.getPropertyCSSValue(font-variant-alternates) : [object CSSPrimitiveValue]
     329rect: style.getPropertyValue(font-variant-east-asian) : normal
     330rect: style.getPropertyCSSValue(font-variant-east-asian) : [object CSSPrimitiveValue]
    321331rect: style.getPropertyValue(-webkit-grid-auto-columns) : auto
    322332rect: style.getPropertyCSSValue(-webkit-grid-auto-columns) : [object CSSPrimitiveValue]
     
    841851g: style.getPropertyValue(-webkit-font-smoothing) : auto
    842852g: style.getPropertyCSSValue(-webkit-font-smoothing) : [object CSSPrimitiveValue]
    843 g: style.getPropertyValue(-webkit-font-variant-ligatures) : normal
    844 g: style.getPropertyCSSValue(-webkit-font-variant-ligatures) : [object CSSPrimitiveValue]
     853g: style.getPropertyValue(font-variant-ligatures) : normal
     854g: style.getPropertyCSSValue(font-variant-ligatures) : [object CSSPrimitiveValue]
     855g: style.getPropertyValue(font-variant-position) : normal
     856g: style.getPropertyCSSValue(font-variant-position) : [object CSSPrimitiveValue]
     857g: style.getPropertyValue(font-variant-caps) : normal
     858g: style.getPropertyCSSValue(font-variant-caps) : [object CSSPrimitiveValue]
     859g: style.getPropertyValue(font-variant-numeric) : normal
     860g: style.getPropertyCSSValue(font-variant-numeric) : [object CSSPrimitiveValue]
     861g: style.getPropertyValue(font-variant-alternates) : normal
     862g: style.getPropertyCSSValue(font-variant-alternates) : [object CSSPrimitiveValue]
     863g: style.getPropertyValue(font-variant-east-asian) : normal
     864g: style.getPropertyCSSValue(font-variant-east-asian) : [object CSSPrimitiveValue]
    845865g: style.getPropertyValue(-webkit-grid-auto-columns) : auto
    846866g: style.getPropertyCSSValue(-webkit-grid-auto-columns) : [object CSSPrimitiveValue]
  • trunk/Source/WebCore/ChangeLog

    r190190 r190192  
     12015-09-23  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] [Font Features] Implement font-variant-*
     4        https://bugs.webkit.org/show_bug.cgi?id=148413
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch is the first pass of implementing of the font-variant-* properties. Specifically,
     9        these properties are:
     10        font-variant-ligatures
     11        font-variant-position
     12        font-variant-caps
     13        font-variant-numeric
     14        font-variant-alternates
     15        font-variant-east-asian
     16
     17        These new properties are held inside FontDescription as bit fields. At font creation time,
     18        we consult with the FontDescription to figure out which variants are specified. We then
     19        convert those variants to font features, and resolve these font features with the additional
     20        features specified by font-feature-settings (as the spec requires). This patch also makes
     21        our caches sensitive to these new properties of FontDescription so we don't look up cached,
     22        stale fonts.
     23
     24        The implementation has some caveats, however. They are listed here:
     25        1. These new properties need to interact correctly with @font-face declarations. In
     26        particular, only certain properties of the FontDescription should be considered when
     27        detecting if a @font-face declaration applies to a particular element. This discrimination
     28        does not happen correctly. In addition, any feature-specific CSS properties inside the
     29        @font-face declaration need to be consulted at a particular point during the feature
     30        resolve. This does not currently occur.
     31        2. One of the properties, font-variant-alternates, has a few values which require custom
     32        CSS functions, which makes modeling the properties as bit fields tricky. These extra values
     33        need to be implemented. This patch implements all the values which do not require extra CSS
     34        features.
     35        3. These new properties have a shorthand, font-variant, which is designed to be backward-
     36        compatible with CSS 2.1's concept of font-variant. In particular, CSS 2.1 allows you to use
     37        "normal" and "small-caps" with font-variant. Both of these values are values of the new
     38        property font-variant-caps. However, our existing implementation of small-caps does not
     39        use font features when they exist; instead, it simply draws text at a smaller font size and
     40        uses (effectively) text-transform to force capital letters. This implementation needs to be
     41        unified with the new font-variant-caps property so that we can expand font-variant to be
     42        a shorthand for the new properties.
     43        4. font-variant-position and font-variant-caps should provide appropriate synthesis if no
     44        matching font-feature exists.
     45        5. FontCascade::typesettingFeatures() is now no-longer accurate. Fixing this would be large
     46        enough to warrant its own patch.
     47        6. These properties are not tested with TrueType fonts.
     48
     49        Tests: css3/font-variant-all-webfont.html
     50               css3/font-variant-parsing.html
     51
     52        * css/CSSComputedStyleDeclaration.cpp: Reconstruct StyleProperties from a RenderStyle.
     53        (WebCore::appendLigaturesValue):
     54        (WebCore::fontVariantLigaturesPropertyValue):
     55        (WebCore::fontVariantPositionPropertyValue):
     56        (WebCore::fontVariantCapsPropertyValue):
     57        (WebCore::fontVariantNumericPropertyValue):
     58        (WebCore::fontVariantAlternatesPropertyValue):
     59        (WebCore::fontVariantEastAsianPropertyValue):
     60        (WebCore::ComputedStyleExtractor::propertyValue):
     61        * css/CSSFontFeatureValue.cpp: Update to FontFeatureTag instead of WTF::String.
     62        (WebCore::CSSFontFeatureValue::CSSFontFeatureValue):
     63        (WebCore::CSSFontFeatureValue::customCSSText):
     64        * css/CSSFontFeatureValue.h: Ditto.
     65        (WebCore::CSSFontFeatureValue::create):
     66        (WebCore::CSSFontFeatureValue::tag):
     67        * css/CSSParser.cpp: Parse the new properties according to the CSS3 fonts spec.
     68        (WebCore::isValidKeywordPropertyAndValue):
     69        (WebCore::isKeywordPropertyID):
     70        (WebCore::CSSParser::parseValue):
     71        (WebCore::CSSParser::parseFontFeatureTag):
     72        (WebCore::CSSParser::parseFontVariantLigatures):
     73        (WebCore::CSSParser::parseFontVariantNumeric):
     74        (WebCore::CSSParser::parseFontVariantEastAsian):
     75        * css/CSSParser.h:
     76        * css/CSSPrimitiveValueMappings.h: For the three properties which are simple keyword value
     77        properties, implement casting operators to automatically convert between RenderStyle
     78        objects and CSS property objects.
     79        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
     80        (WebCore::CSSPrimitiveValue::operator FontVariantPosition):
     81        (WebCore::CSSPrimitiveValue::operator FontVariantCaps):
     82        (WebCore::CSSPrimitiveValue::operator FontVariantAlternates):
     83        * css/CSSPropertyNames.in: New properties.
     84        * css/CSSValueKeywords.in: New values.
     85        * css/StyleBuilderConverter.h:
     86        (WebCore::StyleBuilderConverter::convertFontFeatureSettings): Update to not use
     87        RefPtrs.
     88        * css/StyleBuilderCustom.h: Properties which are not simple keyword value properties are
     89        decomposed into multiple members of FontDescription. These properties exist to convert
     90        between these aggregate members and the CSS properties.
     91        (WebCore::StyleBuilderCustom::applyInheritFontVariantLigatures):
     92        (WebCore::StyleBuilderCustom::applyInitialFontVariantLigatures):
     93        (WebCore::StyleBuilderCustom::applyValueFontVariantLigatures):
     94        (WebCore::StyleBuilderCustom::applyInheritFontVariantNumeric):
     95        (WebCore::StyleBuilderCustom::applyInitialFontVariantNumeric):
     96        (WebCore::StyleBuilderCustom::applyValueFontVariantNumeric):
     97        (WebCore::StyleBuilderCustom::applyInheritFontVariantEastAsian):
     98        (WebCore::StyleBuilderCustom::applyInitialFontVariantEastAsian):
     99        (WebCore::StyleBuilderCustom::applyValueFontVariantEastAsian):
     100        (WebCore::StyleBuilderCustom::applyInitialWebkitFontVariantLigatures): Deleted.
     101        (WebCore::StyleBuilderCustom::applyInheritWebkitFontVariantLigatures): Deleted.
     102        (WebCore::StyleBuilderCustom::applyValueWebkitFontVariantLigatures): Deleted.
     103        * editing/cocoa/HTMLConverter.mm:
     104        (HTMLConverter::computedAttributesForElement): Unprefix font-variant-ligatures.
     105        * platform/graphics/FontCache.h: Update cache to be sensitive to new state in
     106        FontDescription.
     107        (WebCore::FontDescriptionKey::FontDescriptionKey):
     108        (WebCore::FontDescriptionKey::operator==):
     109        (WebCore::FontDescriptionKey::computeHash):
     110        (WebCore::FontDescriptionKey::makeFlagsKey):
     111        (WebCore::FontDescriptionKey::makeFlagKey): Deleted.
     112        * platform/graphics/FontCascade.cpp:
     113        (WebCore::FontCascade::codePath): These new variants should trigger the complex text
     114        codepath.
     115        * platform/graphics/FontCascade.h:
     116        (WebCore::FontCascade::computeTypesettingFeatures): Update to use new state enum.
     117        * platform/graphics/FontDescription.cpp: Add state to hold new property values.
     118        (WebCore::FontDescription::FontDescription):
     119        (WebCore::FontCascadeDescription::FontCascadeDescription): Deleted.
     120        * platform/graphics/FontDescription.h: Add state to hold new property values.
     121        (WebCore::FontDescription::featureSettings):
     122        (WebCore::FontDescription::variantCommonLigatures):
     123        (WebCore::FontDescription::variantDiscretionaryLigatures):
     124        (WebCore::FontDescription::variantHistoricalLigatures):
     125        (WebCore::FontDescription::variantContextualAlternates):
     126        (WebCore::FontDescription::variantPosition):
     127        (WebCore::FontDescription::variantCaps):
     128        (WebCore::FontDescription::variantNumericFigure):
     129        (WebCore::FontDescription::variantNumericSpacing):
     130        (WebCore::FontDescription::variantNumericFraction):
     131        (WebCore::FontDescription::variantNumericOrdinal):
     132        (WebCore::FontDescription::variantNumericSlashedZero):
     133        (WebCore::FontDescription::variantAlternates):
     134        (WebCore::FontDescription::variantEastAsianVariant):
     135        (WebCore::FontDescription::variantEastAsianWidth):
     136        (WebCore::FontDescription::variantEastAsianRuby):
     137        (WebCore::FontDescription::variantSettings):
     138        (WebCore::FontDescription::setFeatureSettings):
     139        (WebCore::FontDescription::setVariantCommonLigatures):
     140        (WebCore::FontDescription::setVariantDiscretionaryLigatures):
     141        (WebCore::FontDescription::setVariantHistoricalLigatures):
     142        (WebCore::FontDescription::setVariantContextualAlternates):
     143        (WebCore::FontDescription::setVariantPosition):
     144        (WebCore::FontDescription::setVariantCaps):
     145        (WebCore::FontDescription::setVariantNumericFigure):
     146        (WebCore::FontDescription::setVariantNumericSpacing):
     147        (WebCore::FontDescription::setVariantNumericFraction):
     148        (WebCore::FontDescription::setVariantNumericOrdinal):
     149        (WebCore::FontDescription::setVariantNumericSlashedZero):
     150        (WebCore::FontDescription::setVariantAlternates):
     151        (WebCore::FontDescription::setVariantEastAsianVariant):
     152        (WebCore::FontDescription::setVariantEastAsianWidth):
     153        (WebCore::FontDescription::setVariantEastAsianRuby):
     154        (WebCore::FontDescription::operator==):
     155        (WebCore::FontCascadeDescription::initialVariantPosition):
     156        (WebCore::FontCascadeDescription::initialVariantCaps):
     157        (WebCore::FontCascadeDescription::initialVariantAlternates):
     158        (WebCore::FontCascadeDescription::commonLigaturesState): Deleted.
     159        (WebCore::FontCascadeDescription::discretionaryLigaturesState): Deleted.
     160        (WebCore::FontCascadeDescription::historicalLigaturesState): Deleted.
     161        (WebCore::FontCascadeDescription::setCommonLigaturesState): Deleted.
     162        (WebCore::FontCascadeDescription::setDiscretionaryLigaturesState): Deleted.
     163        (WebCore::FontCascadeDescription::setHistoricalLigaturesState): Deleted.
     164        (WebCore::FontCascadeDescription::operator==): Deleted.
     165        * platform/graphics/FontFeatureSettings.cpp: Update to use FontFeatureTag instead of
     166        WTF::String.
     167        (WebCore::FontFeature::FontFeature):
     168        (WebCore::FontFeature::operator==):
     169        (WebCore::FontFeature::operator<):
     170        (WebCore::FontFeatureSettings::hash):
     171        (WebCore::FontFeatureSettings::create): Deleted.
     172        * platform/graphics/FontFeatureSettings.h: Update to use FontFeatureTag instead of
     173        WTF::String.
     174        (WebCore::fontFeatureTag):
     175        (WebCore::FontFeatureTagHash::hash):
     176        (WebCore::FontFeatureTagHash::equal):
     177        (WebCore::FontFeatureTagHashTraits::constructDeletedValue):
     178        (WebCore::FontFeatureTagHashTraits::isDeletedValue):
     179        (WebCore::FontFeature::tag):
     180        (WebCore::FontFeatureSettings::operator==):
     181        (WebCore::FontFeatureSettings::begin):
     182        (WebCore::FontFeatureSettings::end):
     183        (WebCore::FontFeatureSettings::FontFeatureSettings): Deleted.
     184        * platform/graphics/cocoa/FontCacheCoreText.cpp: Ditto. Also, when computing font
     185        features, consult with the state inside FontDescription.
     186        (WebCore::tagEquals):
     187        (WebCore::appendTrueTypeFeature):
     188        (WebCore::appendOpenTypeFeature):
     189        (WebCore::computeFeatureSettingsFromVariants):
     190        (WebCore::preparePlatformFont):
     191        (WebCore::platformFontLookupWithFamily):
     192        (WebCore::fontWithFamily):
     193        (WebCore::FontCache::createFontPlatformData):
     194        (WebCore::FontCache::systemFallbackForCharacters):
     195        * platform/graphics/harfbuzz/HarfBuzzShaper.cpp: Update to use references instead of
     196        pointers.
     197        (WebCore::HarfBuzzShaper::setFontFeatures):
     198        * platform/graphics/mac/FontCacheMac.mm:
     199        (WebCore::platformFontWithFamily): Ditto.
     200        * platform/graphics/mac/FontCustomPlatformData.cpp:
     201        (WebCore::FontCustomPlatformData::fontPlatformData): Be sensitive to new state inside FontDescription.
     202        * platform/text/TextFlags.h:
     203        (WebCore::FontVariantSettings::isAllNormal): New state enums.
     204        * rendering/RenderThemeIOS.mm:
     205        (WebCore::RenderThemeIOS::updateCachedSystemFontDescription): Be sensitive to new state inside
     206        FontDescription.
     207        * rendering/line/BreakingContext.h:
     208
    12092015-09-23  Chris Dumez  <cdumez@apple.com>
    2210
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r189830 r190192  
    320320    CSSPropertyWebkitFontKerning,
    321321    CSSPropertyWebkitFontSmoothing,
    322     CSSPropertyWebkitFontVariantLigatures,
     322    CSSPropertyFontVariantLigatures,
     323    CSSPropertyFontVariantPosition,
     324    CSSPropertyFontVariantCaps,
     325    CSSPropertyFontVariantNumeric,
     326    CSSPropertyFontVariantAlternates,
     327    CSSPropertyFontVariantEastAsian,
    323328#if ENABLE(CSS_GRID_LAYOUT)
    324329    CSSPropertyWebkitGridAutoColumns,
     
    11961201
    11971202    return WTF::move(list);
     1203}
     1204
     1205static inline void appendLigaturesValue(CSSValueList& list, FontVariantLigatures value, CSSValueID yesValue, CSSValueID noValue)
     1206{
     1207    switch (value) {
     1208    case FontVariantLigatures::Normal:
     1209        return;
     1210    case FontVariantLigatures::No:
     1211        list.append(CSSValuePool::singleton().createIdentifierValue(noValue));
     1212        return;
     1213    case FontVariantLigatures::Yes:
     1214        list.append(CSSValuePool::singleton().createIdentifierValue(yesValue));
     1215        return;
     1216    }
     1217    ASSERT_NOT_REACHED();
     1218}
     1219
     1220static Ref<CSSValue> fontVariantLigaturesPropertyValue(FontVariantLigatures common, FontVariantLigatures discretionary, FontVariantLigatures historical, FontVariantLigatures contextualAlternates)
     1221{
     1222    auto& cssValuePool = CSSValuePool::singleton();
     1223    if (common == FontVariantLigatures::No && discretionary == FontVariantLigatures::No && historical == FontVariantLigatures::No && contextualAlternates == FontVariantLigatures::No)
     1224        return cssValuePool.createIdentifierValue(CSSValueNone);
     1225    if (common == FontVariantLigatures::Normal && discretionary == FontVariantLigatures::Normal && historical == FontVariantLigatures::Normal && contextualAlternates == FontVariantLigatures::Normal)
     1226        return cssValuePool.createIdentifierValue(CSSValueNormal);
     1227
     1228    auto valueList = CSSValueList::createSpaceSeparated();
     1229    appendLigaturesValue(valueList, common, CSSValueCommonLigatures, CSSValueNoCommonLigatures);
     1230    appendLigaturesValue(valueList, discretionary, CSSValueDiscretionaryLigatures, CSSValueNoDiscretionaryLigatures);
     1231    appendLigaturesValue(valueList, historical, CSSValueHistoricalLigatures, CSSValueNoHistoricalLigatures);
     1232    appendLigaturesValue(valueList, contextualAlternates, CSSValueContextual, CSSValueNoContextual);
     1233    return WTF::move(valueList);
     1234}
     1235
     1236static Ref<CSSValue> fontVariantPositionPropertyValue(FontVariantPosition position)
     1237{
     1238    auto& cssValuePool = CSSValuePool::singleton();
     1239    CSSValueID valueID = CSSValueNormal;
     1240    switch (position) {
     1241    case FontVariantPosition::Normal:
     1242        break;
     1243    case FontVariantPosition::Subscript:
     1244        valueID = CSSValueSub;
     1245        break;
     1246    case FontVariantPosition::Superscript:
     1247        valueID = CSSValueSuper;
     1248        break;
     1249    }
     1250    return cssValuePool.createIdentifierValue(valueID);
     1251}
     1252
     1253static Ref<CSSValue> fontVariantCapsPropertyValue(FontVariantCaps caps)
     1254{
     1255    auto& cssValuePool = CSSValuePool::singleton();
     1256    CSSValueID valueID = CSSValueNormal;
     1257    switch (caps) {
     1258    case FontVariantCaps::Normal:
     1259        break;
     1260    case FontVariantCaps::Small:
     1261        valueID = CSSValueSmallCaps;
     1262        break;
     1263    case FontVariantCaps::AllSmall:
     1264        valueID = CSSValueAllSmallCaps;
     1265        break;
     1266    case FontVariantCaps::Petite:
     1267        valueID = CSSValuePetiteCaps;
     1268        break;
     1269    case FontVariantCaps::AllPetite:
     1270        valueID = CSSValueAllPetiteCaps;
     1271        break;
     1272    case FontVariantCaps::Unicase:
     1273        valueID = CSSValueUnicase;
     1274        break;
     1275    case FontVariantCaps::Titling:
     1276        valueID = CSSValueTitlingCaps;
     1277        break;
     1278    }
     1279    return cssValuePool.createIdentifierValue(valueID);
     1280}
     1281
     1282static Ref<CSSValue> fontVariantNumericPropertyValue(FontVariantNumericFigure figure, FontVariantNumericSpacing spacing, FontVariantNumericFraction fraction, FontVariantNumericOrdinal ordinal, FontVariantNumericSlashedZero slashedZero)
     1283{
     1284    auto& cssValuePool = CSSValuePool::singleton();
     1285    if (figure == FontVariantNumericFigure::Normal && spacing == FontVariantNumericSpacing::Normal && fraction == FontVariantNumericFraction::Normal && ordinal == FontVariantNumericOrdinal::Normal && slashedZero == FontVariantNumericSlashedZero::Normal)
     1286        return cssValuePool.createIdentifierValue(CSSValueNormal);
     1287
     1288    auto valueList = CSSValueList::createSpaceSeparated();
     1289    switch (figure) {
     1290    case FontVariantNumericFigure::Normal:
     1291        break;
     1292    case FontVariantNumericFigure::LiningNumbers:
     1293        valueList->append(cssValuePool.createIdentifierValue(CSSValueLiningNums));
     1294        break;
     1295    case FontVariantNumericFigure::OldStyleNumbers:
     1296        valueList->append(cssValuePool.createIdentifierValue(CSSValueOldstyleNums));
     1297        break;
     1298    }
     1299
     1300    switch (spacing) {
     1301    case FontVariantNumericSpacing::Normal:
     1302        break;
     1303    case FontVariantNumericSpacing::ProportionalNumbers:
     1304        valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalNums));
     1305        break;
     1306    case FontVariantNumericSpacing::TabularNumbers:
     1307        valueList->append(cssValuePool.createIdentifierValue(CSSValueTabularNums));
     1308        break;
     1309    }
     1310
     1311    switch (fraction) {
     1312    case FontVariantNumericFraction::Normal:
     1313        break;
     1314    case FontVariantNumericFraction::DiagonalFractions:
     1315        valueList->append(cssValuePool.createIdentifierValue(CSSValueDiagonalFractions));
     1316        break;
     1317    case FontVariantNumericFraction::StackedFractions:
     1318        valueList->append(cssValuePool.createIdentifierValue(CSSValueStackedFractions));
     1319        break;
     1320    }
     1321
     1322    if (ordinal == FontVariantNumericOrdinal::Yes)
     1323        valueList->append(cssValuePool.createIdentifierValue(CSSValueOrdinal));
     1324    if (slashedZero == FontVariantNumericSlashedZero::Yes)
     1325        valueList->append(cssValuePool.createIdentifierValue(CSSValueSlashedZero));
     1326
     1327    return WTF::move(valueList);
     1328}
     1329
     1330static Ref<CSSValue> fontVariantAlternatesPropertyValue(FontVariantAlternates alternates)
     1331{
     1332    auto& cssValuePool = CSSValuePool::singleton();
     1333    CSSValueID valueID = CSSValueNormal;
     1334    switch (alternates) {
     1335    case FontVariantAlternates::Normal:
     1336        break;
     1337    case FontVariantAlternates::HistoricalForms:
     1338        valueID = CSSValueHistoricalForms;
     1339        break;
     1340    }
     1341    return cssValuePool.createIdentifierValue(valueID);
     1342}
     1343
     1344static Ref<CSSValue> fontVariantEastAsianPropertyValue(FontVariantEastAsianVariant variant, FontVariantEastAsianWidth width, FontVariantEastAsianRuby ruby)
     1345{
     1346    auto& cssValuePool = CSSValuePool::singleton();
     1347    if (variant == FontVariantEastAsianVariant::Normal && width == FontVariantEastAsianWidth::Normal && ruby == FontVariantEastAsianRuby::Normal)
     1348        return cssValuePool.createIdentifierValue(CSSValueNormal);
     1349
     1350    auto valueList = CSSValueList::createSpaceSeparated();
     1351    switch (variant) {
     1352    case FontVariantEastAsianVariant::Normal:
     1353        break;
     1354    case FontVariantEastAsianVariant::Jis78:
     1355        valueList->append(cssValuePool.createIdentifierValue(CSSValueJis78));
     1356        break;
     1357    case FontVariantEastAsianVariant::Jis83:
     1358        valueList->append(cssValuePool.createIdentifierValue(CSSValueJis83));
     1359        break;
     1360    case FontVariantEastAsianVariant::Jis90:
     1361        valueList->append(cssValuePool.createIdentifierValue(CSSValueJis90));
     1362        break;
     1363    case FontVariantEastAsianVariant::Jis04:
     1364        valueList->append(cssValuePool.createIdentifierValue(CSSValueJis04));
     1365        break;
     1366    case FontVariantEastAsianVariant::Simplified:
     1367        valueList->append(cssValuePool.createIdentifierValue(CSSValueSimplified));
     1368        break;
     1369    case FontVariantEastAsianVariant::Traditional:
     1370        valueList->append(cssValuePool.createIdentifierValue(CSSValueTraditional));
     1371        break;
     1372    }
     1373
     1374    switch (width) {
     1375    case FontVariantEastAsianWidth::Normal:
     1376        break;
     1377    case FontVariantEastAsianWidth::FullWidth:
     1378        valueList->append(cssValuePool.createIdentifierValue(CSSValueFullWidth));
     1379        break;
     1380    case FontVariantEastAsianWidth::ProportionalWidth:
     1381        valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalWidth));
     1382        break;
     1383    }
     1384
     1385    if (ruby == FontVariantEastAsianRuby::Yes)
     1386        valueList->append(cssValuePool.createIdentifierValue(CSSValueRuby));
     1387
     1388    return WTF::move(valueList);
    11981389}
    11991390
     
    23212512            return fontSynthesisFromStyle(*style);
    23222513        case CSSPropertyWebkitFontFeatureSettings: {
    2323             const FontFeatureSettings* featureSettings = style->fontDescription().featureSettings();
    2324             if (!featureSettings || !featureSettings->size())
     2514            const FontFeatureSettings& featureSettings = style->fontDescription().featureSettings();
     2515            if (!featureSettings.size())
    23252516                return cssValuePool.createIdentifierValue(CSSValueNormal);
    23262517            RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
    2327             for (unsigned i = 0; i < featureSettings->size(); ++i) {
    2328                 const FontFeature& feature = featureSettings->at(i);
    2329                 list->append(CSSFontFeatureValue::create(feature.tag(), feature.value()));
    2330             }
     2518            for (auto& feature : featureSettings)
     2519                list->append(CSSFontFeatureValue::create(FontFeatureTag(feature.tag()), feature.value()));
    23312520            return list;
    23322521        }
     
    27242913        case CSSPropertyWebkitFontSmoothing:
    27252914            return cssValuePool.createValue(style->fontDescription().fontSmoothing());
    2726         case CSSPropertyWebkitFontVariantLigatures: {
    2727             auto commonLigaturesState = style->fontDescription().commonLigaturesState();
    2728             auto discretionaryLigaturesState = style->fontDescription().discretionaryLigaturesState();
    2729             auto historicalLigaturesState = style->fontDescription().historicalLigaturesState();
    2730             if (commonLigaturesState == FontCascadeDescription::NormalLigaturesState && discretionaryLigaturesState == FontCascadeDescription::NormalLigaturesState
    2731                 && historicalLigaturesState == FontCascadeDescription::NormalLigaturesState)
    2732                 return cssValuePool.createIdentifierValue(CSSValueNormal);
    2733 
    2734             RefPtr<CSSValueList> valueList = CSSValueList::createSpaceSeparated();
    2735             if (commonLigaturesState != FontCascadeDescription::NormalLigaturesState)
    2736                 valueList->append(cssValuePool.createIdentifierValue(commonLigaturesState == FontCascadeDescription::DisabledLigaturesState ? CSSValueNoCommonLigatures : CSSValueCommonLigatures));
    2737             if (discretionaryLigaturesState != FontCascadeDescription::NormalLigaturesState)
    2738                 valueList->append(cssValuePool.createIdentifierValue(discretionaryLigaturesState == FontCascadeDescription::DisabledLigaturesState ? CSSValueNoDiscretionaryLigatures : CSSValueDiscretionaryLigatures));
    2739             if (historicalLigaturesState != FontCascadeDescription::NormalLigaturesState)
    2740                 valueList->append(cssValuePool.createIdentifierValue(historicalLigaturesState == FontCascadeDescription::DisabledLigaturesState ? CSSValueNoHistoricalLigatures : CSSValueHistoricalLigatures));
    2741             return valueList;
    2742         }
     2915        case CSSPropertyFontVariantLigatures:
     2916            return fontVariantLigaturesPropertyValue(style->fontDescription().variantCommonLigatures(), style->fontDescription().variantDiscretionaryLigatures(), style->fontDescription().variantHistoricalLigatures(), style->fontDescription().variantContextualAlternates());
     2917        case CSSPropertyFontVariantPosition:
     2918            return fontVariantPositionPropertyValue(style->fontDescription().variantPosition());
     2919        case CSSPropertyFontVariantCaps:
     2920            return fontVariantCapsPropertyValue(style->fontDescription().variantCaps());
     2921        case CSSPropertyFontVariantNumeric:
     2922            return fontVariantNumericPropertyValue(style->fontDescription().variantNumericFigure(), style->fontDescription().variantNumericSpacing(), style->fontDescription().variantNumericFraction(), style->fontDescription().variantNumericOrdinal(), style->fontDescription().variantNumericSlashedZero());
     2923        case CSSPropertyFontVariantAlternates:
     2924            return fontVariantAlternatesPropertyValue(style->fontDescription().variantAlternates());
     2925        case CSSPropertyFontVariantEastAsian:
     2926            return fontVariantEastAsianPropertyValue(style->fontDescription().variantEastAsianVariant(), style->fontDescription().variantEastAsianWidth(), style->fontDescription().variantEastAsianRuby());
    27432927        case CSSPropertyZIndex:
    27442928            if (style->hasAutoZIndex())
  • trunk/Source/WebCore/css/CSSFontFeatureValue.cpp

    r165676 r190192  
    3333namespace WebCore {
    3434
    35 CSSFontFeatureValue::CSSFontFeatureValue(const String& tag, int value)
     35CSSFontFeatureValue::CSSFontFeatureValue(FontFeatureTag&& tag, int value)
    3636    : CSSValue(FontFeatureClass)
    37     , m_tag(tag)
     37    , m_tag(WTF::move(tag))
    3838    , m_value(value)
    3939{
     
    4444    StringBuilder builder;
    4545    builder.append('\'');
    46     builder.append(m_tag);
     46    for (char c : m_tag)
     47        builder.append(c);
    4748    builder.appendLiteral("' ");
    4849    builder.appendNumber(m_value);
  • trunk/Source/WebCore/css/CSSFontFeatureValue.h

    r177259 r190192  
    2828
    2929#include "CSSValue.h"
    30 #include <wtf/text/WTFString.h>
     30#include "FontFeatureSettings.h"
    3131
    3232namespace WebCore {
     
    3434class CSSFontFeatureValue : public CSSValue {
    3535public:
    36     static Ref<CSSFontFeatureValue> create(const String& tag, int value)
     36    static Ref<CSSFontFeatureValue> create(FontFeatureTag&& tag, int value)
    3737    {
    38         return adoptRef(*new CSSFontFeatureValue(tag, value));
     38        return adoptRef(*new CSSFontFeatureValue(WTF::move(tag), value));
    3939    }
    4040
    41     const String& tag() const { return m_tag; }
     41    const FontFeatureTag& tag() const { return m_tag; }
    4242    int value() const { return m_value; }
    4343    String customCSSText() const;
     
    4646
    4747private:
    48     CSSFontFeatureValue(const String&, int);
     48    CSSFontFeatureValue(FontFeatureTag&&, int);
    4949
    50     String m_tag;
     50    FontFeatureTag m_tag;
    5151    const int m_value;
    5252};
  • trunk/Source/WebCore/css/CSSParser.cpp

    r190003 r190192  
    10371037        break;
    10381038#endif
     1039    case CSSPropertyFontVariantPosition: // normal | sub | super
     1040        if (valueID == CSSValueNormal || valueID == CSSValueSub || valueID == CSSValueSuper)
     1041            return true;
     1042        break;
     1043    case CSSPropertyFontVariantCaps: // normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps
     1044        if (valueID == CSSValueNormal || valueID == CSSValueSmallCaps || valueID == CSSValueAllSmallCaps || valueID == CSSValuePetiteCaps || valueID == CSSValueAllPetiteCaps || valueID == CSSValueUnicase || valueID == CSSValueTitlingCaps)
     1045            return true;
     1046        break;
     1047    case CSSPropertyFontVariantAlternates: // We only support the normal and historical-forms values.
     1048        if (valueID == CSSValueNormal || valueID == CSSValueHistoricalForms)
     1049            return true;
     1050        break;
    10391051    default:
    10401052        ASSERT_NOT_REACHED();
     
    11631175    case CSSPropertyAppleTrailingWord:
    11641176#endif
     1177    case CSSPropertyFontVariantPosition:
     1178    case CSSPropertyFontVariantCaps:
     1179    case CSSPropertyFontVariantAlternates:
    11651180        return true;
    11661181    default:
     
    30163031            return parseFontFeatureSettings(important);
    30173032        break;
    3018 
    3019     case CSSPropertyWebkitFontVariantLigatures:
     3033    case CSSPropertyFontVariantLigatures:
     3034        if (id == CSSValueNormal || id == CSSValueNone)
     3035            validPrimitive = true;
     3036        else
     3037            return parseFontVariantLigatures(important);
     3038        break;
     3039    case CSSPropertyFontVariantNumeric:
    30203040        if (id == CSSValueNormal)
    30213041            validPrimitive = true;
    30223042        else
    3023             return parseFontVariantLigatures(important);
    3024         break;
     3043            return parseFontVariantNumeric(important);
     3044        break;
     3045    case CSSPropertyFontVariantEastAsian:
     3046        if (id == CSSValueNormal)
     3047            validPrimitive = true;
     3048        else
     3049            return parseFontVariantEastAsian(important);
     3050        break;
     3051
    30253052    case CSSPropertyWebkitClipPath:
    30263053        parsedValue = parseClipPath();
     
    1038310410bool CSSParser::parseFontFeatureTag(CSSValueList& settings)
    1038410411{
    10385     // Feature tag name consists of 4-letter characters.
    10386     static const unsigned tagNameLength = 4;
    10387 
    1038810412    CSSParserValue* value = m_valueList->current();
    1038910413    // Feature tag name comes first
    1039010414    if (value->unit != CSSPrimitiveValue::CSS_STRING)
    1039110415        return false;
    10392     if (value->string.length() != tagNameLength)
    10393         return false;
    10394     for (unsigned i = 0; i < tagNameLength; ++i) {
     10416    FontFeatureTag tag;
     10417    if (value->string.length() != tag.size())
     10418        return false;
     10419    for (unsigned i = 0; i < tag.size(); ++i) {
    1039510420        // Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
    1039610421        UChar character = value->string[i];
    1039710422        if (character < 0x20 || character > 0x7E)
    1039810423            return false;
    10399     }
    10400 
    10401     String tag = String(value->string).convertToASCIILowercase();
     10424        tag[i] = toASCIILower(character);
     10425    }
     10426
    1040210427    int tagValue = 1;
    1040310428    // Feature tag values could follow: <integer> | on | off
     
    1041410439        }
    1041510440    }
    10416     settings.append(CSSFontFeatureValue::create(tag, tagValue));
     10441    settings.append(CSSFontFeatureValue::create(WTF::move(tag), tagValue));
    1041710442    return true;
    1041810443}
     
    1044610471bool CSSParser::parseFontVariantLigatures(bool important)
    1044710472{
    10448     RefPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated();
    10449     bool sawCommonLigaturesValue = false;
    10450     bool sawDiscretionaryLigaturesValue = false;
    10451     bool sawHistoricalLigaturesValue = false;
     10473    auto values = CSSValueList::createSpaceSeparated();
     10474    bool sawCommonValue = false;
     10475    bool sawDiscretionaryValue = false;
     10476    bool sawHistoricalValue = false;
     10477    bool sawContextualValue = false;
    1045210478
    1045310479    for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
     
    1045810484        case CSSValueNoCommonLigatures:
    1045910485        case CSSValueCommonLigatures:
    10460             if (sawCommonLigaturesValue)
     10486            if (sawCommonValue)
    1046110487                return false;
    10462             sawCommonLigaturesValue = true;
    10463             ligatureValues->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10488            sawCommonValue = true;
     10489            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
    1046410490            break;
    1046510491        case CSSValueNoDiscretionaryLigatures:
    1046610492        case CSSValueDiscretionaryLigatures:
    10467             if (sawDiscretionaryLigaturesValue)
     10493            if (sawDiscretionaryValue)
    1046810494                return false;
    10469             sawDiscretionaryLigaturesValue = true;
    10470             ligatureValues->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10495            sawDiscretionaryValue = true;
     10496            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
    1047110497            break;
    1047210498        case CSSValueNoHistoricalLigatures:
    1047310499        case CSSValueHistoricalLigatures:
    10474             if (sawHistoricalLigaturesValue)
     10500            if (sawHistoricalValue)
    1047510501                return false;
    10476             sawHistoricalLigaturesValue = true;
    10477             ligatureValues->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10502            sawHistoricalValue = true;
     10503            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10504            break;
     10505        case CSSValueContextual:
     10506        case CSSValueNoContextual:
     10507            if (sawContextualValue)
     10508                return false;
     10509            sawContextualValue = true;
     10510            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
    1047810511            break;
    1047910512        default:
     
    1048210515    }
    1048310516
    10484     if (!ligatureValues->length())
    10485         return false;
    10486 
    10487     addProperty(CSSPropertyWebkitFontVariantLigatures, ligatureValues.release(), important);
     10517    if (!values->length())
     10518        return false;
     10519
     10520    addProperty(CSSPropertyFontVariantLigatures, WTF::move(values), important);
     10521    return true;
     10522}
     10523
     10524bool CSSParser::parseFontVariantNumeric(bool important)
     10525{
     10526    auto values = CSSValueList::createSpaceSeparated();
     10527    bool sawFigureValue = false;
     10528    bool sawSpacingValue = false;
     10529    bool sawFractionValue = false;
     10530    bool sawOrdinal = false;
     10531    bool sawSlashedZero = false;
     10532
     10533    for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
     10534        if (value->unit != CSSPrimitiveValue::CSS_IDENT)
     10535            return false;
     10536
     10537        switch (value->id) {
     10538        case CSSValueLiningNums:
     10539        case CSSValueOldstyleNums:
     10540            if (sawFigureValue)
     10541                return false;
     10542            sawFigureValue = true;
     10543            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10544            break;
     10545        case CSSValueProportionalNums:
     10546        case CSSValueTabularNums:
     10547            if (sawSpacingValue)
     10548                return false;
     10549            sawSpacingValue = true;
     10550            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10551            break;
     10552        case CSSValueDiagonalFractions:
     10553        case CSSValueStackedFractions:
     10554            if (sawFractionValue)
     10555                return false;
     10556            sawFractionValue = true;
     10557            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10558            break;
     10559        case CSSValueOrdinal:
     10560            if (sawOrdinal)
     10561                return false;
     10562            sawOrdinal = true;
     10563            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10564            break;
     10565        case CSSValueSlashedZero:
     10566            if (sawSlashedZero)
     10567                return false;
     10568            sawSlashedZero = true;
     10569            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10570            break;
     10571        default:
     10572            return false;
     10573        }
     10574    }
     10575
     10576    if (!values->length())
     10577        return false;
     10578
     10579    addProperty(CSSPropertyFontVariantNumeric, WTF::move(values), important);
     10580    return true;
     10581}
     10582
     10583bool CSSParser::parseFontVariantEastAsian(bool important)
     10584{
     10585    auto values = CSSValueList::createSpaceSeparated();
     10586    bool sawVariantValue = false;
     10587    bool sawWidthValue = false;
     10588    bool sawRuby = false;
     10589
     10590    for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
     10591        if (value->unit != CSSPrimitiveValue::CSS_IDENT)
     10592            return false;
     10593
     10594        switch (value->id) {
     10595        case CSSValueJis78:
     10596        case CSSValueJis83:
     10597        case CSSValueJis90:
     10598        case CSSValueJis04:
     10599        case CSSValueSimplified:
     10600        case CSSValueTraditional:
     10601            if (sawVariantValue)
     10602                return false;
     10603            sawVariantValue = true;
     10604            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10605            break;
     10606        case CSSValueFullWidth:
     10607        case CSSValueProportionalWidth:
     10608            if (sawWidthValue)
     10609                return false;
     10610            sawWidthValue = true;
     10611            values->append(CSSValuePool::singleton().createIdentifierValue(value->id));
     10612            break;
     10613        case CSSValueRuby:
     10614            sawRuby = true;
     10615            break;
     10616        default:
     10617            return false;
     10618        }
     10619    }
     10620
     10621    if (sawRuby)
     10622        values->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
     10623
     10624    if (!values->length())
     10625        return false;
     10626
     10627    addProperty(CSSPropertyFontVariantEastAsian, WTF::move(values), important);
    1048810628    return true;
    1048910629}
  • trunk/Source/WebCore/css/CSSParser.h

    r188512 r190192  
    345345
    346346    bool parseFontVariantLigatures(bool important);
     347    bool parseFontVariantNumeric(bool important);
     348    bool parseFontVariantEastAsian(bool important);
    347349
    348350    bool parseWillChange(bool important);
  • trunk/Source/WebCore/css/CSSPrimitiveValueMappings.h

    r189830 r190192  
    53235323#endif
    53245324
     5325template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontVariantPosition position)
     5326    : CSSValue(PrimitiveClass)
     5327{
     5328    m_primitiveUnitType = CSS_VALUE_ID;
     5329    switch (position) {
     5330    case FontVariantPosition::Normal:
     5331        m_value.valueID = CSSValueNormal;
     5332        break;
     5333    case FontVariantPosition::Subscript:
     5334        m_value.valueID = CSSValueSub;
     5335        break;
     5336    case FontVariantPosition::Superscript:
     5337        m_value.valueID = CSSValueSuper;
     5338        break;
     5339    default:
     5340        ASSERT_NOT_REACHED();
     5341        break;
     5342    }
     5343}
     5344
     5345template<> inline CSSPrimitiveValue::operator FontVariantPosition() const
     5346{
     5347    ASSERT(isValueID());
     5348    switch (m_value.valueID) {
     5349    case CSSValueNormal:
     5350        return FontVariantPosition::Normal;
     5351    case CSSValueSub:
     5352        return FontVariantPosition::Subscript;
     5353    case CSSValueSuper:
     5354        return FontVariantPosition::Superscript;
     5355    default:
     5356        break;
     5357    }
     5358    ASSERT_NOT_REACHED();
     5359    return FontVariantPosition::Normal;
     5360}
     5361
     5362template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontVariantCaps caps)
     5363    : CSSValue(PrimitiveClass)
     5364{
     5365    m_primitiveUnitType = CSS_VALUE_ID;
     5366    switch (caps) {
     5367    case FontVariantCaps::Normal:
     5368        m_value.valueID = CSSValueNormal;
     5369        break;
     5370    case FontVariantCaps::Small:
     5371        m_value.valueID = CSSValueSmallCaps;
     5372        break;
     5373    case FontVariantCaps::AllSmall:
     5374        m_value.valueID = CSSValueAllSmallCaps;
     5375        break;
     5376    case FontVariantCaps::Petite:
     5377        m_value.valueID = CSSValuePetiteCaps;
     5378        break;
     5379    case FontVariantCaps::AllPetite:
     5380        m_value.valueID = CSSValueAllPetiteCaps;
     5381        break;
     5382    case FontVariantCaps::Unicase:
     5383        m_value.valueID = CSSValueUnicase;
     5384        break;
     5385    case FontVariantCaps::Titling:
     5386        m_value.valueID = CSSValueTitlingCaps;
     5387        break;
     5388    default:
     5389        ASSERT_NOT_REACHED();
     5390        break;
     5391    }
     5392}
     5393
     5394template<> inline CSSPrimitiveValue::operator FontVariantCaps() const
     5395{
     5396    ASSERT(isValueID());
     5397    switch (m_value.valueID) {
     5398    case CSSValueNormal:
     5399        return FontVariantCaps::Normal;
     5400    case CSSValueSmallCaps:
     5401        return FontVariantCaps::Small;
     5402    case CSSValueAllSmallCaps:
     5403        return FontVariantCaps::AllSmall;
     5404    case CSSValuePetiteCaps:
     5405        return FontVariantCaps::Petite;
     5406    case CSSValueAllPetiteCaps:
     5407        return FontVariantCaps::AllPetite;
     5408    case CSSValueUnicase:
     5409        return FontVariantCaps::Unicase;
     5410    case CSSValueTitlingCaps:
     5411        return FontVariantCaps::Titling;
     5412    default:
     5413        break;
     5414    }
     5415    ASSERT_NOT_REACHED();
     5416    return FontVariantCaps::Normal;
     5417}
     5418
     5419template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontVariantAlternates alternates)
     5420    : CSSValue(PrimitiveClass)
     5421{
     5422    m_primitiveUnitType = CSS_VALUE_ID;
     5423    switch (alternates) {
     5424    case FontVariantAlternates::Normal:
     5425        m_value.valueID = CSSValueNormal;
     5426        break;
     5427    case FontVariantAlternates::HistoricalForms:
     5428        m_value.valueID = CSSValueHistoricalForms;
     5429        break;
     5430    default:
     5431        ASSERT_NOT_REACHED();
     5432        break;
     5433    }
     5434}
     5435
     5436template<> inline CSSPrimitiveValue::operator FontVariantAlternates() const
     5437{
     5438    ASSERT(isValueID());
     5439    switch (m_value.valueID) {
     5440    case CSSValueNormal:
     5441        return FontVariantAlternates::Normal;
     5442    case CSSValueHistoricalForms:
     5443        return FontVariantAlternates::HistoricalForms;
     5444    default:
     5445        break;
     5446    }
     5447    ASSERT_NOT_REACHED();
     5448    return FontVariantAlternates::Normal;
     5449}
    53255450}
    53265451
  • trunk/Source/WebCore/css/CSSPropertyNames.in

    r188647 r190192  
    109109-webkit-font-kerning [Inherited, FontProperty, NameForMethods=Kerning]
    110110-webkit-font-smoothing [Inherited, FontProperty]
    111 -webkit-font-variant-ligatures [Inherited, Custom=All]
     111font-variant-ligatures [Inherited, FontProperty, NameForMethods=VariantLigatures, Custom=All]
     112font-variant-position [Inherited, FontProperty, NameForMethods=VariantPosition]
     113font-variant-caps [Inherited, FontProperty, NameForMethods=VariantCaps]
     114font-variant-numeric [Inherited, FontProperty, NameForMethods=VariantNumeric, Custom=All]
     115font-variant-alternates [Inherited, FontProperty, NameForMethods=VariantAlternates]
     116font-variant-east-asian [Inherited, FontProperty, NameForMethods=VariantEastAsian, Custom=All]
    112117-webkit-locale [Inherited, FontProperty, Custom=Value]
    113118-webkit-text-orientation [Inherited, Custom=Value]
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r188512 r190192  
    6868small-caps
    6969
    70 // -webkit-font-variant-ligatures:
    71 //
    72 // normal
     70// font-variant-ligatures:
     71//
    7372common-ligatures
    7473no-common-ligatures
     
    7776historical-ligatures
    7877no-historical-ligatures
     78contextual
     79no-contextual
     80
     81// font-variant-caps
     82//
     83// FIXME: Unify this with plain font-variant
     84// small-caps
     85all-small-caps
     86petite-caps
     87all-petite-caps
     88unicase
     89titling-caps
     90
     91// font-variant-numeric
     92//
     93lining-nums
     94oldstyle-nums
     95proportional-nums
     96tabular-nums
     97diagonal-fractions
     98stacked-fractions
     99ordinal
     100slashed-zero
     101
     102// font-variant-alternates
     103//
     104historical-forms
     105
     106// font-variant-east-asian
     107//
     108jis78
     109jis83
     110jis90
     111jis04
     112simplified
     113traditional
     114full-width
     115proportional-width
     116ruby
    79117
    80118//
  • trunk/Source/WebCore/css/StyleBuilderConverter.h

    r188056 r190192  
    113113    static bool convertOverflowScrolling(StyleResolver&, CSSValue&);
    114114#endif
    115     static RefPtr<FontFeatureSettings> convertFontFeatureSettings(StyleResolver&, CSSValue&);
     115    static FontFeatureSettings convertFontFeatureSettings(StyleResolver&, CSSValue&);
    116116    static SVGLength convertSVGLength(StyleResolver&, CSSValue&);
    117117    static Vector<SVGLength> convertSVGLengthVector(StyleResolver&, CSSValue&);
     
    10051005}
    10061006
    1007 inline RefPtr<FontFeatureSettings> StyleBuilderConverter::convertFontFeatureSettings(StyleResolver&, CSSValue& value)
     1007inline FontFeatureSettings StyleBuilderConverter::convertFontFeatureSettings(StyleResolver&, CSSValue& value)
    10081008{
    10091009    if (is<CSSPrimitiveValue>(value)) {
    10101010        ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNormal);
    1011         return nullptr;
    1012     }
    1013 
    1014     RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
     1011        return { };
     1012    }
     1013
     1014    FontFeatureSettings settings;
    10151015    for (auto& item : downcast<CSSValueList>(value)) {
    10161016        auto& feature = downcast<CSSFontFeatureValue>(item.get());
    1017         settings->insert(FontFeature(feature.tag(), feature.value()));
    1018     }
    1019     return WTF::move(settings);
     1017        settings.insert(FontFeature(feature.tag(), feature.value()));
     1018    }
     1019    return settings;
    10201020}
    10211021
  • trunk/Source/WebCore/css/StyleBuilderCustom.h

    r189830 r190192  
    9090    DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitAspectRatio);
    9191    DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitBoxShadow);
    92     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitFontVariantLigatures);
     92    DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantLigatures);
     93    DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantNumeric);
     94    DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantEastAsian);
    9395#if ENABLE(CSS_GRID_LAYOUT)
    9496    DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitGridTemplateAreas);
     
    13891391}
    13901392
    1391 inline void StyleBuilderCustom::applyInitialWebkitFontVariantLigatures(StyleResolver& styleResolver)
     1393inline void StyleBuilderCustom::applyInheritFontVariantLigatures(StyleResolver& styleResolver)
    13921394{
    13931395    auto fontDescription = styleResolver.fontDescription();
    1394 
    1395     fontDescription.setCommonLigaturesState(FontCascadeDescription::NormalLigaturesState);
    1396     fontDescription.setDiscretionaryLigaturesState(FontCascadeDescription::NormalLigaturesState);
    1397     fontDescription.setHistoricalLigaturesState(FontCascadeDescription::NormalLigaturesState);
    1398 
     1396    fontDescription.setVariantCommonLigatures(styleResolver.parentFontDescription().variantCommonLigatures());
     1397    fontDescription.setVariantDiscretionaryLigatures(styleResolver.parentFontDescription().variantDiscretionaryLigatures());
     1398    fontDescription.setVariantHistoricalLigatures(styleResolver.parentFontDescription().variantHistoricalLigatures());
     1399    fontDescription.setVariantContextualAlternates(styleResolver.parentFontDescription().variantContextualAlternates());
    13991400    styleResolver.setFontDescription(fontDescription);
    14001401}
    14011402
    1402 inline void StyleBuilderCustom::applyInheritWebkitFontVariantLigatures(StyleResolver& styleResolver)
    1403 {
    1404     const auto& parentFontDescription = styleResolver.parentFontDescription();
     1403inline void StyleBuilderCustom::applyInitialFontVariantLigatures(StyleResolver& styleResolver)
     1404{
    14051405    auto fontDescription = styleResolver.fontDescription();
    1406 
    1407     fontDescription.setCommonLigaturesState(parentFontDescription.commonLigaturesState());
    1408     fontDescription.setDiscretionaryLigaturesState(parentFontDescription.discretionaryLigaturesState());
    1409     fontDescription.setHistoricalLigaturesState(parentFontDescription.historicalLigaturesState());
    1410 
     1406    fontDescription.setVariantCommonLigatures(FontVariantLigatures::Normal);
     1407    fontDescription.setVariantDiscretionaryLigatures(FontVariantLigatures::Normal);
     1408    fontDescription.setVariantHistoricalLigatures(FontVariantLigatures::Normal);
     1409    fontDescription.setVariantContextualAlternates(FontVariantLigatures::Normal);
    14111410    styleResolver.setFontDescription(fontDescription);
    14121411}
    14131412
    1414 inline void StyleBuilderCustom::applyValueWebkitFontVariantLigatures(StyleResolver& styleResolver, CSSValue& value)
    1415 {
    1416     auto commonLigaturesState = FontCascadeDescription::NormalLigaturesState;
    1417     auto discretionaryLigaturesState = FontCascadeDescription::NormalLigaturesState;
    1418     auto historicalLigaturesState = FontCascadeDescription::NormalLigaturesState;
     1413inline void StyleBuilderCustom::applyValueFontVariantLigatures(StyleResolver& styleResolver, CSSValue& value)
     1414{
     1415    FontVariantLigatures common = FontVariantLigatures::Normal;
     1416    FontVariantLigatures discretionary = FontVariantLigatures::Normal;
     1417    FontVariantLigatures historical = FontVariantLigatures::Normal;
     1418    FontVariantLigatures contextualAlternates = FontVariantLigatures::Normal;
    14191419
    14201420    if (is<CSSValueList>(value)) {
     
    14221422            switch (downcast<CSSPrimitiveValue>(item.get()).getValueID()) {
    14231423            case CSSValueNoCommonLigatures:
    1424                 commonLigaturesState = FontCascadeDescription::DisabledLigaturesState;
     1424                common = FontVariantLigatures::No;
    14251425                break;
    14261426            case CSSValueCommonLigatures:
    1427                 commonLigaturesState = FontCascadeDescription::EnabledLigaturesState;
     1427                common = FontVariantLigatures::Yes;
    14281428                break;
    14291429            case CSSValueNoDiscretionaryLigatures:
    1430                 discretionaryLigaturesState = FontCascadeDescription::DisabledLigaturesState;
     1430                discretionary = FontVariantLigatures::No;
    14311431                break;
    14321432            case CSSValueDiscretionaryLigatures:
    1433                 discretionaryLigaturesState = FontCascadeDescription::EnabledLigaturesState;
     1433                discretionary = FontVariantLigatures::Yes;
    14341434                break;
    14351435            case CSSValueNoHistoricalLigatures:
    1436                 historicalLigaturesState = FontCascadeDescription::DisabledLigaturesState;
     1436                historical = FontVariantLigatures::No;
    14371437                break;
    14381438            case CSSValueHistoricalLigatures:
    1439                 historicalLigaturesState = FontCascadeDescription::EnabledLigaturesState;
     1439                historical = FontVariantLigatures::Yes;
     1440                break;
     1441            case CSSValueContextual:
     1442                contextualAlternates = FontVariantLigatures::Yes;
     1443                break;
     1444            case CSSValueNoContextual:
     1445                contextualAlternates = FontVariantLigatures::No;
     1446                break;
     1447            default:
     1448                ASSERT_NOT_REACHED();
     1449                break;
     1450            }
     1451        }
     1452    } else {
     1453        switch (downcast<CSSPrimitiveValue>(value).getValueID()) {
     1454        case CSSValueNormal:
     1455            break;
     1456        case CSSValueNone:
     1457            common = FontVariantLigatures::No;
     1458            discretionary = FontVariantLigatures::No;
     1459            historical = FontVariantLigatures::No;
     1460            contextualAlternates = FontVariantLigatures::No;
     1461            break;
     1462        default:
     1463            ASSERT_NOT_REACHED();
     1464            break;
     1465        }
     1466    }
     1467
     1468    auto fontDescription = styleResolver.fontDescription();
     1469    fontDescription.setVariantCommonLigatures(common);
     1470    fontDescription.setVariantDiscretionaryLigatures(discretionary);
     1471    fontDescription.setVariantHistoricalLigatures(historical);
     1472    fontDescription.setVariantContextualAlternates(contextualAlternates);
     1473    styleResolver.setFontDescription(fontDescription);
     1474}
     1475
     1476inline void StyleBuilderCustom::applyInheritFontVariantNumeric(StyleResolver& styleResolver)
     1477{
     1478    auto fontDescription = styleResolver.fontDescription();
     1479    fontDescription.setVariantNumericFigure(styleResolver.parentFontDescription().variantNumericFigure());
     1480    fontDescription.setVariantNumericSpacing(styleResolver.parentFontDescription().variantNumericSpacing());
     1481    fontDescription.setVariantNumericFraction(styleResolver.parentFontDescription().variantNumericFraction());
     1482    fontDescription.setVariantNumericOrdinal(styleResolver.parentFontDescription().variantNumericOrdinal());
     1483    fontDescription.setVariantNumericSlashedZero(styleResolver.parentFontDescription().variantNumericSlashedZero());
     1484    styleResolver.setFontDescription(fontDescription);
     1485}
     1486
     1487inline void StyleBuilderCustom::applyInitialFontVariantNumeric(StyleResolver& styleResolver)
     1488{
     1489    auto fontDescription = styleResolver.fontDescription();
     1490    fontDescription.setVariantNumericFigure(FontVariantNumericFigure::Normal);
     1491    fontDescription.setVariantNumericSpacing(FontVariantNumericSpacing::Normal);
     1492    fontDescription.setVariantNumericFraction(FontVariantNumericFraction::Normal);
     1493    fontDescription.setVariantNumericOrdinal(FontVariantNumericOrdinal::Normal);
     1494    fontDescription.setVariantNumericSlashedZero(FontVariantNumericSlashedZero::Normal);
     1495    styleResolver.setFontDescription(fontDescription);
     1496}
     1497
     1498inline void StyleBuilderCustom::applyValueFontVariantNumeric(StyleResolver& styleResolver, CSSValue& value)
     1499{
     1500    FontVariantNumericFigure figure = FontVariantNumericFigure::Normal;
     1501    FontVariantNumericSpacing spacing = FontVariantNumericSpacing::Normal;
     1502    FontVariantNumericFraction fraction = FontVariantNumericFraction::Normal;
     1503    FontVariantNumericOrdinal ordinal = FontVariantNumericOrdinal::Normal;
     1504    FontVariantNumericSlashedZero slashedZero = FontVariantNumericSlashedZero::Normal;
     1505
     1506    if (is<CSSValueList>(value)) {
     1507        for (auto& item : downcast<CSSValueList>(value)) {
     1508            switch (downcast<CSSPrimitiveValue>(item.get()).getValueID()) {
     1509            case CSSValueLiningNums:
     1510                figure = FontVariantNumericFigure::LiningNumbers;
     1511                break;
     1512            case CSSValueOldstyleNums:
     1513                figure = FontVariantNumericFigure::OldStyleNumbers;
     1514                break;
     1515            case CSSValueProportionalNums:
     1516                spacing = FontVariantNumericSpacing::ProportionalNumbers;
     1517                break;
     1518            case CSSValueTabularNums:
     1519                spacing = FontVariantNumericSpacing::TabularNumbers;
     1520                break;
     1521            case CSSValueDiagonalFractions:
     1522                fraction = FontVariantNumericFraction::DiagonalFractions;
     1523                break;
     1524            case CSSValueStackedFractions:
     1525                fraction = FontVariantNumericFraction::StackedFractions;
     1526                break;
     1527            case CSSValueOrdinal:
     1528                ordinal = FontVariantNumericOrdinal::Yes;
     1529                break;
     1530            case CSSValueSlashedZero:
     1531                slashedZero = FontVariantNumericSlashedZero::Yes;
    14401532                break;
    14411533            default:
     
    14481540
    14491541    auto fontDescription = styleResolver.fontDescription();
    1450     fontDescription.setCommonLigaturesState(commonLigaturesState);
    1451     fontDescription.setDiscretionaryLigaturesState(discretionaryLigaturesState);
    1452     fontDescription.setHistoricalLigaturesState(historicalLigaturesState);
     1542    fontDescription.setVariantNumericFigure(figure);
     1543    fontDescription.setVariantNumericSpacing(spacing);
     1544    fontDescription.setVariantNumericFraction(fraction);
     1545    fontDescription.setVariantNumericOrdinal(ordinal);
     1546    fontDescription.setVariantNumericSlashedZero(slashedZero);
     1547    styleResolver.setFontDescription(fontDescription);
     1548}
     1549
     1550inline void StyleBuilderCustom::applyInheritFontVariantEastAsian(StyleResolver& styleResolver)
     1551{
     1552    auto fontDescription = styleResolver.fontDescription();
     1553    fontDescription.setVariantEastAsianVariant(styleResolver.parentFontDescription().variantEastAsianVariant());
     1554    fontDescription.setVariantEastAsianWidth(styleResolver.parentFontDescription().variantEastAsianWidth());
     1555    fontDescription.setVariantEastAsianRuby(styleResolver.parentFontDescription().variantEastAsianRuby());
     1556    styleResolver.setFontDescription(fontDescription);
     1557}
     1558
     1559inline void StyleBuilderCustom::applyInitialFontVariantEastAsian(StyleResolver& styleResolver)
     1560{
     1561    auto fontDescription = styleResolver.fontDescription();
     1562    fontDescription.setVariantEastAsianVariant(FontVariantEastAsianVariant::Normal);
     1563    fontDescription.setVariantEastAsianWidth(FontVariantEastAsianWidth::Normal);
     1564    fontDescription.setVariantEastAsianRuby(FontVariantEastAsianRuby::Normal);
     1565    styleResolver.setFontDescription(fontDescription);
     1566}
     1567
     1568inline void StyleBuilderCustom::applyValueFontVariantEastAsian(StyleResolver& styleResolver, CSSValue& value)
     1569{
     1570    FontVariantEastAsianVariant variant = FontVariantEastAsianVariant::Normal;
     1571    FontVariantEastAsianWidth width = FontVariantEastAsianWidth::Normal;
     1572    FontVariantEastAsianRuby ruby = FontVariantEastAsianRuby::Normal;
     1573
     1574    if (is<CSSValueList>(value)) {
     1575        for (auto& item : downcast<CSSValueList>(value)) {
     1576            switch (downcast<CSSPrimitiveValue>(item.get()).getValueID()) {
     1577            case CSSValueJis78:
     1578                variant = FontVariantEastAsianVariant::Jis78;
     1579                break;
     1580            case CSSValueJis83:
     1581                variant = FontVariantEastAsianVariant::Jis83;
     1582                break;
     1583            case CSSValueJis90:
     1584                variant = FontVariantEastAsianVariant::Jis90;
     1585                break;
     1586            case CSSValueJis04:
     1587                variant = FontVariantEastAsianVariant::Jis04;
     1588                break;
     1589            case CSSValueSimplified:
     1590                variant = FontVariantEastAsianVariant::Simplified;
     1591                break;
     1592            case CSSValueTraditional:
     1593                variant = FontVariantEastAsianVariant::Traditional;
     1594                break;
     1595            case CSSValueFullWidth:
     1596                width = FontVariantEastAsianWidth::FullWidth;
     1597                break;
     1598            case CSSValueProportionalWidth:
     1599                width = FontVariantEastAsianWidth::ProportionalWidth;
     1600                break;
     1601            case CSSValueRuby:
     1602                ruby = FontVariantEastAsianRuby::Yes;
     1603                break;
     1604            default:
     1605                ASSERT_NOT_REACHED();
     1606                break;
     1607            }
     1608        }
     1609    } else
     1610        ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNormal);
     1611
     1612    auto fontDescription = styleResolver.fontDescription();
     1613    fontDescription.setVariantEastAsianVariant(variant);
     1614    fontDescription.setVariantEastAsianWidth(width);
     1615    fontDescription.setVariantEastAsianRuby(ruby);
    14531616    styleResolver.setFontDescription(fontDescription);
    14541617}
  • trunk/Source/WebCore/editing/cocoa/HTMLConverter.mm

    r189182 r190192  
    11571157    }
    11581158
    1159     String fontLigatures = _caches->propertyValueForNode(element, CSSPropertyWebkitFontVariantLigatures);
     1159    String fontLigatures = _caches->propertyValueForNode(element, CSSPropertyFontVariantLigatures);
    11601160    if (fontLigatures.length()) {
    11611161        if (fontLigatures.contains("normal"))
  • trunk/Source/WebCore/platform/graphics/FontCache.h

    r189830 r190192  
    3333#include "FontDescription.h"
    3434#include "Timer.h"
     35#include <array>
    3536#include <limits.h>
    3637#include <wtf/Forward.h>
     
    7475        : m_size(description.computedPixelSize())
    7576        , m_weight(description.weight())
    76         , m_flags(makeFlagKey(description))
     77        , m_flags(makeFlagsKey(description))
    7778        , m_locale(description.locale())
    7879        , m_featureSettings(description.featureSettings())
     
    8687    {
    8788        return m_size == other.m_size && m_weight == other.m_weight && m_flags == other.m_flags && m_locale == other.m_locale
    88             && ((m_featureSettings == other.m_featureSettings) || (m_featureSettings && other.m_featureSettings && m_featureSettings.get() == other.m_featureSettings.get()));
     89            && m_featureSettings == other.m_featureSettings;
    8990    }
    9091
     
    9899    inline unsigned computeHash() const
    99100    {
    100         unsigned toHash[] = {m_size, m_weight, m_flags, m_locale.isNull() ? 0 : m_locale.impl()->existingHash(), m_featureSettings ? m_featureSettings->hash() : 0};
    101         return StringHasher::hashMemory(toHash, sizeof(toHash));
     101        IntegerHasher hasher;
     102        hasher.add(m_size);
     103        hasher.add(m_weight);
     104        for (unsigned flagItem : m_flags)
     105            hasher.add(flagItem);
     106        hasher.add(m_locale.isNull() ? 0 : m_locale.impl()->existingHash());
     107        hasher.add(m_featureSettings.hash());
     108        return hasher.hash();
    102109    }
    103110
    104111private:
    105     static unsigned makeFlagKey(const FontDescription& description)
     112    static std::array<unsigned, 2> makeFlagsKey(const FontDescription& description)
    106113    {
    107114        static_assert(USCRIPT_CODE_LIMIT < 0x1000, "Script code must fit in an unsigned along with the other flags");
    108         return static_cast<unsigned>(description.script()) << 11
     115        unsigned first = static_cast<unsigned>(description.script()) << 11
    109116            | static_cast<unsigned>(description.textRenderingMode()) << 9
    110117            | static_cast<unsigned>(description.smallCaps()) << 8
     
    115122            | static_cast<unsigned>(description.italic()) << 1
    116123            | static_cast<unsigned>(description.renderingMode());
     124        unsigned second = static_cast<unsigned>(description.variantEastAsianRuby()) << 27
     125            | static_cast<unsigned>(description.variantEastAsianWidth()) << 25
     126            | static_cast<unsigned>(description.variantEastAsianVariant()) << 22
     127            | static_cast<unsigned>(description.variantAlternates()) << 21
     128            | static_cast<unsigned>(description.variantNumericSlashedZero()) << 20
     129            | static_cast<unsigned>(description.variantNumericOrdinal()) << 19
     130            | static_cast<unsigned>(description.variantNumericFraction()) << 17
     131            | static_cast<unsigned>(description.variantNumericSpacing()) << 15
     132            | static_cast<unsigned>(description.variantNumericFigure()) << 13
     133            | static_cast<unsigned>(description.variantCaps()) << 10
     134            | static_cast<unsigned>(description.variantPosition()) << 8
     135            | static_cast<unsigned>(description.variantContextualAlternates()) << 6
     136            | static_cast<unsigned>(description.variantHistoricalLigatures()) << 4
     137            | static_cast<unsigned>(description.variantDiscretionaryLigatures()) << 2
     138            | static_cast<unsigned>(description.variantCommonLigatures());
     139        return {{ first, second }};
    117140    }
    118141
     
    121144    unsigned m_size { 0 };
    122145    unsigned m_weight { 0 };
    123     unsigned m_flags { 0 };
     146    std::array<unsigned, 2> m_flags {{ 0, 0 }};
    124147    AtomicString m_locale;
    125     RefPtr<FontFeatureSettings> m_featureSettings;
     148    FontFeatureSettings m_featureSettings;
    126149};
    127150
     
    235258};
    236259
    237 RetainPtr<CTFontRef> preparePlatformFont(CTFontRef, TextRenderingMode, const FontFeatureSettings*);
     260RetainPtr<CTFontRef> preparePlatformFont(CTFontRef, TextRenderingMode, const FontFeatureSettings&, const FontVariantSettings&);
    238261FontWeight fontWeightFromCoreText(CGFloat weight);
    239262uint16_t toCoreTextFontWeight(FontWeight);
     
    242265SynthesisPair computeNecessarySynthesis(CTFontRef, const FontDescription&, bool isPlatformFont = false);
    243266RetainPtr<CTFontRef> platformFontWithFamilySpecialCase(const AtomicString& family, FontWeight, CTFontSymbolicTraits, float size);
    244 RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits, FontWeight, const FontFeatureSettings*, TextRenderingMode, float size);
     267RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits, FontWeight, TextRenderingMode, float size);
    245268RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef, FontWeight, const AtomicString& locale, const UChar* characters, unsigned length);
    246269bool requiresCustomFallbackFont(UChar32 character);
  • trunk/Source/WebCore/platform/graphics/FontCascade.cpp

    r189830 r190192  
    601601#endif
    602602
    603     if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
     603    // FIXME: This shouldn't be necessary because Font::applyTransforms() should perform all necessary shaping.
     604    if (m_fontDescription.featureSettings().size() > 0 || !m_fontDescription.variantSettings().isAllNormal())
    604605        return Complex;
    605606   
  • trunk/Source/WebCore/platform/graphics/FontCascade.h

    r189830 r190192  
    329329        }
    330330
    331         switch (m_fontDescription.commonLigaturesState()) {
    332         case FontCascadeDescription::DisabledLigaturesState:
     331        switch (m_fontDescription.variantCommonLigatures()) {
     332        case FontVariantLigatures::No:
    333333            features &= ~Ligatures;
    334334            break;
    335         case FontCascadeDescription::EnabledLigaturesState:
     335        case FontVariantLigatures::Yes:
    336336            features |= Ligatures;
    337337            break;
    338         case FontCascadeDescription::NormalLigaturesState:
     338        default:
    339339            break;
    340340        }
  • trunk/Source/WebCore/platform/graphics/FontDescription.cpp

    r189830 r190192  
    3636
    3737struct SameSizeAsFontCascadeDescription {
    38     void* pointers[3];
    39     float sizes[2];
    40     // FIXME: Make them fit into one word.
    41     uint32_t bitfields;
    42     uint32_t bitfields2 : 8;
     38    Vector<void*> vector;
     39    void* string;
     40    float size;
     41    unsigned bitfields1;
     42    unsigned bitfields2 : 22;
     43    void* array;
     44    float size2;
     45    unsigned bitfields3 : 10;
    4346};
    4447
     
    5659    , m_script(localeToScriptCodeForFontSelection(m_locale))
    5760    , m_fontSynthesis(FontSynthesisWeight | FontSynthesisStyle)
     61    , m_variantCommonLigatures(static_cast<unsigned>(FontVariantLigatures::Normal))
     62    , m_variantDiscretionaryLigatures(static_cast<unsigned>(FontVariantLigatures::Normal))
     63    , m_variantHistoricalLigatures(static_cast<unsigned>(FontVariantLigatures::Normal))
     64    , m_variantContextualAlternates(static_cast<unsigned>(FontVariantLigatures::Normal))
     65    , m_variantPosition(static_cast<unsigned>(FontVariantPosition::Normal))
     66    , m_variantCaps(static_cast<unsigned>(FontVariantCaps::Normal))
     67    , m_variantNumericFigure(static_cast<unsigned>(FontVariantNumericFigure::Normal))
     68    , m_variantNumericSpacing(static_cast<unsigned>(FontVariantNumericSpacing::Normal))
     69    , m_variantNumericFraction(static_cast<unsigned>(FontVariantNumericFraction::Normal))
     70    , m_variantNumericOrdinal(static_cast<unsigned>(FontVariantNumericOrdinal::Normal))
     71    , m_variantNumericSlashedZero(static_cast<unsigned>(FontVariantNumericSlashedZero::Normal))
     72    , m_variantAlternates(static_cast<unsigned>(FontVariantAlternates::Normal))
     73    , m_variantEastAsianVariant(static_cast<unsigned>(FontVariantEastAsianVariant::Normal))
     74    , m_variantEastAsianWidth(static_cast<unsigned>(FontVariantEastAsianWidth::Normal))
     75    , m_variantEastAsianRuby(static_cast<unsigned>(FontVariantEastAsianRuby::Normal))
    5876{
    5977}
     
    7694    : m_isAbsoluteSize(false)
    7795    , m_kerning(AutoKerning)
    78     , m_commonLigaturesState(NormalLigaturesState)
    79     , m_discretionaryLigaturesState(NormalLigaturesState)
    80     , m_historicalLigaturesState(NormalLigaturesState)
    8196    , m_keywordSize(0)
    8297    , m_fontSmoothing(AutoSmoothing)
  • trunk/Source/WebCore/platform/graphics/FontDescription.h

    r189830 r190192  
    6161    NonCJKGlyphOrientation nonCJKGlyphOrientation() const { return static_cast<NonCJKGlyphOrientation>(m_nonCJKGlyphOrientation); }
    6262    FontWidthVariant widthVariant() const { return static_cast<FontWidthVariant>(m_widthVariant); }
    63     FontFeatureSettings* featureSettings() const { return m_featureSettings.get(); }
     63    const FontFeatureSettings& featureSettings() const { return m_featureSettings; }
    6464    FontSynthesis fontSynthesis() const { return static_cast<FontSynthesis>(m_fontSynthesis); }
     65    FontVariantLigatures variantCommonLigatures() const { return static_cast<FontVariantLigatures>(m_variantCommonLigatures); }
     66    FontVariantLigatures variantDiscretionaryLigatures() const { return static_cast<FontVariantLigatures>(m_variantDiscretionaryLigatures); }
     67    FontVariantLigatures variantHistoricalLigatures() const { return static_cast<FontVariantLigatures>(m_variantHistoricalLigatures); }
     68    FontVariantLigatures variantContextualAlternates() const { return static_cast<FontVariantLigatures>(m_variantContextualAlternates); }
     69    FontVariantPosition variantPosition() const { return static_cast<FontVariantPosition>(m_variantPosition); }
     70    FontVariantCaps variantCaps() const { return static_cast<FontVariantCaps>(m_variantCaps); }
     71    FontVariantNumericFigure variantNumericFigure() const { return static_cast<FontVariantNumericFigure>(m_variantNumericFigure); }
     72    FontVariantNumericSpacing variantNumericSpacing() const { return static_cast<FontVariantNumericSpacing>(m_variantNumericSpacing); }
     73    FontVariantNumericFraction variantNumericFraction() const { return static_cast<FontVariantNumericFraction>(m_variantNumericFraction); }
     74    FontVariantNumericOrdinal variantNumericOrdinal() const { return static_cast<FontVariantNumericOrdinal>(m_variantNumericOrdinal); }
     75    FontVariantNumericSlashedZero variantNumericSlashedZero() const { return static_cast<FontVariantNumericSlashedZero>(m_variantNumericSlashedZero); }
     76    FontVariantAlternates variantAlternates() const { return static_cast<FontVariantAlternates>(m_variantAlternates); }
     77    FontVariantEastAsianVariant variantEastAsianVariant() const { return static_cast<FontVariantEastAsianVariant>(m_variantEastAsianVariant); }
     78    FontVariantEastAsianWidth variantEastAsianWidth() const { return static_cast<FontVariantEastAsianWidth>(m_variantEastAsianWidth); }
     79    FontVariantEastAsianRuby variantEastAsianRuby() const { return static_cast<FontVariantEastAsianRuby>(m_variantEastAsianRuby); }
     80    FontVariantSettings variantSettings() const
     81    {
     82        return { variantCommonLigatures(),
     83            variantDiscretionaryLigatures(),
     84            variantHistoricalLigatures(),
     85            variantContextualAlternates(),
     86            variantPosition(),
     87            variantCaps(),
     88            variantNumericFigure(),
     89            variantNumericSpacing(),
     90            variantNumericFraction(),
     91            variantNumericOrdinal(),
     92            variantNumericSlashedZero(),
     93            variantAlternates(),
     94            variantEastAsianVariant(),
     95            variantEastAsianWidth(),
     96            variantEastAsianRuby() };
     97    }
    6598
    6699    void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
     
    76109    void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; } // Make sure new callers of this sync with FontPlatformData::isForTextCombine()!
    77110    void setLocale(const AtomicString&);
    78     void setFeatureSettings(PassRefPtr<FontFeatureSettings> settings) { m_featureSettings = settings; }
     111    void setFeatureSettings(FontFeatureSettings&& settings) { m_featureSettings = WTF::move(settings); }
    79112    void setFontSynthesis(FontSynthesis fontSynthesis) { m_fontSynthesis = fontSynthesis; }
     113    void setVariantCommonLigatures(FontVariantLigatures variant) { m_variantCommonLigatures = static_cast<unsigned>(variant); }
     114    void setVariantDiscretionaryLigatures(FontVariantLigatures variant) { m_variantDiscretionaryLigatures = static_cast<unsigned>(variant); }
     115    void setVariantHistoricalLigatures(FontVariantLigatures variant) { m_variantHistoricalLigatures = static_cast<unsigned>(variant); }
     116    void setVariantContextualAlternates(FontVariantLigatures variant) { m_variantContextualAlternates = static_cast<unsigned>(variant); }
     117    void setVariantPosition(FontVariantPosition variant) { m_variantPosition = static_cast<unsigned>(variant); }
     118    void setVariantCaps(FontVariantCaps variant) { m_variantCaps = static_cast<unsigned>(variant); }
     119    void setVariantNumericFigure(FontVariantNumericFigure variant) { m_variantNumericFigure = static_cast<unsigned>(variant); }
     120    void setVariantNumericSpacing(FontVariantNumericSpacing variant) { m_variantNumericSpacing = static_cast<unsigned>(variant); }
     121    void setVariantNumericFraction(FontVariantNumericFraction variant) { m_variantNumericFraction = static_cast<unsigned>(variant); }
     122    void setVariantNumericOrdinal(FontVariantNumericOrdinal variant) { m_variantNumericOrdinal = static_cast<unsigned>(variant); }
     123    void setVariantNumericSlashedZero(FontVariantNumericSlashedZero variant) { m_variantNumericSlashedZero = static_cast<unsigned>(variant); }
     124    void setVariantAlternates(FontVariantAlternates variant) { m_variantAlternates = static_cast<unsigned>(variant); }
     125    void setVariantEastAsianVariant(FontVariantEastAsianVariant variant) { m_variantEastAsianVariant = static_cast<unsigned>(variant); }
     126    void setVariantEastAsianWidth(FontVariantEastAsianWidth variant) { m_variantEastAsianWidth = static_cast<unsigned>(variant); }
     127    void setVariantEastAsianRuby(FontVariantEastAsianRuby variant) { m_variantEastAsianRuby = static_cast<unsigned>(variant); }
    80128
    81129    FontTraitsMask traitsMask() const;
    82130
    83131private:
    84     RefPtr<FontFeatureSettings> m_featureSettings;
     132    FontFeatureSettings m_featureSettings;
    85133    AtomicString m_locale;
    86134
     
    96144    unsigned m_script : 7; // Used to help choose an appropriate font for generic font families.
    97145    unsigned m_fontSynthesis : 2; // FontSynthesis type
     146    unsigned m_variantCommonLigatures : 2; // FontVariantLigatures
     147    unsigned m_variantDiscretionaryLigatures : 2; // FontVariantLigatures
     148    unsigned m_variantHistoricalLigatures : 2; // FontVariantLigatures
     149    unsigned m_variantContextualAlternates : 2; // FontVariantLigatures
     150    unsigned m_variantPosition : 2; // FontVariantPosition
     151    unsigned m_variantCaps : 3; // FontVariantCaps
     152    unsigned m_variantNumericFigure : 2; // FontVariantNumericFigure
     153    unsigned m_variantNumericSpacing : 2; // FontVariantNumericSpacing
     154    unsigned m_variantNumericFraction : 2; // FontVariantNumericFraction
     155    unsigned m_variantNumericOrdinal : 1; // FontVariantNumericOrdinal
     156    unsigned m_variantNumericSlashedZero : 1; // FontVariantNumericSlashedZero
     157    unsigned m_variantAlternates : 1; // FontVariantAlternates
     158    unsigned m_variantEastAsianVariant : 3; // FontVariantEastAsianVariant
     159    unsigned m_variantEastAsianWidth : 2; // FontVariantEastAsianWidth
     160    unsigned m_variantEastAsianRuby : 1; // FontVariantEastAsianRuby
    98161};
    99162
     
    111174        && m_locale == other.m_locale
    112175        && m_featureSettings == other.m_featureSettings
    113         && m_fontSynthesis == other.m_fontSynthesis;
     176        && m_fontSynthesis == other.m_fontSynthesis
     177        && m_variantCommonLigatures == other.m_variantCommonLigatures
     178        && m_variantDiscretionaryLigatures == other.m_variantDiscretionaryLigatures
     179        && m_variantHistoricalLigatures == other.m_variantHistoricalLigatures
     180        && m_variantContextualAlternates == other.m_variantContextualAlternates
     181        && m_variantPosition == other.m_variantPosition
     182        && m_variantCaps == other.m_variantCaps
     183        && m_variantNumericFigure == other.m_variantNumericFigure
     184        && m_variantNumericSpacing == other.m_variantNumericSpacing
     185        && m_variantNumericFraction == other.m_variantNumericFraction
     186        && m_variantNumericOrdinal == other.m_variantNumericOrdinal
     187        && m_variantNumericSlashedZero == other.m_variantNumericSlashedZero
     188        && m_variantAlternates == other.m_variantAlternates
     189        && m_variantEastAsianVariant == other.m_variantEastAsianVariant
     190        && m_variantEastAsianWidth == other.m_variantEastAsianWidth
     191        && m_variantEastAsianRuby == other.m_variantEastAsianRuby;
    114192}
    115193
     
    119197    enum Kerning { AutoKerning, NormalKerning, NoneKerning };
    120198
    121     enum LigaturesState { NormalLigaturesState, DisabledLigaturesState, EnabledLigaturesState };
    122 
    123199    FontCascadeDescription();
    124200
     
    140216
    141217    Kerning kerning() const { return static_cast<Kerning>(m_kerning); }
    142     LigaturesState commonLigaturesState() const { return static_cast<LigaturesState>(m_commonLigaturesState); }
    143     LigaturesState discretionaryLigaturesState() const { return static_cast<LigaturesState>(m_discretionaryLigaturesState); }
    144     LigaturesState historicalLigaturesState() const { return static_cast<LigaturesState>(m_historicalLigaturesState); }
    145218    unsigned keywordSize() const { return m_keywordSize; }
    146219    CSSValueID keywordSizeAsIdentifier() const
     
    159232    void setIsAbsoluteSize(bool s) { m_isAbsoluteSize = s; }
    160233    void setKerning(Kerning kerning) { m_kerning = kerning; }
    161     void setCommonLigaturesState(LigaturesState commonLigaturesState) { m_commonLigaturesState = commonLigaturesState; }
    162     void setDiscretionaryLigaturesState(LigaturesState discretionaryLigaturesState) { m_discretionaryLigaturesState = discretionaryLigaturesState; }
    163     void setHistoricalLigaturesState(LigaturesState historicalLigaturesState) { m_historicalLigaturesState = historicalLigaturesState; }
    164234    void setKeywordSize(unsigned size)
    165235    {
     
    197267    static FontSynthesis initialFontSynthesis() { return FontSynthesisWeight | FontSynthesisStyle; }
    198268    static const AtomicString& initialLocale() { return nullAtom; }
     269    static FontVariantPosition initialVariantPosition() { return FontVariantPosition::Normal; }
     270    static FontVariantCaps initialVariantCaps() { return FontVariantCaps::Normal; }
     271    static FontVariantAlternates initialVariantAlternates() { return FontVariantAlternates::Normal; }
    199272
    200273private:
     
    206279                                  // (logical sizes like "medium" don't count).
    207280    unsigned m_kerning : 2; // Kerning
    208     unsigned m_commonLigaturesState : 2;
    209     unsigned m_discretionaryLigaturesState : 2;
    210     unsigned m_historicalLigaturesState : 2;
    211281
    212282    unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium).  If so,
     
    225295        && m_isAbsoluteSize == other.m_isAbsoluteSize
    226296        && m_kerning == other.m_kerning
    227         && m_commonLigaturesState == other.m_commonLigaturesState
    228         && m_discretionaryLigaturesState == other.m_discretionaryLigaturesState
    229         && m_historicalLigaturesState == other.m_historicalLigaturesState
    230297        && m_keywordSize == other.m_keywordSize
    231298        && m_fontSmoothing == other.m_fontSmoothing
  • trunk/Source/WebCore/platform/graphics/FontFeatureSettings.cpp

    r188557 r190192  
    3131namespace WebCore {
    3232
    33 FontFeature::FontFeature(const AtomicString& tag, int value)
     33FontFeature::FontFeature(const FontFeatureTag& tag, int value)
    3434    : m_tag(tag)
     35    , m_value(value)
     36{
     37}
     38
     39FontFeature::FontFeature(FontFeatureTag&& tag, int value)
     40    : m_tag(WTF::move(tag))
    3541    , m_value(value)
    3642{
     
    4450bool FontFeature::operator<(const FontFeature& other) const
    4551{
    46     return (m_tag.impl() < other.m_tag.impl()) || (m_tag.impl() == other.m_tag.impl() && m_value < other.m_value);
    47 }
    48 
    49 Ref<FontFeatureSettings> FontFeatureSettings::create()
    50 {
    51     return adoptRef(*new FontFeatureSettings);
     52    return (m_tag < other.m_tag) || (m_tag == other.m_tag && m_value < other.m_value);
    5253}
    5354
     
    6768    IntegerHasher hasher;
    6869    for (auto& feature : m_list) {
    69         hasher.add(feature.tag().impl()->existingHash());
     70        hasher.add(FontFeatureTagHash::hash(feature.tag()));
    7071        hasher.add(feature.value());
    7172    }
  • trunk/Source/WebCore/platform/graphics/FontFeatureSettings.h

    r188557 r190192  
    2727#define FontFeatureSettings_h
    2828
     29#include <array>
    2930#include <wtf/PassRefPtr.h>
    3031#include <wtf/RefCounted.h>
     
    3536namespace WebCore {
    3637
     38typedef std::array<char, 4> FontFeatureTag;
     39
     40inline FontFeatureTag fontFeatureTag(const char arr[4]) { return {{ arr[0], arr[1], arr[2], arr[3] }}; }
     41
     42struct FontFeatureTagHash {
     43    static unsigned hash(const FontFeatureTag& characters) { return (characters[0] << 24) | (characters[1] << 16) | (characters[2] << 8) | characters[3]; }
     44    static bool equal(const FontFeatureTag& a, const FontFeatureTag& b) { return a == b; }
     45    static const bool safeToCompareToEmptyOrDeleted = true;
     46};
     47
     48struct FontFeatureTagHashTraits : WTF::GenericHashTraits<FontFeatureTag> {
     49    static const bool emptyValueIsZero = true;
     50    static void constructDeletedValue(FontFeatureTag& slot) { new (NotNull, std::addressof(slot)) FontFeatureTag({{ -1, -1, -1, -1 }}); }
     51    static bool isDeletedValue(const FontFeatureTag& value) { return value == FontFeatureTag({{ -1, -1, -1, -1 }}); }
     52};
     53
    3754class FontFeature {
    3855public:
    39     FontFeature(const AtomicString& tag, int value);
     56    FontFeature() = delete;
     57    FontFeature(const FontFeatureTag&, int value);
     58    FontFeature(FontFeatureTag&&, int value);
    4059
    4160    bool operator==(const FontFeature& other) const;
    4261    bool operator<(const FontFeature& other) const;
    4362
    44     const AtomicString& tag() const { return m_tag; }
     63    const FontFeatureTag& tag() const { return m_tag; }
    4564    int value() const { return m_value; }
    4665    bool enabled() const { return value(); }
    4766
    4867private:
    49     AtomicString m_tag;
    50     const int m_value { 0 };
     68    FontFeatureTag m_tag;
     69    int m_value;
    5170};
    5271
    53 class FontFeatureSettings : public RefCounted<FontFeatureSettings> {
     72class FontFeatureSettings {
    5473public:
    55     static Ref<FontFeatureSettings> create();
    56 
    5774    void insert(FontFeature&&);
     75    bool operator==(const FontFeatureSettings& other) const { return m_list == other.m_list; }
    5876
    5977    size_t size() const { return m_list.size(); }
     
    6179    const FontFeature& at(size_t index) const { return m_list.at(index); }
    6280
     81    Vector<FontFeature>::const_iterator begin() const { return m_list.begin(); }
     82    Vector<FontFeature>::const_iterator end() const { return m_list.end(); }
     83
    6384    unsigned hash() const;
    6485
    6586private:
    66     FontFeatureSettings() { }
    6787    Vector<FontFeature> m_list;
    6888};
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

    r189830 r190192  
    4848}
    4949
     50static inline bool tagEquals(FontFeatureTag tag, const char comparison[4])
     51{
     52    return equalIgnoringASCIICase(tag.data(), comparison, 4);
     53}
     54
    5055static inline void appendTrueTypeFeature(CFMutableArrayRef features, const FontFeature& feature)
    5156{
    52     if (equalIgnoringASCIICase(feature.tag(), "liga") || equalIgnoringASCIICase(feature.tag(), "clig")) {
     57    if (tagEquals(feature.tag(), "liga") || tagEquals(feature.tag(), "clig")) {
    5358        if (feature.enabled()) {
    5459            appendRawTrueTypeFeature(features, kLigaturesType, kCommonLigaturesOnSelector);
     
    5863            appendRawTrueTypeFeature(features, kLigaturesType, kContextualLigaturesOffSelector);
    5964        }
    60     } else if (equalIgnoringASCIICase(feature.tag(), "dlig")) {
     65    } else if (tagEquals(feature.tag(), "dlig")) {
    6166        if (feature.enabled())
    6267            appendRawTrueTypeFeature(features, kLigaturesType, kRareLigaturesOnSelector);
    6368        else
    6469            appendRawTrueTypeFeature(features, kLigaturesType, kRareLigaturesOffSelector);
    65     } else if (equalIgnoringASCIICase(feature.tag(), "hlig")) {
     70    } else if (tagEquals(feature.tag(), "hlig")) {
    6671        if (feature.enabled())
    6772            appendRawTrueTypeFeature(features, kLigaturesType, kHistoricalLigaturesOnSelector);
    6873        else
    6974            appendRawTrueTypeFeature(features, kLigaturesType, kHistoricalLigaturesOffSelector);
    70     } else if (equalIgnoringASCIICase(feature.tag(), "calt")) {
     75    } else if (tagEquals(feature.tag(), "calt")) {
    7176        if (feature.enabled())
    7277            appendRawTrueTypeFeature(features, kContextualAlternatesType, kContextualAlternatesOnSelector);
    7378        else
    7479            appendRawTrueTypeFeature(features, kContextualAlternatesType, kContextualAlternatesOffSelector);
    75     } else if (equalIgnoringASCIICase(feature.tag(), "subs") && feature.enabled())
     80    } else if (tagEquals(feature.tag(), "subs") && feature.enabled())
    7681        appendRawTrueTypeFeature(features, kVerticalPositionType, kInferiorsSelector);
    77     else if (equalIgnoringASCIICase(feature.tag(), "sups") && feature.enabled())
     82    else if (tagEquals(feature.tag(), "sups") && feature.enabled())
    7883        appendRawTrueTypeFeature(features, kVerticalPositionType, kSuperiorsSelector);
    79     else if (equalIgnoringASCIICase(feature.tag(), "smcp") && feature.enabled())
     84    else if (tagEquals(feature.tag(), "smcp") && feature.enabled())
    8085        appendRawTrueTypeFeature(features, kLowerCaseType, kLowerCaseSmallCapsSelector);
    81     else if (equalIgnoringASCIICase(feature.tag(), "c2sc") && feature.enabled())
     86    else if (tagEquals(feature.tag(), "c2sc") && feature.enabled())
    8287        appendRawTrueTypeFeature(features, kUpperCaseType, kUpperCaseSmallCapsSelector);
    83     else if (equalIgnoringASCIICase(feature.tag(), "pcap") && feature.enabled())
     88    else if (tagEquals(feature.tag(), "pcap") && feature.enabled())
    8489        appendRawTrueTypeFeature(features, kLowerCaseType, kLowerCasePetiteCapsSelector);
    85     else if (equalIgnoringASCIICase(feature.tag(), "c2pc") && feature.enabled())
     90    else if (tagEquals(feature.tag(), "c2pc") && feature.enabled())
    8691        appendRawTrueTypeFeature(features, kUpperCaseType, kUpperCasePetiteCapsSelector);
    87     else if (equalIgnoringASCIICase(feature.tag(), "unic") && feature.enabled())
     92    else if (tagEquals(feature.tag(), "unic") && feature.enabled())
    8893        appendRawTrueTypeFeature(features, kLetterCaseType, 14);
    89     else if (equalIgnoringASCIICase(feature.tag(), "titl") && feature.enabled())
     94    else if (tagEquals(feature.tag(), "titl") && feature.enabled())
    9095        appendRawTrueTypeFeature(features, kStyleOptionsType, kTitlingCapsSelector);
    91     else if (equalIgnoringASCIICase(feature.tag(), "lnum") && feature.enabled())
     96    else if (tagEquals(feature.tag(), "lnum") && feature.enabled())
    9297        appendRawTrueTypeFeature(features, kNumberCaseType, kUpperCaseNumbersSelector);
    93     else if (equalIgnoringASCIICase(feature.tag(), "onum") && feature.enabled())
     98    else if (tagEquals(feature.tag(), "onum") && feature.enabled())
    9499        appendRawTrueTypeFeature(features, kNumberCaseType, kLowerCaseNumbersSelector);
    95     else if (equalIgnoringASCIICase(feature.tag(), "pnum") && feature.enabled())
     100    else if (tagEquals(feature.tag(), "pnum") && feature.enabled())
    96101        appendRawTrueTypeFeature(features, kNumberSpacingType, kProportionalNumbersSelector);
    97     else if (equalIgnoringASCIICase(feature.tag(), "tnum") && feature.enabled())
     102    else if (tagEquals(feature.tag(), "tnum") && feature.enabled())
    98103        appendRawTrueTypeFeature(features, kNumberSpacingType, kMonospacedNumbersSelector);
    99     else if (equalIgnoringASCIICase(feature.tag(), "frac") && feature.enabled())
     104    else if (tagEquals(feature.tag(), "frac") && feature.enabled())
    100105        appendRawTrueTypeFeature(features, kFractionsType, kDiagonalFractionsSelector);
    101     else if (equalIgnoringASCIICase(feature.tag(), "afrc") && feature.enabled())
     106    else if (tagEquals(feature.tag(), "afrc") && feature.enabled())
    102107        appendRawTrueTypeFeature(features, kFractionsType, kVerticalFractionsSelector);
    103     else if (equalIgnoringASCIICase(feature.tag(), "ordn") && feature.enabled())
     108    else if (tagEquals(feature.tag(), "ordn") && feature.enabled())
    104109        appendRawTrueTypeFeature(features, kVerticalPositionType, kOrdinalsSelector);
    105     else if (equalIgnoringASCIICase(feature.tag(), "zero") && feature.enabled())
     110    else if (tagEquals(feature.tag(), "zero") && feature.enabled())
    106111        appendRawTrueTypeFeature(features, kTypographicExtrasType, kSlashedZeroOnSelector);
    107     else if (equalIgnoringASCIICase(feature.tag(), "hist") && feature.enabled())
     112    else if (tagEquals(feature.tag(), "hist") && feature.enabled())
    108113        appendRawTrueTypeFeature(features, kLigaturesType, kHistoricalLigaturesOnSelector);
    109     else if (equalIgnoringASCIICase(feature.tag(), "jp78") && feature.enabled())
     114    else if (tagEquals(feature.tag(), "jp78") && feature.enabled())
    110115        appendRawTrueTypeFeature(features, kCharacterShapeType, kJIS1978CharactersSelector);
    111     else if (equalIgnoringASCIICase(feature.tag(), "jp83") && feature.enabled())
     116    else if (tagEquals(feature.tag(), "jp83") && feature.enabled())
    112117        appendRawTrueTypeFeature(features, kCharacterShapeType, kJIS1983CharactersSelector);
    113     else if (equalIgnoringASCIICase(feature.tag(), "jp90") && feature.enabled())
     118    else if (tagEquals(feature.tag(), "jp90") && feature.enabled())
    114119        appendRawTrueTypeFeature(features, kCharacterShapeType, kJIS1990CharactersSelector);
    115     else if (equalIgnoringASCIICase(feature.tag(), "jp04") && feature.enabled())
     120    else if (tagEquals(feature.tag(), "jp04") && feature.enabled())
    116121        appendRawTrueTypeFeature(features, kCharacterShapeType, kJIS2004CharactersSelector);
    117     else if (equalIgnoringASCIICase(feature.tag(), "smpl") && feature.enabled())
     122    else if (tagEquals(feature.tag(), "smpl") && feature.enabled())
    118123        appendRawTrueTypeFeature(features, kCharacterShapeType, kSimplifiedCharactersSelector);
    119     else if (equalIgnoringASCIICase(feature.tag(), "trad") && feature.enabled())
     124    else if (tagEquals(feature.tag(), "trad") && feature.enabled())
    120125        appendRawTrueTypeFeature(features, kCharacterShapeType, kTraditionalCharactersSelector);
    121     else if (equalIgnoringASCIICase(feature.tag(), "fwid") && feature.enabled())
     126    else if (tagEquals(feature.tag(), "fwid") && feature.enabled())
    122127        appendRawTrueTypeFeature(features, kTextSpacingType, kMonospacedTextSelector);
    123     else if (equalIgnoringASCIICase(feature.tag(), "pwid") && feature.enabled())
     128    else if (tagEquals(feature.tag(), "pwid") && feature.enabled())
    124129        appendRawTrueTypeFeature(features, kTextSpacingType, kProportionalTextSelector);
    125     else if (equalIgnoringASCIICase(feature.tag(), "ruby") && feature.enabled())
     130    else if (tagEquals(feature.tag(), "ruby") && feature.enabled())
    126131        appendRawTrueTypeFeature(features, kRubyKanaType, kRubyKanaOnSelector);
    127132}
     
    130135{
    131136#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000)
    132     RetainPtr<CFStringRef> featureKey = feature.tag().string().createCFString();
     137    RetainPtr<CFStringRef> featureKey = adoptCF(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(feature.tag().data()), feature.tag().size() * sizeof(FontFeatureTag::value_type), kCFStringEncodingASCII, false));
    133138    int rawFeatureValue = feature.value();
    134139    RetainPtr<CFNumberRef> featureValue = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rawFeatureValue));
     
    143148}
    144149
    145 RetainPtr<CTFontRef> preparePlatformFont(CTFontRef originalFont, TextRenderingMode textRenderingMode, const FontFeatureSettings* features)
    146 {
    147     if (!originalFont || ((!features || !features->size()) && (textRenderingMode != OptimizeLegibility)))
     150typedef HashMap<FontFeatureTag, int, FontFeatureTagHash, FontFeatureTagHashTraits> FeaturesMap;
     151
     152static FeaturesMap computeFeatureSettingsFromVariants(const FontVariantSettings& variantSettings)
     153{
     154    FeaturesMap result;
     155
     156    switch (variantSettings.commonLigatures) {
     157    case FontVariantLigatures::Yes:
     158        result.add(fontFeatureTag("liga"), 1);
     159        result.add(fontFeatureTag("clig"), 1);
     160        break;
     161    case FontVariantLigatures::No:
     162        result.add(fontFeatureTag("liga"), 0);
     163        result.add(fontFeatureTag("clig"), 0);
     164        break;
     165    default:
     166        break;
     167    }
     168
     169    switch (variantSettings.discretionaryLigatures) {
     170    case FontVariantLigatures::Yes:
     171        result.add(fontFeatureTag("dlig"), 1);
     172        break;
     173    case FontVariantLigatures::No:
     174        result.add(fontFeatureTag("dlig"), 0);
     175        break;
     176    default:
     177        break;
     178    }
     179
     180    switch (variantSettings.historicalLigatures) {
     181    case FontVariantLigatures::Yes:
     182        result.add(fontFeatureTag("hlig"), 1);
     183        break;
     184    case FontVariantLigatures::No:
     185        result.add(fontFeatureTag("hlig"), 0);
     186        break;
     187    default:
     188        break;
     189    }
     190
     191    switch (variantSettings.contextualAlternates) {
     192    case FontVariantLigatures::Yes:
     193        result.add(fontFeatureTag("calt"), 1);
     194        break;
     195    case FontVariantLigatures::No:
     196        result.add(fontFeatureTag("calt"), 0);
     197        break;
     198    default:
     199        break;
     200    }
     201
     202    switch (variantSettings.position) {
     203    case FontVariantPosition::Subscript:
     204        result.add(fontFeatureTag("subs"), 1);
     205        break;
     206    case FontVariantPosition::Superscript:
     207        result.add(fontFeatureTag("sups"), 1);
     208        break;
     209    default:
     210        break;
     211    }
     212
     213    switch (variantSettings.caps) {
     214    case FontVariantCaps::AllSmall:
     215        result.add(fontFeatureTag("c2sc"), 1);
     216        FALLTHROUGH;
     217    case FontVariantCaps::Small:
     218        result.add(fontFeatureTag("smcp"), 1);
     219        break;
     220    case FontVariantCaps::AllPetite:
     221        result.add(fontFeatureTag("c2pc"), 1);
     222        FALLTHROUGH;
     223    case FontVariantCaps::Petite:
     224        result.add(fontFeatureTag("pcap"), 1);
     225        break;
     226    case FontVariantCaps::Unicase:
     227        result.add(fontFeatureTag("unic"), 1);
     228        break;
     229    case FontVariantCaps::Titling:
     230        result.add(fontFeatureTag("titl"), 1);
     231        break;
     232    default:
     233        break;
     234    }
     235
     236    switch (variantSettings.numericFigure) {
     237    case FontVariantNumericFigure::LiningNumbers:
     238        result.add(fontFeatureTag("lnum"), 1);
     239        break;
     240    case FontVariantNumericFigure::OldStyleNumbers:
     241        result.add(fontFeatureTag("onum"), 1);
     242        break;
     243    default:
     244        break;
     245    }
     246
     247    switch (variantSettings.numericSpacing) {
     248    case FontVariantNumericSpacing::ProportionalNumbers:
     249        result.add(fontFeatureTag("pnum"), 1);
     250        break;
     251    case FontVariantNumericSpacing::TabularNumbers:
     252        result.add(fontFeatureTag("tnum"), 1);
     253        break;
     254    default:
     255        break;
     256    }
     257
     258    switch (variantSettings.numericFraction) {
     259    case FontVariantNumericFraction::DiagonalFractions:
     260        result.add(fontFeatureTag("frac"), 1);
     261        break;
     262    case FontVariantNumericFraction::StackedFractions:
     263        result.add(fontFeatureTag("afrc"), 1);
     264        break;
     265    default:
     266        break;
     267    }
     268
     269    if (variantSettings.numericOrdinal == FontVariantNumericOrdinal::Yes)
     270        result.add(fontFeatureTag("ordn"), 1);
     271    if (variantSettings.numericSlashedZero == FontVariantNumericSlashedZero::Yes)
     272        result.add(fontFeatureTag("zero"), 1);
     273
     274    switch (variantSettings.alternates) {
     275    case FontVariantAlternates::HistoricalForms:
     276        result.add(fontFeatureTag("hist"), 1);
     277        break;
     278    default:
     279        break;
     280    }
     281
     282    switch (variantSettings.eastAsianVariant) {
     283    case FontVariantEastAsianVariant::Jis78:
     284        result.add(fontFeatureTag("jp78"), 1);
     285        break;
     286    case FontVariantEastAsianVariant::Jis83:
     287        result.add(fontFeatureTag("jp83"), 1);
     288        break;
     289    case FontVariantEastAsianVariant::Jis90:
     290        result.add(fontFeatureTag("jp90"), 1);
     291        break;
     292    case FontVariantEastAsianVariant::Jis04:
     293        result.add(fontFeatureTag("jp04"), 1);
     294        break;
     295    case FontVariantEastAsianVariant::Simplified:
     296        result.add(fontFeatureTag("smpl"), 1);
     297        break;
     298    case FontVariantEastAsianVariant::Traditional:
     299        result.add(fontFeatureTag("trad"), 1);
     300        break;
     301    default:
     302        break;
     303    }
     304
     305    switch (variantSettings.eastAsianWidth) {
     306    case FontVariantEastAsianWidth::FullWidth:
     307        result.add(fontFeatureTag("fwid"), 1);
     308        break;
     309    case FontVariantEastAsianWidth::ProportionalWidth:
     310        result.add(fontFeatureTag("pwid"), 1);
     311        break;
     312    default:
     313        break;
     314    }
     315
     316    if (variantSettings.eastAsianRuby == FontVariantEastAsianRuby::Yes)
     317        result.add(fontFeatureTag("ruby"), 1);
     318
     319    return result;
     320}
     321
     322RetainPtr<CTFontRef> preparePlatformFont(CTFontRef originalFont, TextRenderingMode textRenderingMode, const FontFeatureSettings& features, const FontVariantSettings& variantSettings)
     323{
     324    if (!originalFont || (!features.size() && (textRenderingMode != OptimizeLegibility) && variantSettings.isAllNormal()))
    148325        return originalFont;
    149326
     327    // FIXME: We don't consult with the @font-face first, like the spec says we should.
     328
     329    // Spec says that font-feature-settings should override font-variant-*.
     330    auto fontFeatureSettingsFromVariants = computeFeatureSettingsFromVariants(variantSettings);
     331    for (auto& newFeature : features)
     332        fontFeatureSettingsFromVariants.set(newFeature.tag(), newFeature.value());
     333
    150334    RetainPtr<CFMutableDictionaryRef> attributes = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    151     if (features && features->size()) {
    152         RetainPtr<CFMutableArrayRef> featureArray = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, features->size(), &kCFTypeArrayCallBacks));
    153         for (size_t i = 0; i < features->size(); ++i) {
    154             appendTrueTypeFeature(featureArray.get(), features->at(i));
    155             appendOpenTypeFeature(featureArray.get(), features->at(i));
     335    if (fontFeatureSettingsFromVariants.size()) {
     336        RetainPtr<CFMutableArrayRef> featureArray = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, features.size(), &kCFTypeArrayCallBacks));
     337        for (auto& p : fontFeatureSettingsFromVariants) {
     338            auto feature = FontFeature(p.key, p.value);
     339            appendTrueTypeFeature(featureArray.get(), feature);
     340            appendOpenTypeFeature(featureArray.get(), feature);
    156341        }
    157342        CFDictionaryAddValue(attributes.get(), kCTFontFeatureSettingsAttribute, featureArray.get());
     
    411596
    412597#if ENABLE(PLATFORM_FONT_LOOKUP)
    413 static RetainPtr<CTFontRef> platformFontLookupWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, const FontFeatureSettings* featureSettings, TextRenderingMode textRenderingMode, float size)
     598static RetainPtr<CTFontRef> platformFontLookupWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, const FontFeatureSettings& featureSettings, const FontVariantSettings& variantSettings, TextRenderingMode textRenderingMode, float size)
    414599{
    415600    const auto& whitelist = fontWhitelist();
     
    418603
    419604    auto foundFont = adoptCF(CTFontCreateForCSS(family.string().createCFString().get(), toCoreTextFontWeight(weight), requestedTraits, size));
    420     return preparePlatformFont(foundFont.get(), textRenderingMode, featureSettings);
    421 }
    422 #endif
    423 
    424 static RetainPtr<CTFontRef> fontWithFamily(const AtomicString& family, CTFontSymbolicTraits desiredTraits, FontWeight weight, const FontFeatureSettings* featureSettings, TextRenderingMode textRenderingMode, float size)
     605    return preparePlatformFont(foundFont.get(), textRenderingMode, featureSettings, variantSettings);
     606}
     607#endif
     608
     609static RetainPtr<CTFontRef> fontWithFamily(const AtomicString& family, CTFontSymbolicTraits desiredTraits, FontWeight weight, const FontFeatureSettings& featureSettings, const FontVariantSettings& variantSettings, const TextRenderingMode& textRenderingMode, float size)
    425610{
    426611    if (family.isEmpty())
     
    429614        return specialCase;
    430615#if ENABLE(PLATFORM_FONT_LOOKUP)
    431     return platformFontLookupWithFamily(family, desiredTraits, weight, featureSettings, textRenderingMode, size);
     616    return platformFontLookupWithFamily(family, desiredTraits, weight, featureSettings, variantSettings, textRenderingMode, size);
    432617#else
    433     return platformFontWithFamily(family, desiredTraits, weight, featureSettings, textRenderingMode, size);
     618    UNUSED_PARAM(featureSettings);
     619    UNUSED_PARAM(variantSettings);
     620    return platformFontWithFamily(family, desiredTraits, weight, textRenderingMode, size);
    434621#endif
    435622}
     
    472659    float size = fontDescription.computedPixelSize();
    473660
    474     RetainPtr<CTFontRef> font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
     661    RetainPtr<CTFontRef> font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontDescription.textRenderingMode(), size);
    475662
    476663#if PLATFORM(MAC)
     
    483670        autoActivateFont(family.string(), size);
    484671
    485         font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
     672        font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontDescription.textRenderingMode(), size);
    486673    }
    487674#endif
     
    527714    const FontPlatformData& platformData = originalFontData->platformData();
    528715    RetainPtr<CTFontRef> result = platformLookupFallbackFont(platformData.font(), description.weight(), description.locale(), characters, length);
    529     result = preparePlatformFont(result.get(), description.textRenderingMode(), description.featureSettings());
     716    result = preparePlatformFont(result.get(), description.textRenderingMode(), description.featureSettings(), description.variantSettings());
    530717    if (!result)
    531718        return lastResortFallbackFont(description);
  • trunk/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzShaper.cpp

    r189830 r190192  
    353353    }
    354354
    355     FontFeatureSettings* settings = description.featureSettings();
    356     if (!settings)
    357         return;
    358 
    359     unsigned numFeatures = settings->size();
     355    const FontFeatureSettings& settings = description.featureSettings();
     356
     357    unsigned numFeatures = settings.size();
    360358    for (unsigned i = 0; i < numFeatures; ++i) {
    361359        hb_feature_t feature;
    362         auto& tag = settings->at(i).tag();
     360        auto& tag = settings[i].tag();
    363361        feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
    364         feature.value = settings->at(i).value();
     362        feature.value = settings[i].value();
    365363        feature.start = 0;
    366364        feature.end = static_cast<unsigned>(-1);
  • trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm

    r188877 r190192  
    255255
    256256#if !ENABLE(PLATFORM_FONT_LOOKUP)
    257 RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, const FontFeatureSettings*, TextRenderingMode, float size)
     257RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, TextRenderingMode, float size)
    258258{
    259259    NSFontManager *fontManager = [NSFontManager sharedFontManager];
  • trunk/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp

    r188591 r190192  
    4242#if CORETEXT_WEB_FONTS
    4343    RetainPtr<CTFontRef> font = adoptCF(CTFontCreateWithFontDescriptor(m_fontDescriptor.get(), size, nullptr));
    44     font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings());
     44    font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings(), fontDescription.variantSettings());
    4545    return FontPlatformData(font.get(), size, bold, italic, orientation, widthVariant, fontDescription.textRenderingMode());
    4646#else
  • trunk/Source/WebCore/platform/text/TextFlags.h

    r185632 r190192  
    7373const unsigned FontSynthesisWidth = 2;
    7474
     75enum class FontVariantLigatures {
     76    Normal,
     77    Yes,
     78    No
     79};
     80
     81enum class FontVariantPosition {
     82    Normal,
     83    Subscript,
     84    Superscript
     85};
     86
     87enum class FontVariantCaps {
     88    Normal,
     89    Small,
     90    AllSmall,
     91    Petite,
     92    AllPetite,
     93    Unicase,
     94    Titling
     95};
     96
     97enum class FontVariantNumericFigure {
     98    Normal,
     99    LiningNumbers,
     100    OldStyleNumbers
     101};
     102
     103enum class FontVariantNumericSpacing {
     104    Normal,
     105    ProportionalNumbers,
     106    TabularNumbers
     107};
     108
     109enum class FontVariantNumericFraction {
     110    Normal,
     111    DiagonalFractions,
     112    StackedFractions
     113};
     114
     115enum class FontVariantNumericOrdinal {
     116    Normal,
     117    Yes
     118};
     119
     120enum class FontVariantNumericSlashedZero {
     121    Normal,
     122    Yes
     123};
     124
     125enum class FontVariantAlternates {
     126    Normal,
     127    HistoricalForms
     128};
     129
     130enum class FontVariantEastAsianVariant {
     131    Normal,
     132    Jis78,
     133    Jis83,
     134    Jis90,
     135    Jis04,
     136    Simplified,
     137    Traditional
     138};
     139
     140enum class FontVariantEastAsianWidth {
     141    Normal,
     142    FullWidth,
     143    ProportionalWidth
     144};
     145
     146enum class FontVariantEastAsianRuby {
     147    Normal,
     148    Yes
     149};
     150
     151struct FontVariantSettings {
     152    bool isAllNormal() const
     153    {
     154        return commonLigatures == FontVariantLigatures::Normal
     155            && discretionaryLigatures == FontVariantLigatures::Normal
     156            && historicalLigatures == FontVariantLigatures::Normal
     157            && contextualAlternates == FontVariantLigatures::Normal
     158            && position == FontVariantPosition::Normal
     159            && caps == FontVariantCaps::Normal
     160            && numericFigure == FontVariantNumericFigure::Normal
     161            && numericSpacing == FontVariantNumericSpacing::Normal
     162            && numericFraction == FontVariantNumericFraction::Normal
     163            && numericOrdinal == FontVariantNumericOrdinal::Normal
     164            && numericSlashedZero == FontVariantNumericSlashedZero::Normal
     165            && alternates == FontVariantAlternates::Normal
     166            && eastAsianVariant == FontVariantEastAsianVariant::Normal
     167            && eastAsianWidth == FontVariantEastAsianWidth::Normal
     168            && eastAsianRuby == FontVariantEastAsianRuby::Normal;
     169    }
     170
     171    FontVariantLigatures commonLigatures;
     172    FontVariantLigatures discretionaryLigatures;
     173    FontVariantLigatures historicalLigatures;
     174    FontVariantLigatures contextualAlternates;
     175    FontVariantPosition position;
     176    FontVariantCaps caps;
     177    FontVariantNumericFigure numericFigure;
     178    FontVariantNumericSpacing numericSpacing;
     179    FontVariantNumericFraction numericFraction;
     180    FontVariantNumericOrdinal numericOrdinal;
     181    FontVariantNumericSlashedZero numericSlashedZero;
     182    FontVariantAlternates alternates;
     183    FontVariantEastAsianVariant eastAsianVariant;
     184    FontVariantEastAsianWidth eastAsianWidth;
     185    FontVariantEastAsianRuby eastAsianRuby;
     186};
     187
    75188enum FontWidthVariant {
    76189    RegularWidth,
  • trunk/Source/WebCore/rendering/RenderThemeIOS.mm

    r189830 r190192  
    12381238    ASSERT(fontDescriptor);
    12391239    RetainPtr<CTFontRef> font = adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), 0, nullptr));
    1240     font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings());
     1240    font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings(), fontDescription.variantSettings());
    12411241    fontDescription.setIsAbsoluteSize(true);
    12421242    fontDescription.setOneFamily(textStyle);
  • trunk/Source/WebCore/rendering/line/BreakingContext.h

    r189817 r190192  
    8484        return m_width;
    8585    }
     86
    8687private:
    8788    enum class WordTrailingSpaceState { Uninitialized, Computed };
  • trunk/Tools/ChangeLog

    r190133 r190192  
     12015-09-23  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] [Font Features] Implement font-variant-*
     4        https://bugs.webkit.org/show_bug.cgi?id=148413
     5
     6        Reviewed by Darin Adler.
     7
     8        Update test font to use "lnum" feature.
     9
     10        * FontWithFeatures/FontWithFeatures/FontCreator.cpp:
     11        (Generator::appendGSUBTable):
     12
    1132015-09-22  Andy Estes  <aestes@apple.com>
    214
  • trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp

    r189943 r190192  
    471471    void appendGSUBTable()
    472472    {
    473         std::vector<std::array<char, 5>> features {{"liga"}, {"clig"}, {"dlig"}, {"hlig"}, {"calt"}, {"subs"}, {"sups"}, {"smcp"}, {"c2sc"}, {"pcap"}, {"c2pc"}, {"unic"}, {"titl"}, {"onum"}, {"pnum"}, {"tnum"}, {"frac"}, {"afrc"}, {"ordn"}, {"zero"}, {"hist"}, {"jp78"}, {"jp83"}, {"jp90"}, {"jp04"}, {"smpl"}, {"trad"}, {"fwid"}, {"pwid"}, {"ruby"}};
     473        std::vector<std::array<char, 5>> features {{"liga"}, {"clig"}, {"dlig"}, {"hlig"}, {"calt"}, {"subs"}, {"sups"}, {"smcp"}, {"c2sc"}, {"pcap"}, {"c2pc"}, {"unic"}, {"titl"}, {"lnum"}, {"onum"}, {"pnum"}, {"tnum"}, {"frac"}, {"afrc"}, {"ordn"}, {"zero"}, {"hist"}, {"jp78"}, {"jp83"}, {"jp90"}, {"jp04"}, {"smpl"}, {"trad"}, {"fwid"}, {"pwid"}, {"ruby"}};
    474474        auto tableLocation = result.size();
    475475        auto headerSize = 10;
Note: See TracChangeset for help on using the changeset viewer.