Changeset 213341 in webkit


Ignore:
Timestamp:
Mar 2, 2017 7:17:35 PM (7 years ago)
Author:
mmaxfield@apple.com
Message:

Migrate font-stretch to use fixed-point values
https://bugs.webkit.org/show_bug.cgi?id=169107

Reviewed by Dean Jackson.

Source/WebCore:

There are a few benefits of using fixed-point values:

  • Not all of the entropy of a float is necessary for font selection. In particular, values are

expected to stay between around -1000 to 1000, and only need to have a few fractional bits.
Therefore, the values can be represented by 16-bit fixed point numbers, which includes one sign
bit and two fractional bits. This is smaller than the 32-bit floating point numbers we were
using, which means FontDescription can be slimmed down. This becomes even more important when
the rest of the variation font properties are implemented, since those will use these fixed-
point values too.

  • Fixed point values have a larger distance between adjacent representable values, which means

there are more collisions, which means our cache hit rates are higher.

No new tests because there is no behavior change.

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::fontStretchFromStyle):

  • css/StyleBuilderConverter.h:

(WebCore::StyleBuilderConverter::convertFontStretch):

  • platform/graphics/FontCache.h:

(WebCore::FontDescriptionKey::FontDescriptionKey):

  • platform/graphics/FontDescription.h:

(WebCore::FontDescription::stretch):
(WebCore::FontDescription::setStretch):
(WebCore::FontCascadeDescription::initialStretch):

  • platform/graphics/cocoa/FontCacheCoreText.cpp:

(WebCore::defaultFontSelectionValues):
(WebCore::preparePlatformFont):
(WebCore::FontDatabase::InstalledFont::InstalledFont):
(WebCore::FontDatabase::InstalledFontFamily::expand):
(WebCore::FontDatabase::capabilitiesForFontDescriptor):
(WebCore::FontDatabase::stretchThreshold):
(WebCore::FontDatabase::italicThreshold):
(WebCore::FontDatabase::weightThreshold):
(WebCore::findClosestStretch):
(WebCore::filterStretch):
(WebCore::findClosestStyle):
(WebCore::filterStyle):
(WebCore::findClosestWeight):
(WebCore::filterWeight):
(WebCore::computeTargetWeight):
(WebCore::findClosestFont):
(WebCore::platformFontLookupWithFamily):
(WebCore::fontWithFamily):
(WebCore::defaultVariationValues): Deleted.
(WebCore::FontDatabase::Range::Range): Deleted.
(WebCore::FontDatabase::Range::isValid): Deleted.
(WebCore::FontDatabase::Range::expand): Deleted.
(WebCore::FontDatabase::Range::includes): Deleted.
(): Deleted.

  • platform/text/TextFlags.h:

(WebCore::FontSelectionValue::FontSelectionValue):
(WebCore::FontSelectionValue::operator float):
(WebCore::FontSelectionValue::operator+):
(WebCore::FontSelectionValue::operator-):
(WebCore::FontSelectionValue::operator*):
(WebCore::FontSelectionValue::operator/):
(WebCore::FontSelectionValue::operator==):
(WebCore::FontSelectionValue::operator!=):
(WebCore::FontSelectionValue::operator<):
(WebCore::FontSelectionValue::operator<=):
(WebCore::FontSelectionValue::operator>):
(WebCore::FontSelectionValue::operator>=):
(WebCore::FontSelectionValue::rawValue):
(WebCore::FontSelectionRange::isValid):
(WebCore::FontSelectionRange::expand):
(WebCore::FontSelectionRange::includes):
(WebCore::FontSelectionCapabilities::expand):

Tools:

Update to new types.

  • TestWebKitAPI/Tests/WebCore/FontCache.cpp:

(TestWebKitAPI::createPlatformFont):

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r213322 r213341  
     12017-03-02  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        Migrate font-stretch to use fixed-point values
     4        https://bugs.webkit.org/show_bug.cgi?id=169107
     5
     6        Reviewed by Dean Jackson.
     7
     8        There are a few benefits of using fixed-point values:
     9        - Not all of the entropy of a float is necessary for font selection. In particular, values are
     10        expected to stay between around -1000 to 1000, and only need to have a few fractional bits.
     11        Therefore, the values can be represented by 16-bit fixed point numbers, which includes one sign
     12        bit and two fractional bits. This is smaller than the 32-bit floating point numbers we were
     13        using, which means FontDescription can be slimmed down. This becomes even more important when
     14        the rest of the variation font properties are implemented, since those will use these fixed-
     15        point values too.
     16        - Fixed point values have a larger distance between adjacent representable values, which means
     17        there are more collisions, which means our cache hit rates are higher.
     18
     19        No new tests because there is no behavior change.
     20
     21        * css/CSSComputedStyleDeclaration.cpp:
     22        (WebCore::fontStretchFromStyle):
     23        * css/StyleBuilderConverter.h:
     24        (WebCore::StyleBuilderConverter::convertFontStretch):
     25        * platform/graphics/FontCache.h:
     26        (WebCore::FontDescriptionKey::FontDescriptionKey):
     27        * platform/graphics/FontDescription.h:
     28        (WebCore::FontDescription::stretch):
     29        (WebCore::FontDescription::setStretch):
     30        (WebCore::FontCascadeDescription::initialStretch):
     31        * platform/graphics/cocoa/FontCacheCoreText.cpp:
     32        (WebCore::defaultFontSelectionValues):
     33        (WebCore::preparePlatformFont):
     34        (WebCore::FontDatabase::InstalledFont::InstalledFont):
     35        (WebCore::FontDatabase::InstalledFontFamily::expand):
     36        (WebCore::FontDatabase::capabilitiesForFontDescriptor):
     37        (WebCore::FontDatabase::stretchThreshold):
     38        (WebCore::FontDatabase::italicThreshold):
     39        (WebCore::FontDatabase::weightThreshold):
     40        (WebCore::findClosestStretch):
     41        (WebCore::filterStretch):
     42        (WebCore::findClosestStyle):
     43        (WebCore::filterStyle):
     44        (WebCore::findClosestWeight):
     45        (WebCore::filterWeight):
     46        (WebCore::computeTargetWeight):
     47        (WebCore::findClosestFont):
     48        (WebCore::platformFontLookupWithFamily):
     49        (WebCore::fontWithFamily):
     50        (WebCore::defaultVariationValues): Deleted.
     51        (WebCore::FontDatabase::Range::Range): Deleted.
     52        (WebCore::FontDatabase::Range::isValid): Deleted.
     53        (WebCore::FontDatabase::Range::expand): Deleted.
     54        (WebCore::FontDatabase::Range::includes): Deleted.
     55        (): Deleted.
     56        * platform/text/TextFlags.h:
     57        (WebCore::FontSelectionValue::FontSelectionValue):
     58        (WebCore::FontSelectionValue::operator float):
     59        (WebCore::FontSelectionValue::operator+):
     60        (WebCore::FontSelectionValue::operator-):
     61        (WebCore::FontSelectionValue::operator*):
     62        (WebCore::FontSelectionValue::operator/):
     63        (WebCore::FontSelectionValue::operator==):
     64        (WebCore::FontSelectionValue::operator!=):
     65        (WebCore::FontSelectionValue::operator<):
     66        (WebCore::FontSelectionValue::operator<=):
     67        (WebCore::FontSelectionValue::operator>):
     68        (WebCore::FontSelectionValue::operator>=):
     69        (WebCore::FontSelectionValue::rawValue):
     70        (WebCore::FontSelectionRange::isValid):
     71        (WebCore::FontSelectionRange::expand):
     72        (WebCore::FontSelectionRange::includes):
     73        (WebCore::FontSelectionCapabilities::expand):
     74
    1752017-03-02  Alex Christensen  <achristensen@webkit.org>
    276
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r213267 r213341  
    19221922static Ref<CSSPrimitiveValue> fontStretchFromStyle(const RenderStyle& style)
    19231923{
    1924     float stretch = style.fontDescription().stretch();
    1925     if (stretch == 50)
     1924    auto stretch = style.fontDescription().stretch();
     1925    if (stretch == FontSelectionValue(50))
    19261926        return CSSValuePool::singleton().createIdentifierValue(CSSValueUltraCondensed);
    1927     if (stretch == 62.5)
     1927    if (stretch == FontSelectionValue(62.5f))
    19281928        return CSSValuePool::singleton().createIdentifierValue(CSSValueExtraCondensed);
    1929     if (stretch == 75)
     1929    if (stretch == FontSelectionValue(75))
    19301930        return CSSValuePool::singleton().createIdentifierValue(CSSValueCondensed);
    1931     if (stretch == 87.5)
     1931    if (stretch == FontSelectionValue(87.5f))
    19321932        return CSSValuePool::singleton().createIdentifierValue(CSSValueSemiCondensed);
    1933     if (stretch == 100)
     1933    if (stretch == FontSelectionValue(100))
    19341934        return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
    1935     if (stretch == 112.5)
     1935    if (stretch == FontSelectionValue(112.5f))
    19361936        return CSSValuePool::singleton().createIdentifierValue(CSSValueSemiExpanded);
    1937     if (stretch == 125)
     1937    if (stretch == FontSelectionValue(125))
    19381938        return CSSValuePool::singleton().createIdentifierValue(CSSValueExpanded);
    1939     if (stretch == 150)
     1939    if (stretch == FontSelectionValue(150))
    19401940        return CSSValuePool::singleton().createIdentifierValue(CSSValueExtraExpanded);
    1941     if (stretch == 200)
     1941    if (stretch == FontSelectionValue(200))
    19421942        return CSSValuePool::singleton().createIdentifierValue(CSSValueUltraExpanded);
    1943     return CSSValuePool::singleton().createValue(stretch, CSSPrimitiveValue::CSS_PERCENTAGE);
     1943    return CSSValuePool::singleton().createValue(static_cast<float>(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
    19441944}
    19451945
  • trunk/Source/WebCore/css/StyleBuilderConverter.h

    r213267 r213341  
    115115#endif
    116116    static FontFeatureSettings convertFontFeatureSettings(StyleResolver&, const CSSValue&);
    117     static float convertFontStretch(StyleResolver&, const CSSValue&);
     117    static FontSelectionValue convertFontStretch(StyleResolver&, const CSSValue&);
    118118#if ENABLE(VARIATION_FONTS)
    119119    static FontVariationSettings convertFontVariationSettings(StyleResolver&, const CSSValue&);
     
    11551155}
    11561156
    1157 inline float StyleBuilderConverter::convertFontStretch(StyleResolver&, const CSSValue& value)
     1157inline FontSelectionValue StyleBuilderConverter::convertFontStretch(StyleResolver&, const CSSValue& value)
    11581158{
    11591159    ASSERT(is<CSSPrimitiveValue>(value));
    11601160    const auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
    1161     if (primitiveValue.isPercentage() || primitiveValue.isNumber())
    1162         return primitiveValue.floatValue();
     1161    if (primitiveValue.isPercentage() || primitiveValue.isNumber()) {
     1162        auto value = primitiveValue.floatValue();
     1163        if (value <= static_cast<float>(FontSelectionValue::maximumValue())
     1164            && value >= static_cast<float>(FontSelectionValue::minimumValue()))
     1165            return FontSelectionValue(value);
     1166        if (value < static_cast<float>(FontSelectionValue::minimumValue()))
     1167            return FontSelectionValue::minimumValue();
     1168        ASSERT(value > static_cast<float>(FontSelectionValue::maximumValue()));
     1169        return FontSelectionValue::maximumValue();
     1170    }
    11631171
    11641172    switch (primitiveValue.valueID()) {
    11651173    case CSSValueUltraCondensed:
    1166         return 50;
     1174        return FontSelectionValue(50);
    11671175    case CSSValueExtraCondensed:
    1168         return 62.5;
     1176        return FontSelectionValue(62.5f);
    11691177    case CSSValueCondensed:
    1170         return 75;
     1178        return FontSelectionValue(75);
    11711179    case CSSValueSemiCondensed:
    1172         return 87.5;
     1180        return FontSelectionValue(87.5f);
    11731181    case CSSValueNormal:
    1174         return 100;
     1182        return FontSelectionValue(100);
    11751183    case CSSValueSemiExpanded:
    1176         return 112.5;
     1184        return FontSelectionValue(112.5f);
    11771185    case CSSValueExpanded:
    1178         return 125;
     1186        return FontSelectionValue(125);
    11791187    case CSSValueExtraExpanded:
    1180         return 150;
     1188        return FontSelectionValue(150);
    11811189    case CSSValueUltraExpanded:
    1182         return 200;
     1190        return FontSelectionValue(200);
    11831191    default:
    11841192        ASSERT_NOT_REACHED();
    1185         return 100;
     1193        return FontSelectionValue(100);
    11861194    }
    11871195}
  • trunk/Source/WebCore/platform/graphics/FontCache.h

    r213267 r213341  
    7474        : m_size(description.computedPixelSize())
    7575        , m_weight(description.weight())
    76         , m_stretch(description.stretch())
    7776        , m_flags(makeFlagsKey(description))
    7877        , m_featureSettings(description.featureSettings())
     
    8079        , m_variationSettings(description.variationSettings())
    8180#endif
     81        , m_stretch(description.stretch().rawValue())
    8282    { }
    8383
     
    155155    unsigned m_size { 0 };
    156156    unsigned m_weight { 0 };
    157     float m_stretch { 0 };
    158157    std::array<unsigned, 2> m_flags {{ 0, 0 }};
    159158    FontFeatureSettings m_featureSettings;
     
    161160    FontVariationSettings m_variationSettings;
    162161#endif
     162    uint16_t m_stretch { 0 };
    163163};
    164164
  • trunk/Source/WebCore/platform/graphics/FontDescription.h

    r213267 r213341  
    4747    float computedSize() const { return m_computedSize; }
    4848    FontItalic italic() const { return static_cast<FontItalic>(m_italic); }
    49     float stretch() const { return m_stretch; }
     49    FontSelectionValue stretch() const { return m_stretch; }
    5050    int computedPixelSize() const { return int(m_computedSize + 0.5f); }
    5151    FontWeight weight() const { return static_cast<FontWeight>(m_weight); }
     
    9999    void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
    100100    void setItalic(FontItalic i) { m_italic = i; }
    101     void setStretch(float stretch) { m_stretch = stretch; }
     101    void setStretch(FontSelectionValue stretch) { m_stretch = stretch; }
    102102    void setIsItalic(bool i) { setItalic(i ? FontItalicOn : FontItalicOff); }
    103103    void setWeight(FontWeight w) { m_weight = w; }
     
    137137    AtomicString m_locale;
    138138
    139     float m_stretch { 100 }; // Stretch, or "width," of the font
    140139    float m_computedSize { 0 }; // Computed size adjusted for the minimum font size and the zoom factor.
     140    FontSelectionValue m_stretch { 100 }; // Stretch, or "width," of the font
    141141    unsigned m_orientation : 1; // FontOrientation - Whether the font is rendering on a horizontal line or a vertical line.
    142142    unsigned m_nonCJKGlyphOrientation : 1; // NonCJKGlyphOrientation - Only used by vertical text. Determines the default orientation for non-ideograph glyphs.
     
    266266    // Initial values for font properties.
    267267    static FontItalic initialItalic() { return FontItalicOff; }
    268     static float initialStretch() { return 100; }
     268    static FontSelectionValue initialStretch() { return FontSelectionValue(100); }
    269269    static FontSmallCaps initialSmallCaps() { return FontSmallCapsOff; }
    270270    static Kerning initialKerning() { return Kerning::Auto; }
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

    r213267 r213341  
    790790#if !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
    791791
    792 constexpr float stretchThreshold = 100;
    793 constexpr float italicThreshold = 20;
    794 constexpr float weightThreshold = 500;
    795 
    796792class FontDatabase {
    797793public:
     
    805801    FontDatabase& operator=(const FontDatabase&) = delete;
    806802
    807     // [Inclusive, Inclusive]
    808     struct Range {
    809         Range()
    810         {
    811             ASSERT(!isValid());
    812         }
    813 
    814         Range(float minimum, float maximum)
    815             : minimum(minimum)
    816             , maximum(maximum)
    817         {
    818             ASSERT(isValid());
    819         }
    820 
    821         bool isValid() const
    822         {
    823             return minimum <= maximum;
    824         }
    825 
    826         void expand(const Range& other)
    827         {
    828             ASSERT(other.isValid());
    829             if (!isValid())
    830                 *this = other;
    831             else {
    832                 minimum = std::min(minimum, other.minimum);
    833                 maximum = std::max(maximum, other.maximum);
    834             }
    835             ASSERT(isValid());
    836         }
    837 
    838         bool includes(float target) const
    839         {
    840             return target >= minimum && target <= maximum;
    841         }
    842 
    843         float minimum { 1 };
    844         float maximum { 0 };
    845     };
    846 
    847803    struct InstalledFont {
    848804        InstalledFont() = default;
     
    850806        InstalledFont(CTFontDescriptorRef fontDescriptor)
    851807            : fontDescriptor(fontDescriptor)
     808            , capabilities(capabilitiesForFontDescriptor(fontDescriptor))
    852809        {
    853             if (!fontDescriptor)
    854                 return;
    855 
    856             auto traits = adoptCF(static_cast<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
    857             float width = 0;
    858             float slant = 0;
    859             float weight = 0;
    860             if (traits) {
    861                 auto widthNumber = static_cast<CFNumberRef>(CFDictionaryGetValue(traits.get(), kCTFontWidthTrait));
    862                 if (widthNumber) {
    863                     // FIXME: The normalization from Core Text's [-1, 1] range to CSS's [50%, 200%] range isn't perfect.
    864                     float ctWidth;
    865                     auto success = CFNumberGetValue(widthNumber, kCFNumberFloatType, &ctWidth);
    866                     ASSERT_UNUSED(success, success);
    867                     width = ctWidth < 0.5 ? ctWidth * 50 + 100 : ctWidth * 150 + 50;
    868                 }
    869 
    870                 auto symbolicTraitsNumber = static_cast<CFNumberRef>(CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait));
    871                 if (symbolicTraitsNumber) {
    872                     int32_t symbolicTraits;
    873                     auto success = CFNumberGetValue(symbolicTraitsNumber, kCFNumberSInt32Type, &symbolicTraits);
    874                     ASSERT_UNUSED(success, success);
    875                     slant = symbolicTraits & kCTFontTraitItalic ? italicThreshold : 0;
    876                 }
    877             }
    878 
    879             auto weightNumber = adoptCF(static_cast<CFNumberRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontCSSWeightAttribute)));
    880             if (weightNumber) {
    881                 auto success = CFNumberGetValue(weightNumber.get(), kCFNumberFloatType, &weight);
    882                 ASSERT_UNUSED(success, success);
    883             }
    884            
    885             stretch = Range(width, width);
    886             style = Range(slant, slant);
    887             this->weight = Range(weight, weight);
    888810        }
    889811
    890812        RetainPtr<CTFontDescriptorRef> fontDescriptor;
    891         Range stretch;
    892         Range style;
    893         Range weight;
     813        FontSelectionCapabilities capabilities;
    894814    };
    895815
     
    906826        void expand(const InstalledFont& installedFont)
    907827        {
    908             stretchBounds.expand(installedFont.stretch);
    909             styleBounds.expand(installedFont.style);
    910             weightBounds.expand(installedFont.weight);
     828            capabilities.expand(installedFont.capabilities);
    911829        }
    912830
     
    922840
    923841        Vector<InstalledFont> installedFonts;
    924         Range stretchBounds;
    925         Range styleBounds;
    926         Range weightBounds;
     842        FontSelectionCapabilities capabilities;
    927843    };
    928844
     
    970886    }
    971887
     888    static FontSelectionCapabilities capabilitiesForFontDescriptor(CTFontDescriptorRef fontDescriptor)
     889    {
     890        if (!fontDescriptor)
     891            return { };
     892
     893        auto traits = adoptCF(static_cast<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
     894        FontSelectionValue width;
     895        FontSelectionValue slant;
     896        FontSelectionValue weight;
     897        if (traits) {
     898            auto widthNumber = static_cast<CFNumberRef>(CFDictionaryGetValue(traits.get(), kCTFontWidthTrait));
     899            if (widthNumber) {
     900                // FIXME: The normalization from Core Text's [-1, 1] range to CSS's [50%, 200%] range isn't perfect.
     901                float ctWidth;
     902                auto success = CFNumberGetValue(widthNumber, kCFNumberFloatType, &ctWidth);
     903                ASSERT_UNUSED(success, success);
     904                width = FontSelectionValue(ctWidth < 0.5 ? ctWidth * 50 + 100 : ctWidth * 150 + 50);
     905            }
     906
     907            auto symbolicTraitsNumber = static_cast<CFNumberRef>(CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait));
     908            if (symbolicTraitsNumber) {
     909                int32_t symbolicTraits;
     910                auto success = CFNumberGetValue(symbolicTraitsNumber, kCFNumberSInt32Type, &symbolicTraits);
     911                ASSERT_UNUSED(success, success);
     912                slant = symbolicTraits & kCTFontTraitItalic ? italicThreshold() : FontSelectionValue();
     913            }
     914        }
     915
     916        auto weightNumber = adoptCF(static_cast<CFNumberRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontCSSWeightAttribute)));
     917        if (weightNumber) {
     918            float cssWeight;
     919            auto success = CFNumberGetValue(weightNumber.get(), kCFNumberFloatType, &cssWeight);
     920            ASSERT_UNUSED(success, success);
     921            weight = FontSelectionValue(cssWeight);
     922        }
     923
     924        // FIXME: Educate this function about font variations.
     925
     926        return { { weight, weight }, { width, width }, { slant, slant } };
     927    }
     928
     929    static const FontSelectionValue stretchThreshold()
     930    {
     931        static NeverDestroyed<FontSelectionValue> threshold(100);
     932        return threshold.get();
     933    }
     934
     935    static const FontSelectionValue italicThreshold()
     936    {
     937        static NeverDestroyed<FontSelectionValue> threshold(20);
     938        return threshold.get();
     939    }
     940
     941    static const FontSelectionValue weightThreshold()
     942    {
     943        static NeverDestroyed<FontSelectionValue> threshold(500);
     944        return threshold.get();
     945    }
     946
    972947private:
    973948    friend class NeverDestroyed<FontDatabase>;
     
    1003978}
    1004979
    1005 static inline std::optional<float> findClosestStretch(float targetStretch, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
     980static inline std::optional<FontSelectionValue> findClosestStretch(FontSelectionValue targetStretch, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
    1006981{
    1007982    std::function<float(const FontDatabase::InstalledFont&)> computeScore;
    1008983
    1009     if (targetStretch >= stretchThreshold) {
    1010         float threshold = std::max(targetStretch, installedFonts.stretchBounds.maximum);
     984    if (targetStretch >= FontDatabase::stretchThreshold()) {
     985        auto threshold = std::max(targetStretch, installedFonts.capabilities.width.maximum);
    1011986        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1012             ASSERT(font.stretch.isValid());
    1013             if (font.stretch.includes(targetStretch))
     987            auto width = font.capabilities.width;
     988            ASSERT(width.isValid());
     989            if (width.includes(targetStretch))
    1014990                return 0;
    1015             ASSERT(font.stretch.minimum > targetStretch || font.stretch.maximum < targetStretch);
    1016             if (font.stretch.minimum > targetStretch)
    1017                 return font.stretch.minimum - targetStretch;
    1018             ASSERT(font.stretch.maximum < targetStretch);
    1019             return threshold - font.stretch.maximum;
     991            ASSERT(width.minimum > targetStretch || width.maximum < targetStretch);
     992            if (width.minimum > targetStretch)
     993                return width.minimum - targetStretch;
     994            ASSERT(width.maximum < targetStretch);
     995            return threshold - width.maximum;
    1020996        };
    1021997    } else {
    1022         ASSERT(targetStretch < stretchThreshold);
    1023         float threshold = std::min(targetStretch, installedFonts.stretchBounds.minimum);
     998        ASSERT(targetStretch < FontDatabase::stretchThreshold());
     999        auto threshold = std::min(targetStretch, installedFonts.capabilities.width.minimum);
    10241000        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1025             if (font.stretch.includes(targetStretch))
     1001            auto width = font.capabilities.width;
     1002            if (width.includes(targetStretch))
    10261003                return 0;
    1027             ASSERT(font.stretch.minimum > targetStretch || font.stretch.maximum < targetStretch);
    1028             if (font.stretch.maximum < targetStretch)
    1029                 return targetStretch - font.stretch.maximum;
    1030             ASSERT(font.stretch.minimum > targetStretch);
    1031             return font.stretch.minimum - threshold;
     1004            ASSERT(width.minimum > targetStretch || width.maximum < targetStretch);
     1005            if (width.maximum < targetStretch)
     1006                return targetStretch - width.maximum;
     1007            ASSERT(width.minimum > targetStretch);
     1008            return width.minimum - threshold;
    10321009        };
    10331010    }
     
    10461023        return std::nullopt;
    10471024    auto& winner = installedFonts.installedFonts[closestIndex];
    1048     if (winner.stretch.includes(targetStretch))
     1025    auto width = winner.capabilities.width;
     1026    if (width.includes(targetStretch))
    10491027        return targetStretch;
    1050     if (winner.stretch.minimum > targetStretch)
    1051         return winner.stretch.minimum;
    1052     ASSERT(winner.stretch.maximum < targetStretch);
    1053     return winner.stretch.maximum;
    1054 }
    1055 
    1056 static inline void filterStretch(float target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
     1028    if (width.minimum > targetStretch)
     1029        return width.minimum;
     1030    ASSERT(width.maximum < targetStretch);
     1031    return width.maximum;
     1032}
     1033
     1034static inline void filterStretch(FontSelectionValue target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
    10571035{
    10581036    iterateActiveFonts(installedFonts, filter, [&](auto& installedFont, size_t i) {
    1059         if (!installedFont.stretch.includes(target))
     1037        if (!installedFont.capabilities.width.includes(target))
    10601038            filter[i] = false;
    10611039    });
    10621040}
    10631041
    1064 static inline std::optional<float> findClosestStyle(float targetStyle, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
     1042static inline std::optional<FontSelectionValue> findClosestStyle(FontSelectionValue targetStyle, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
    10651043{
    10661044    std::function<float(const FontDatabase::InstalledFont&)> computeScore;
    10671045
    1068     if (targetStyle >= italicThreshold) {
    1069         float threshold = std::max(targetStyle, installedFonts.styleBounds.maximum);
     1046    if (targetStyle >= FontDatabase::italicThreshold()) {
     1047        auto threshold = std::max(targetStyle, installedFonts.capabilities.slope.maximum);
    10701048        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1071             ASSERT(font.style.isValid());
    1072             if (font.style.includes(targetStyle))
     1049            auto slope = font.capabilities.slope;
     1050            ASSERT(slope.isValid());
     1051            if (slope.includes(targetStyle))
    10731052                return 0;
    1074             ASSERT(font.style.minimum > targetStyle || font.style.maximum < targetStyle);
    1075             if (font.style.minimum > targetStyle)
    1076                 return font.style.minimum - targetStyle;
    1077             ASSERT(targetStyle > font.style.maximum);
    1078             return threshold - font.style.maximum;
     1053            ASSERT(slope.minimum > targetStyle || slope.maximum < targetStyle);
     1054            if (slope.minimum > targetStyle)
     1055                return slope.minimum - targetStyle;
     1056            ASSERT(targetStyle > slope.maximum);
     1057            return threshold - slope.maximum;
    10791058        };
    1080     } else if (targetStyle >= 0) {
    1081         float threshold = std::max(targetStyle, installedFonts.styleBounds.maximum);
     1059    } else if (targetStyle >= FontSelectionValue()) {
     1060        auto threshold = std::max(targetStyle, installedFonts.capabilities.slope.maximum);
    10821061        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1083             ASSERT(font.style.isValid());
    1084             if (font.style.includes(targetStyle))
     1062            auto slope = font.capabilities.slope;
     1063            ASSERT(slope.isValid());
     1064            if (slope.includes(targetStyle))
    10851065                return 0;
    1086             ASSERT(font.style.minimum > targetStyle || font.style.maximum < targetStyle);
    1087             if (font.style.maximum >= 0 && font.style.maximum < targetStyle)
    1088                 return targetStyle - font.style.maximum;
    1089             if (font.style.minimum > targetStyle)
    1090                 return font.style.minimum;
    1091             ASSERT(font.style.maximum < 0);
    1092             return threshold - font.style.maximum;
     1066            ASSERT(slope.minimum > targetStyle || slope.maximum < targetStyle);
     1067            if (slope.maximum >= FontSelectionValue() && slope.maximum < targetStyle)
     1068                return targetStyle - slope.maximum;
     1069            if (slope.minimum > targetStyle)
     1070                return slope.minimum;
     1071            ASSERT(slope.maximum < FontSelectionValue());
     1072            return threshold - slope.maximum;
    10931073        };
    1094     } else if (targetStyle > -italicThreshold) {
    1095         float threshold = std::min(targetStyle, installedFonts.styleBounds.minimum);
     1074    } else if (targetStyle > -FontDatabase::italicThreshold()) {
     1075        auto threshold = std::min(targetStyle, installedFonts.capabilities.slope.minimum);
    10961076        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1097             ASSERT(font.style.isValid());
    1098             if (font.style.includes(targetStyle))
     1077            auto slope = font.capabilities.slope;
     1078            ASSERT(slope.isValid());
     1079            if (slope.includes(targetStyle))
    10991080                return 0;
    1100             ASSERT(font.style.minimum > targetStyle || font.style.maximum < targetStyle);
    1101             if (font.style.minimum > targetStyle && font.style.minimum <= 0)
    1102                 return font.style.minimum - targetStyle;
    1103             if (font.style.maximum < targetStyle)
    1104                 return -font.style.maximum;
    1105             ASSERT(font.style.minimum > 0);
    1106             return font.style.minimum - threshold;
     1081            ASSERT(slope.minimum > targetStyle || slope.maximum < targetStyle);
     1082            if (slope.minimum > targetStyle && slope.minimum <= FontSelectionValue())
     1083                return slope.minimum - targetStyle;
     1084            if (slope.maximum < targetStyle)
     1085                return -slope.maximum;
     1086            ASSERT(slope.minimum > FontSelectionValue());
     1087            return slope.minimum - threshold;
    11071088        };
    11081089    } else {
    1109         ASSERT(targetStyle <= -italicThreshold);
    1110         float threshold = std::min(targetStyle, installedFonts.styleBounds.minimum);
     1090        ASSERT(targetStyle <= -FontDatabase::italicThreshold());
     1091        auto threshold = std::min(targetStyle, installedFonts.capabilities.slope.minimum);
    11111092        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1112             ASSERT(font.style.isValid());
    1113             if (font.style.includes(targetStyle))
     1093            auto slope = font.capabilities.slope;
     1094            ASSERT(slope.isValid());
     1095            if (slope.includes(targetStyle))
    11141096                return 0;
    1115             ASSERT(font.style.minimum > targetStyle || font.style.maximum < targetStyle);
    1116             if (font.style.maximum < targetStyle)
    1117                 return targetStyle - font.style.maximum;
    1118             ASSERT(font.style.minimum > targetStyle);
    1119             return font.style.minimum - threshold;
     1097            ASSERT(slope.minimum > targetStyle || slope.maximum < targetStyle);
     1098            if (slope.maximum < targetStyle)
     1099                return targetStyle - slope.maximum;
     1100            ASSERT(slope.minimum > targetStyle);
     1101            return slope.minimum - threshold;
    11201102        };
    11211103    }
     
    11341116        return std::nullopt;
    11351117    auto& winner = installedFonts.installedFonts[closestIndex];
    1136     if (winner.style.includes(targetStyle))
     1118    auto slope = winner.capabilities.slope;
     1119    if (slope.includes(targetStyle))
    11371120        return targetStyle;
    1138     if (winner.style.minimum > targetStyle)
    1139         return winner.style.minimum;
    1140     ASSERT(winner.style.maximum < targetStyle);
    1141     return winner.style.maximum;
    1142 }
    1143 
    1144 static inline void filterStyle(float target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
     1121    if (slope.minimum > targetStyle)
     1122        return slope.minimum;
     1123    ASSERT(slope.maximum < targetStyle);
     1124    return slope.maximum;
     1125}
     1126
     1127static inline void filterStyle(FontSelectionValue target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
    11451128{
    11461129    iterateActiveFonts(installedFonts, filter, [&](auto& installedFont, size_t i) {
    1147         if (!installedFont.style.includes(target))
     1130        if (!installedFont.capabilities.slope.includes(target))
    11481131            filter[i] = false;
    11491132    });
    11501133}
    11511134
    1152 static inline std::optional<float> findClosestWeight(float targetWeight, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
     1135static inline std::optional<FontSelectionValue> findClosestWeight(FontSelectionValue targetWeight, const FontDatabase::InstalledFontFamily& installedFonts, const std::unique_ptr<bool[]>& filter)
    11531136{
    11541137    {
    11551138        // The spec states: "If the desired weight is 400, 500 is checked first ... If the desired weight is 500, 400 is checked first"
    1156         IterateActiveFontsWithReturnCallback<float> searchFor400 = [&](const FontDatabase::InstalledFont& font, size_t) -> std::optional<float> {
    1157             if (font.weight.includes(400))
    1158                 return 400;
     1139        IterateActiveFontsWithReturnCallback<FontSelectionValue> searchFor400 = [&](const FontDatabase::InstalledFont& font, size_t) -> std::optional<FontSelectionValue> {
     1140            if (font.capabilities.weight.includes(FontSelectionValue(400)))
     1141                return FontSelectionValue(400);
    11591142            return std::nullopt;
    11601143        };
    1161         IterateActiveFontsWithReturnCallback<float> searchFor500 = [&](const FontDatabase::InstalledFont& font, size_t) -> std::optional<float> {
    1162             if (font.weight.includes(500))
    1163                 return 500;
     1144        IterateActiveFontsWithReturnCallback<FontSelectionValue> searchFor500 = [&](const FontDatabase::InstalledFont& font, size_t) -> std::optional<FontSelectionValue> {
     1145            if (font.capabilities.weight.includes(FontSelectionValue(500)))
     1146                return FontSelectionValue(500);
    11641147            return std::nullopt;
    11651148        };
    1166         if (targetWeight == 400) {
     1149        if (targetWeight == FontSelectionValue(400)) {
    11671150            if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor400))
    11681151                return result;
    11691152            if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor500))
    11701153                return result;
    1171         } else if (targetWeight == 500) {
     1154        } else if (targetWeight == FontSelectionValue(500)) {
    11721155            if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor500))
    11731156                return result;
     
    11781161
    11791162    std::function<float(const FontDatabase::InstalledFont&)> computeScore;
    1180     if (targetWeight <= weightThreshold) {
    1181         float threshold = std::min(targetWeight, installedFonts.weightBounds.minimum);
    1182         computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1183             if (font.weight.includes(targetWeight))
    1184                 return 0;
    1185             ASSERT(font.weight.minimum > targetWeight || font.weight.maximum < targetWeight);
    1186             if (font.weight.maximum < targetWeight)
    1187                 return targetWeight - font.weight.maximum;
    1188             ASSERT(font.weight.minimum > targetWeight);
    1189             return font.weight.minimum - threshold;
     1163    if (targetWeight <= FontDatabase::weightThreshold()) {
     1164        auto threshold = std::min(targetWeight, installedFonts.capabilities.weight.minimum);
     1165        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> FontSelectionValue {
     1166            auto weight = font.capabilities.weight;
     1167            if (weight.includes(targetWeight))
     1168                return FontSelectionValue();
     1169            ASSERT(weight.minimum > targetWeight || weight.maximum < targetWeight);
     1170            if (weight.maximum < targetWeight)
     1171                return targetWeight - weight.maximum;
     1172            ASSERT(weight.minimum > targetWeight);
     1173            return weight.minimum - threshold;
    11901174        };
    11911175    } else {
    1192         ASSERT(targetWeight > weightThreshold);
    1193         float threshold = std::max(targetWeight, installedFonts.weightBounds.maximum);
    1194         computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> float {
    1195             if (font.weight.includes(targetWeight))
    1196                 return 0;
    1197             ASSERT(font.weight.minimum > targetWeight || font.weight.maximum < targetWeight);
    1198             if (font.weight.minimum > targetWeight)
    1199                 return font.weight.minimum - targetWeight;
    1200             ASSERT(font.weight.maximum < targetWeight);
    1201             return threshold - font.weight.maximum;
     1176        ASSERT(targetWeight > FontDatabase::weightThreshold());
     1177        auto threshold = std::max(targetWeight, installedFonts.capabilities.weight.maximum);
     1178        computeScore = [&, threshold](const FontDatabase::InstalledFont& font) -> FontSelectionValue {
     1179            auto weight = font.capabilities.weight;
     1180            if (weight.includes(targetWeight))
     1181                return FontSelectionValue();
     1182            ASSERT(weight.minimum > targetWeight || weight.maximum < targetWeight);
     1183            if (weight.minimum > targetWeight)
     1184                return weight.minimum - targetWeight;
     1185            ASSERT(weight.maximum < targetWeight);
     1186            return threshold - weight.maximum;
    12021187        };
    12031188    }
     
    12161201        return std::nullopt;
    12171202    auto& winner = installedFonts.installedFonts[closestIndex];
    1218     if (winner.weight.includes(targetWeight))
     1203    auto weight = winner.capabilities.weight;
     1204    if (weight.includes(targetWeight))
    12191205        return targetWeight;
    1220     if (winner.weight.minimum > targetWeight)
    1221         return winner.weight.minimum;
    1222     ASSERT(winner.weight.maximum < targetWeight);
    1223     return winner.weight.maximum;
    1224 }
    1225 
    1226 static inline void filterWeight(float target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
     1206    if (weight.minimum > targetWeight)
     1207        return weight.minimum;
     1208    ASSERT(weight.maximum < targetWeight);
     1209    return weight.maximum;
     1210}
     1211
     1212static inline void filterWeight(FontSelectionValue target, const FontDatabase::InstalledFontFamily& installedFonts, std::unique_ptr<bool[]>& filter)
    12271213{
    12281214    iterateActiveFonts(installedFonts, filter, [&](auto& installedFont, size_t i) {
    1229         if (!installedFont.weight.includes(target))
     1215        if (!installedFont.capabilities.weight.includes(target))
    12301216            filter[i] = false;
    12311217    });
    12321218}
    12331219
    1234 static inline float computeTargetWeight(FontWeight weight)
     1220static inline FontSelectionValue computeTargetWeight(FontWeight weight)
    12351221{
    12361222    switch (weight) {
    12371223    case FontWeight100:
    1238         return 100;
     1224        return FontSelectionValue(100);
    12391225    case FontWeight200:
    1240         return 200;
     1226        return FontSelectionValue(200);
    12411227    case FontWeight300:
    1242         return 300;
     1228        return FontSelectionValue(300);
    12431229    case FontWeight400:
    1244         return 400;
     1230        return FontSelectionValue(400);
    12451231    case FontWeight500:
    1246         return 500;
     1232        return FontSelectionValue(500);
    12471233    case FontWeight600:
    1248         return 600;
     1234        return FontSelectionValue(600);
    12491235    case FontWeight700:
    1250         return 700;
     1236        return FontSelectionValue(700);
    12511237    case FontWeight800:
    1252         return 800;
     1238        return FontSelectionValue(800);
    12531239    case FontWeight900:
    1254         return 900;
     1240        return FontSelectionValue(900);
    12551241    default:
    12561242        ASSERT_NOT_REACHED();
    1257         return 400;
    1258     }
    1259 }
    1260 
    1261 static const FontDatabase::InstalledFont* findClosestFont(const FontDatabase::InstalledFontFamily& familyFonts, CTFontSymbolicTraits requestedTraits, FontWeight weight, float stretch)
     1243        return FontSelectionValue(400);
     1244    }
     1245}
     1246
     1247static const FontDatabase::InstalledFont* findClosestFont(const FontDatabase::InstalledFontFamily& familyFonts, CTFontSymbolicTraits requestedTraits, FontWeight weight, FontSelectionValue stretch)
    12621248{
    12631249    ASSERT(!familyFonts.isEmpty());
     
    12681254        filter[i] = true;
    12691255
    1270     // FIXME: Implement this.
    1271     float targetStretch = stretch;
    1272     if (auto closestStretch = findClosestStretch(targetStretch, familyFonts, filter))
     1256    if (auto closestStretch = findClosestStretch(stretch, familyFonts, filter))
    12731257        filterStretch(closestStretch.value(), familyFonts, filter);
    12741258    else
    12751259        return nullptr;
    12761260
    1277     float targetStyle = requestedTraits & kCTFontTraitItalic ? italicThreshold : 0;
     1261    FontSelectionValue targetStyle = requestedTraits & kCTFontTraitItalic ? FontDatabase::italicThreshold() : FontSelectionValue();
    12781262    if (auto closestStyle = findClosestStyle(targetStyle, familyFonts, filter))
    12791263        filterStyle(closestStyle.value(), familyFonts, filter);
     
    12811265        return nullptr;
    12821266
    1283     float targetWeight = computeTargetWeight(weight);
     1267    FontSelectionValue targetWeight = computeTargetWeight(weight);
    12841268    if (auto closestWeight = findClosestWeight(targetWeight, familyFonts, filter))
    12851269        filterWeight(closestWeight.value(), familyFonts, filter);
     
    12941278#endif // !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
    12951279
    1296 static RetainPtr<CTFontRef> platformFontLookupWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, float stretch, float size)
     1280static RetainPtr<CTFontRef> platformFontLookupWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, FontSelectionValue stretch, float size)
    12971281{
    12981282    const auto& whitelist = fontWhitelist();
     
    13171301        if (!postScriptFont.fontDescriptor)
    13181302            return nullptr;
    1319         if (((requestedTraits & kCTFontTraitItalic) && postScriptFont.style.maximum < italicThreshold) || (weight >= FontWeight600 && postScriptFont.weight.maximum < 600)) {
     1303        if (((requestedTraits & kCTFontTraitItalic) && postScriptFont.capabilities.slope.maximum < FontDatabase::italicThreshold())
     1304            || (weight >= FontWeight600 && postScriptFont.capabilities.weight.maximum < FontSelectionValue(600))) {
    13201305            auto postScriptFamilyName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(postScriptFont.fontDescriptor.get(), kCTFontFamilyNameAttribute)));
    13211306            if (!postScriptFamilyName)
     
    13571342}
    13581343
    1359 static RetainPtr<CTFontRef> fontWithFamily(const AtomicString& family, CTFontSymbolicTraits desiredTraits, FontWeight weight, float stretch, const FontFeatureSettings& featureSettings, const FontVariantSettings& variantSettings, const FontVariationSettings& variationSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode& textRenderingMode, float size)
     1344static RetainPtr<CTFontRef> fontWithFamily(const AtomicString& family, CTFontSymbolicTraits desiredTraits, FontWeight weight, FontSelectionValue stretch, const FontFeatureSettings& featureSettings, const FontVariantSettings& variantSettings, const FontVariationSettings& variationSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode& textRenderingMode, float size)
    13601345{
    13611346    if (family.isEmpty())
  • trunk/Source/WebCore/platform/text/TextFlags.h

    r209875 r213341  
    2424 */
    2525
    26 #ifndef TextFlags_h
    27 #define TextFlags_h
     26#pragma once
     27
     28#include <wtf/NeverDestroyed.h>
    2829
    2930namespace WebCore {
     
    398399};
    399400
     401// Unclamped, unchecked, signed fixed-point number representing a value used for font variations.
     402// Sixteen bits in total, one sign bit, two fractional bits, means the smallest positive representable value is 0.25,
     403// the maximum representable value is 8191.75, and the minimum representable value is -8192.
     404class FontSelectionValue {
     405public:
     406    FontSelectionValue() = default;
     407
     408    // Explicit because it is lossy.
     409    explicit FontSelectionValue(int x)
     410        : m_backing(x * fractionalEntropy)
     411    {
     412    }
     413
     414    // Explicit because it is lossy.
     415    explicit FontSelectionValue(float x)
     416        : m_backing(x * fractionalEntropy)
     417    {
     418    }
     419
     420    operator float() const
     421    {
     422        // floats have 23 fractional bits, but only 14 fractional bits are necessary, so every value can be represented losslessly.
     423        return m_backing / static_cast<float>(fractionalEntropy);
     424    }
     425
     426    FontSelectionValue operator+(const FontSelectionValue other) const
     427    {
     428        return FontSelectionValue(m_backing + other.m_backing, RawTag::RawTag);
     429    }
     430
     431    FontSelectionValue operator-(const FontSelectionValue other) const
     432    {
     433        return FontSelectionValue(m_backing - other.m_backing, RawTag::RawTag);
     434    }
     435
     436    FontSelectionValue operator*(const FontSelectionValue other) const
     437    {
     438        return FontSelectionValue(static_cast<int32_t>(m_backing) * other.m_backing / fractionalEntropy, RawTag::RawTag);
     439    }
     440
     441    FontSelectionValue operator/(const FontSelectionValue other) const
     442    {
     443        return FontSelectionValue(static_cast<int32_t>(m_backing) / other.m_backing * fractionalEntropy, RawTag::RawTag);
     444    }
     445
     446    FontSelectionValue operator-() const
     447    {
     448        return FontSelectionValue(-m_backing, RawTag::RawTag);
     449    }
     450
     451    bool operator==(const FontSelectionValue other) const
     452    {
     453        return m_backing == other.m_backing;
     454    }
     455
     456    bool operator!=(const FontSelectionValue other) const
     457    {
     458        return !operator==(other);
     459    }
     460
     461    bool operator<(const FontSelectionValue other) const
     462    {
     463        return m_backing < other.m_backing;
     464    }
     465
     466    bool operator<=(const FontSelectionValue other) const
     467    {
     468        return m_backing <= other.m_backing;
     469    }
     470
     471    bool operator>(const FontSelectionValue other) const
     472    {
     473        return m_backing > other.m_backing;
     474    }
     475
     476    bool operator>=(const FontSelectionValue other) const
     477    {
     478        return m_backing >= other.m_backing;
     479    }
     480
     481    int16_t rawValue() const
     482    {
     483        return m_backing;
     484    }
     485
     486    static FontSelectionValue maximumValue()
     487    {
     488        static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<int16_t>::max(), RawTag::RawTag);
     489        return result.get();
     490    }
     491
     492    static FontSelectionValue minimumValue()
     493    {
     494        static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<int16_t>::min(), RawTag::RawTag);
     495        return result.get();
     496    }
     497
     498private:
     499    enum class RawTag { RawTag };
     500
     501    FontSelectionValue(int16_t rawValue, RawTag)
     502        : m_backing(rawValue)
     503    {
     504    }
     505
     506    static constexpr int fractionalEntropy = 4;
     507    int16_t m_backing { 0 };
     508};
     509
     510// [Inclusive, Inclusive]
     511struct FontSelectionRange {
     512    bool isValid() const
     513    {
     514        return minimum <= maximum;
     515    }
     516
     517    void expand(const FontSelectionRange& other)
     518    {
     519        ASSERT(other.isValid());
     520        if (!isValid())
     521            *this = other;
     522        else {
     523            minimum = std::min(minimum, other.minimum);
     524            maximum = std::max(maximum, other.maximum);
     525        }
     526        ASSERT(isValid());
     527    }
     528
     529    bool includes(FontSelectionValue target) const
     530    {
     531        return target >= minimum && target <= maximum;
     532    }
     533
     534    FontSelectionValue minimum { FontSelectionValue(1) };
     535    FontSelectionValue maximum { FontSelectionValue(0) };
     536};
     537
     538struct FontSelectionRequest {
     539    FontSelectionValue weight;
     540    FontSelectionValue width;
     541    FontSelectionValue slope;
     542};
     543
     544struct FontSelectionCapabilities {
     545    void expand(const FontSelectionCapabilities& capabilities)
     546    {
     547        weight.expand(capabilities.weight);
     548        width.expand(capabilities.width);
     549        slope.expand(capabilities.slope);
     550    }
     551
     552    FontSelectionRange weight;
     553    FontSelectionRange width;
     554    FontSelectionRange slope;
     555};
     556
    400557enum class Kerning {
    401558    Auto,
     
    405562
    406563}
    407 
    408 #endif
  • trunk/Tools/ChangeLog

    r213331 r213341  
     12017-03-02  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        Migrate font-stretch to use fixed-point values
     4        https://bugs.webkit.org/show_bug.cgi?id=169107
     5
     6        Reviewed by Dean Jackson.
     7
     8        Update to new types.
     9
     10        * TestWebKitAPI/Tests/WebCore/FontCache.cpp:
     11        (TestWebKitAPI::createPlatformFont):
     12
    1132017-03-02  Brady Eidson  <beidson@apple.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/FontCache.cpp

    r213267 r213341  
    5757    description.setWeight(weight);
    5858    description.setItalic(italic);
    59     description.setStretch(stretch);
     59    description.setStretch(FontSelectionValue(stretch));
    6060    description.setComputedSize(size);
    6161
Note: See TracChangeset for help on using the changeset viewer.