<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[213341] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/213341">213341</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2017-03-02 19:17:35 -0800 (Thu, 02 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>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&lt;):
(WebCore::FontSelectionValue::operator&lt;=):
(WebCore::FontSelectionValue::operator&gt;):
(WebCore::FontSelectionValue::operator&gt;=):
(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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSComputedStyleDeclarationcpp">trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp</a></li>
<li><a href="#trunkSourceWebCorecssStyleBuilderConverterh">trunk/Source/WebCore/css/StyleBuilderConverter.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontCacheh">trunk/Source/WebCore/platform/graphics/FontCache.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontDescriptionh">trunk/Source/WebCore/platform/graphics/FontDescription.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp">trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformtextTextFlagsh">trunk/Source/WebCore/platform/text/TextFlags.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreFontCachecpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/FontCache.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/ChangeLog        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -1,3 +1,77 @@
</span><ins>+2017-03-02  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Migrate font-stretch to use fixed-point values
+        https://bugs.webkit.org/show_bug.cgi?id=169107
+
+        Reviewed by Dean Jackson.
+
+        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&lt;):
+        (WebCore::FontSelectionValue::operator&lt;=):
+        (WebCore::FontSelectionValue::operator&gt;):
+        (WebCore::FontSelectionValue::operator&gt;=):
+        (WebCore::FontSelectionValue::rawValue):
+        (WebCore::FontSelectionRange::isValid):
+        (WebCore::FontSelectionRange::expand):
+        (WebCore::FontSelectionRange::includes):
+        (WebCore::FontSelectionCapabilities::expand):
+
</ins><span class="cx"> 2017-03-02  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Modernize ContentExtensionParser
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSComputedStyleDeclarationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -1921,26 +1921,26 @@
</span><span class="cx"> 
</span><span class="cx"> static Ref&lt;CSSPrimitiveValue&gt; fontStretchFromStyle(const RenderStyle&amp; style)
</span><span class="cx"> {
</span><del>-    float stretch = style.fontDescription().stretch();
-    if (stretch == 50)
</del><ins>+    auto stretch = style.fontDescription().stretch();
+    if (stretch == FontSelectionValue(50))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueUltraCondensed);
</span><del>-    if (stretch == 62.5)
</del><ins>+    if (stretch == FontSelectionValue(62.5f))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueExtraCondensed);
</span><del>-    if (stretch == 75)
</del><ins>+    if (stretch == FontSelectionValue(75))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueCondensed);
</span><del>-    if (stretch == 87.5)
</del><ins>+    if (stretch == FontSelectionValue(87.5f))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueSemiCondensed);
</span><del>-    if (stretch == 100)
</del><ins>+    if (stretch == FontSelectionValue(100))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
</span><del>-    if (stretch == 112.5)
</del><ins>+    if (stretch == FontSelectionValue(112.5f))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueSemiExpanded);
</span><del>-    if (stretch == 125)
</del><ins>+    if (stretch == FontSelectionValue(125))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueExpanded);
</span><del>-    if (stretch == 150)
</del><ins>+    if (stretch == FontSelectionValue(150))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueExtraExpanded);
</span><del>-    if (stretch == 200)
</del><ins>+    if (stretch == FontSelectionValue(200))
</ins><span class="cx">         return CSSValuePool::singleton().createIdentifierValue(CSSValueUltraExpanded);
</span><del>-    return CSSValuePool::singleton().createValue(stretch, CSSPrimitiveValue::CSS_PERCENTAGE);
</del><ins>+    return CSSValuePool::singleton().createValue(static_cast&lt;float&gt;(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static Ref&lt;CSSValue&gt; fontVariantFromStyle(const RenderStyle&amp; style)
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleBuilderConverterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleBuilderConverter.h (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleBuilderConverter.h        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/css/StyleBuilderConverter.h        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx">     static bool convertOverflowScrolling(StyleResolver&amp;, const CSSValue&amp;);
</span><span class="cx"> #endif
</span><span class="cx">     static FontFeatureSettings convertFontFeatureSettings(StyleResolver&amp;, const CSSValue&amp;);
</span><del>-    static float convertFontStretch(StyleResolver&amp;, const CSSValue&amp;);
</del><ins>+    static FontSelectionValue convertFontStretch(StyleResolver&amp;, const CSSValue&amp;);
</ins><span class="cx"> #if ENABLE(VARIATION_FONTS)
</span><span class="cx">     static FontVariationSettings convertFontVariationSettings(StyleResolver&amp;, const CSSValue&amp;);
</span><span class="cx"> #endif
</span><span class="lines">@@ -1154,35 +1154,43 @@
</span><span class="cx">     return settings;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline float StyleBuilderConverter::convertFontStretch(StyleResolver&amp;, const CSSValue&amp; value)
</del><ins>+inline FontSelectionValue StyleBuilderConverter::convertFontStretch(StyleResolver&amp;, const CSSValue&amp; value)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(is&lt;CSSPrimitiveValue&gt;(value));
</span><span class="cx">     const auto&amp; primitiveValue = downcast&lt;CSSPrimitiveValue&gt;(value);
</span><del>-    if (primitiveValue.isPercentage() || primitiveValue.isNumber())
-        return primitiveValue.floatValue();
</del><ins>+    if (primitiveValue.isPercentage() || primitiveValue.isNumber()) {
+        auto value = primitiveValue.floatValue();
+        if (value &lt;= static_cast&lt;float&gt;(FontSelectionValue::maximumValue())
+            &amp;&amp; value &gt;= static_cast&lt;float&gt;(FontSelectionValue::minimumValue()))
+            return FontSelectionValue(value);
+        if (value &lt; static_cast&lt;float&gt;(FontSelectionValue::minimumValue()))
+            return FontSelectionValue::minimumValue();
+        ASSERT(value &gt; static_cast&lt;float&gt;(FontSelectionValue::maximumValue()));
+        return FontSelectionValue::maximumValue();
+    }
</ins><span class="cx"> 
</span><span class="cx">     switch (primitiveValue.valueID()) {
</span><span class="cx">     case CSSValueUltraCondensed:
</span><del>-        return 50;
</del><ins>+        return FontSelectionValue(50);
</ins><span class="cx">     case CSSValueExtraCondensed:
</span><del>-        return 62.5;
</del><ins>+        return FontSelectionValue(62.5f);
</ins><span class="cx">     case CSSValueCondensed:
</span><del>-        return 75;
</del><ins>+        return FontSelectionValue(75);
</ins><span class="cx">     case CSSValueSemiCondensed:
</span><del>-        return 87.5;
</del><ins>+        return FontSelectionValue(87.5f);
</ins><span class="cx">     case CSSValueNormal:
</span><del>-        return 100;
</del><ins>+        return FontSelectionValue(100);
</ins><span class="cx">     case CSSValueSemiExpanded:
</span><del>-        return 112.5;
</del><ins>+        return FontSelectionValue(112.5f);
</ins><span class="cx">     case CSSValueExpanded:
</span><del>-        return 125;
</del><ins>+        return FontSelectionValue(125);
</ins><span class="cx">     case CSSValueExtraExpanded:
</span><del>-        return 150;
</del><ins>+        return FontSelectionValue(150);
</ins><span class="cx">     case CSSValueUltraExpanded:
</span><del>-        return 200;
</del><ins>+        return FontSelectionValue(200);
</ins><span class="cx">     default:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><del>-        return 100;
</del><ins>+        return FontSelectionValue(100);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontCache.h (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontCache.h        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/platform/graphics/FontCache.h        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -73,12 +73,12 @@
</span><span class="cx">     FontDescriptionKey(const FontDescription&amp; description)
</span><span class="cx">         : m_size(description.computedPixelSize())
</span><span class="cx">         , m_weight(description.weight())
</span><del>-        , m_stretch(description.stretch())
</del><span class="cx">         , m_flags(makeFlagsKey(description))
</span><span class="cx">         , m_featureSettings(description.featureSettings())
</span><span class="cx"> #if ENABLE(VARIATION_FONTS)
</span><span class="cx">         , m_variationSettings(description.variationSettings())
</span><span class="cx"> #endif
</span><ins>+        , m_stretch(description.stretch().rawValue())
</ins><span class="cx">     { }
</span><span class="cx"> 
</span><span class="cx">     explicit FontDescriptionKey(WTF::HashTableDeletedValueType)
</span><span class="lines">@@ -154,12 +154,12 @@
</span><span class="cx">     // FontCascade::locale() is explicitly not included in this struct.
</span><span class="cx">     unsigned m_size { 0 };
</span><span class="cx">     unsigned m_weight { 0 };
</span><del>-    float m_stretch { 0 };
</del><span class="cx">     std::array&lt;unsigned, 2&gt; m_flags {{ 0, 0 }};
</span><span class="cx">     FontFeatureSettings m_featureSettings;
</span><span class="cx"> #if ENABLE(VARIATION_FONTS)
</span><span class="cx">     FontVariationSettings m_variationSettings;
</span><span class="cx"> #endif
</span><ins>+    uint16_t m_stretch { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct FontDescriptionKeyHash {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontDescriptionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontDescription.h (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontDescription.h        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/platform/graphics/FontDescription.h        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> 
</span><span class="cx">     float computedSize() const { return m_computedSize; }
</span><span class="cx">     FontItalic italic() const { return static_cast&lt;FontItalic&gt;(m_italic); }
</span><del>-    float stretch() const { return m_stretch; }
</del><ins>+    FontSelectionValue stretch() const { return m_stretch; }
</ins><span class="cx">     int computedPixelSize() const { return int(m_computedSize + 0.5f); }
</span><span class="cx">     FontWeight weight() const { return static_cast&lt;FontWeight&gt;(m_weight); }
</span><span class="cx">     FontWeight lighterWeight() const;
</span><span class="lines">@@ -98,7 +98,7 @@
</span><span class="cx"> 
</span><span class="cx">     void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
</span><span class="cx">     void setItalic(FontItalic i) { m_italic = i; }
</span><del>-    void setStretch(float stretch) { m_stretch = stretch; }
</del><ins>+    void setStretch(FontSelectionValue stretch) { m_stretch = stretch; }
</ins><span class="cx">     void setIsItalic(bool i) { setItalic(i ? FontItalicOn : FontItalicOff); }
</span><span class="cx">     void setWeight(FontWeight w) { m_weight = w; }
</span><span class="cx">     void setRenderingMode(FontRenderingMode mode) { m_renderingMode = static_cast&lt;unsigned&gt;(mode); }
</span><span class="lines">@@ -136,8 +136,8 @@
</span><span class="cx">     FontVariationSettings m_variationSettings;
</span><span class="cx">     AtomicString m_locale;
</span><span class="cx"> 
</span><del>-    float m_stretch { 100 }; // Stretch, or &quot;width,&quot; of the font
</del><span class="cx">     float m_computedSize { 0 }; // Computed size adjusted for the minimum font size and the zoom factor.
</span><ins>+    FontSelectionValue m_stretch { 100 }; // Stretch, or &quot;width,&quot; of the font
</ins><span class="cx">     unsigned m_orientation : 1; // FontOrientation - Whether the font is rendering on a horizontal line or a vertical line.
</span><span class="cx">     unsigned m_nonCJKGlyphOrientation : 1; // NonCJKGlyphOrientation - Only used by vertical text. Determines the default orientation for non-ideograph glyphs.
</span><span class="cx">     unsigned m_widthVariant : 2; // FontWidthVariant
</span><span class="lines">@@ -265,7 +265,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Initial values for font properties.
</span><span class="cx">     static FontItalic initialItalic() { return FontItalicOff; }
</span><del>-    static float initialStretch() { return 100; }
</del><ins>+    static FontSelectionValue initialStretch() { return FontSelectionValue(100); }
</ins><span class="cx">     static FontSmallCaps initialSmallCaps() { return FontSmallCapsOff; }
</span><span class="cx">     static Kerning initialKerning() { return Kerning::Auto; }
</span><span class="cx">     static FontSmoothingMode initialFontSmoothing() { return AutoSmoothing; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -789,10 +789,6 @@
</span><span class="cx"> 
</span><span class="cx"> #if !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
</span><span class="cx"> 
</span><del>-constexpr float stretchThreshold = 100;
-constexpr float italicThreshold = 20;
-constexpr float weightThreshold = 500;
-
</del><span class="cx"> class FontDatabase {
</span><span class="cx"> public:
</span><span class="cx">     static FontDatabase&amp; singleton()
</span><span class="lines">@@ -804,93 +800,17 @@
</span><span class="cx">     FontDatabase(const FontDatabase&amp;) = delete;
</span><span class="cx">     FontDatabase&amp; operator=(const FontDatabase&amp;) = delete;
</span><span class="cx"> 
</span><del>-    // [Inclusive, Inclusive]
-    struct Range {
-        Range()
-        {
-            ASSERT(!isValid());
-        }
-
-        Range(float minimum, float maximum)
-            : minimum(minimum)
-            , maximum(maximum)
-        {
-            ASSERT(isValid());
-        }
-
-        bool isValid() const
-        {
-            return minimum &lt;= maximum;
-        }
-
-        void expand(const Range&amp; other)
-        {
-            ASSERT(other.isValid());
-            if (!isValid())
-                *this = other;
-            else {
-                minimum = std::min(minimum, other.minimum);
-                maximum = std::max(maximum, other.maximum);
-            }
-            ASSERT(isValid());
-        }
-
-        bool includes(float target) const
-        {
-            return target &gt;= minimum &amp;&amp; target &lt;= maximum;
-        }
-
-        float minimum { 1 };
-        float maximum { 0 };
-    };
-
</del><span class="cx">     struct InstalledFont {
</span><span class="cx">         InstalledFont() = default;
</span><span class="cx"> 
</span><span class="cx">         InstalledFont(CTFontDescriptorRef fontDescriptor)
</span><span class="cx">             : fontDescriptor(fontDescriptor)
</span><ins>+            , capabilities(capabilitiesForFontDescriptor(fontDescriptor))
</ins><span class="cx">         {
</span><del>-            if (!fontDescriptor)
-                return;
-
-            auto traits = adoptCF(static_cast&lt;CFDictionaryRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
-            float width = 0;
-            float slant = 0;
-            float weight = 0;
-            if (traits) {
-                auto widthNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontWidthTrait));
-                if (widthNumber) {
-                    // FIXME: The normalization from Core Text's [-1, 1] range to CSS's [50%, 200%] range isn't perfect.
-                    float ctWidth;
-                    auto success = CFNumberGetValue(widthNumber, kCFNumberFloatType, &amp;ctWidth);
-                    ASSERT_UNUSED(success, success);
-                    width = ctWidth &lt; 0.5 ? ctWidth * 50 + 100 : ctWidth * 150 + 50;
-                }
-
-                auto symbolicTraitsNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait));
-                if (symbolicTraitsNumber) {
-                    int32_t symbolicTraits;
-                    auto success = CFNumberGetValue(symbolicTraitsNumber, kCFNumberSInt32Type, &amp;symbolicTraits);
-                    ASSERT_UNUSED(success, success);
-                    slant = symbolicTraits &amp; kCTFontTraitItalic ? italicThreshold : 0;
-                }
-            }
-
-            auto weightNumber = adoptCF(static_cast&lt;CFNumberRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontCSSWeightAttribute)));
-            if (weightNumber) {
-                auto success = CFNumberGetValue(weightNumber.get(), kCFNumberFloatType, &amp;weight);
-                ASSERT_UNUSED(success, success);
-            }
-            
-            stretch = Range(width, width);
-            style = Range(slant, slant);
-            this-&gt;weight = Range(weight, weight);
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         RetainPtr&lt;CTFontDescriptorRef&gt; fontDescriptor;
</span><del>-        Range stretch;
-        Range style;
-        Range weight;
</del><ins>+        FontSelectionCapabilities capabilities;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     struct InstalledFontFamily {
</span><span class="lines">@@ -905,9 +825,7 @@
</span><span class="cx"> 
</span><span class="cx">         void expand(const InstalledFont&amp; installedFont)
</span><span class="cx">         {
</span><del>-            stretchBounds.expand(installedFont.stretch);
-            styleBounds.expand(installedFont.style);
-            weightBounds.expand(installedFont.weight);
</del><ins>+            capabilities.expand(installedFont.capabilities);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool isEmpty() const
</span><span class="lines">@@ -921,9 +839,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         Vector&lt;InstalledFont&gt; installedFonts;
</span><del>-        Range stretchBounds;
-        Range styleBounds;
-        Range weightBounds;
</del><ins>+        FontSelectionCapabilities capabilities;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     const InstalledFontFamily&amp; collectionForFamily(const String&amp; familyName)
</span><span class="lines">@@ -969,6 +885,65 @@
</span><span class="cx">         m_postScriptNameToFontDescriptors.clear();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static FontSelectionCapabilities capabilitiesForFontDescriptor(CTFontDescriptorRef fontDescriptor)
+    {
+        if (!fontDescriptor)
+            return { };
+
+        auto traits = adoptCF(static_cast&lt;CFDictionaryRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
+        FontSelectionValue width;
+        FontSelectionValue slant;
+        FontSelectionValue weight;
+        if (traits) {
+            auto widthNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontWidthTrait));
+            if (widthNumber) {
+                // FIXME: The normalization from Core Text's [-1, 1] range to CSS's [50%, 200%] range isn't perfect.
+                float ctWidth;
+                auto success = CFNumberGetValue(widthNumber, kCFNumberFloatType, &amp;ctWidth);
+                ASSERT_UNUSED(success, success);
+                width = FontSelectionValue(ctWidth &lt; 0.5 ? ctWidth * 50 + 100 : ctWidth * 150 + 50);
+            }
+
+            auto symbolicTraitsNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait));
+            if (symbolicTraitsNumber) {
+                int32_t symbolicTraits;
+                auto success = CFNumberGetValue(symbolicTraitsNumber, kCFNumberSInt32Type, &amp;symbolicTraits);
+                ASSERT_UNUSED(success, success);
+                slant = symbolicTraits &amp; kCTFontTraitItalic ? italicThreshold() : FontSelectionValue();
+            }
+        }
+
+        auto weightNumber = adoptCF(static_cast&lt;CFNumberRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontCSSWeightAttribute)));
+        if (weightNumber) {
+            float cssWeight;
+            auto success = CFNumberGetValue(weightNumber.get(), kCFNumberFloatType, &amp;cssWeight);
+            ASSERT_UNUSED(success, success);
+            weight = FontSelectionValue(cssWeight);
+        }
+
+        // FIXME: Educate this function about font variations.
+
+        return { { weight, weight }, { width, width }, { slant, slant } };
+    }
+
+    static const FontSelectionValue stretchThreshold()
+    {
+        static NeverDestroyed&lt;FontSelectionValue&gt; threshold(100);
+        return threshold.get();
+    }
+
+    static const FontSelectionValue italicThreshold()
+    {
+        static NeverDestroyed&lt;FontSelectionValue&gt; threshold(20);
+        return threshold.get();
+    }
+
+    static const FontSelectionValue weightThreshold()
+    {
+        static NeverDestroyed&lt;FontSelectionValue&gt; threshold(500);
+        return threshold.get();
+    }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class NeverDestroyed&lt;FontDatabase&gt;;
</span><span class="cx"> 
</span><span class="lines">@@ -1002,33 +977,35 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline std::optional&lt;float&gt; findClosestStretch(float targetStretch, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline std::optional&lt;FontSelectionValue&gt; findClosestStretch(FontSelectionValue targetStretch, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     std::function&lt;float(const FontDatabase::InstalledFont&amp;)&gt; computeScore;
</span><span class="cx"> 
</span><del>-    if (targetStretch &gt;= stretchThreshold) {
-        float threshold = std::max(targetStretch, installedFonts.stretchBounds.maximum);
</del><ins>+    if (targetStretch &gt;= FontDatabase::stretchThreshold()) {
+        auto threshold = std::max(targetStretch, installedFonts.capabilities.width.maximum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            ASSERT(font.stretch.isValid());
-            if (font.stretch.includes(targetStretch))
</del><ins>+            auto width = font.capabilities.width;
+            ASSERT(width.isValid());
+            if (width.includes(targetStretch))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.stretch.minimum &gt; targetStretch || font.stretch.maximum &lt; targetStretch);
-            if (font.stretch.minimum &gt; targetStretch)
-                return font.stretch.minimum - targetStretch;
-            ASSERT(font.stretch.maximum &lt; targetStretch);
-            return threshold - font.stretch.maximum;
</del><ins>+            ASSERT(width.minimum &gt; targetStretch || width.maximum &lt; targetStretch);
+            if (width.minimum &gt; targetStretch)
+                return width.minimum - targetStretch;
+            ASSERT(width.maximum &lt; targetStretch);
+            return threshold - width.maximum;
</ins><span class="cx">         };
</span><span class="cx">     } else {
</span><del>-        ASSERT(targetStretch &lt; stretchThreshold);
-        float threshold = std::min(targetStretch, installedFonts.stretchBounds.minimum);
</del><ins>+        ASSERT(targetStretch &lt; FontDatabase::stretchThreshold());
+        auto threshold = std::min(targetStretch, installedFonts.capabilities.width.minimum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            if (font.stretch.includes(targetStretch))
</del><ins>+            auto width = font.capabilities.width;
+            if (width.includes(targetStretch))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.stretch.minimum &gt; targetStretch || font.stretch.maximum &lt; targetStretch);
-            if (font.stretch.maximum &lt; targetStretch)
-                return targetStretch - font.stretch.maximum;
-            ASSERT(font.stretch.minimum &gt; targetStretch);
-            return font.stretch.minimum - threshold;
</del><ins>+            ASSERT(width.minimum &gt; targetStretch || width.maximum &lt; targetStretch);
+            if (width.maximum &lt; targetStretch)
+                return targetStretch - width.maximum;
+            ASSERT(width.minimum &gt; targetStretch);
+            return width.minimum - threshold;
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1045,78 +1022,83 @@
</span><span class="cx">     if (!minimumScore)
</span><span class="cx">         return std::nullopt;
</span><span class="cx">     auto&amp; winner = installedFonts.installedFonts[closestIndex];
</span><del>-    if (winner.stretch.includes(targetStretch))
</del><ins>+    auto width = winner.capabilities.width;
+    if (width.includes(targetStretch))
</ins><span class="cx">         return targetStretch;
</span><del>-    if (winner.stretch.minimum &gt; targetStretch)
-        return winner.stretch.minimum;
-    ASSERT(winner.stretch.maximum &lt; targetStretch);
-    return winner.stretch.maximum;
</del><ins>+    if (width.minimum &gt; targetStretch)
+        return width.minimum;
+    ASSERT(width.maximum &lt; targetStretch);
+    return width.maximum;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void filterStretch(float target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline void filterStretch(FontSelectionValue target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     iterateActiveFonts(installedFonts, filter, [&amp;](auto&amp; installedFont, size_t i) {
</span><del>-        if (!installedFont.stretch.includes(target))
</del><ins>+        if (!installedFont.capabilities.width.includes(target))
</ins><span class="cx">             filter[i] = false;
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline std::optional&lt;float&gt; findClosestStyle(float targetStyle, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline std::optional&lt;FontSelectionValue&gt; findClosestStyle(FontSelectionValue targetStyle, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     std::function&lt;float(const FontDatabase::InstalledFont&amp;)&gt; computeScore;
</span><span class="cx"> 
</span><del>-    if (targetStyle &gt;= italicThreshold) {
-        float threshold = std::max(targetStyle, installedFonts.styleBounds.maximum);
</del><ins>+    if (targetStyle &gt;= FontDatabase::italicThreshold()) {
+        auto threshold = std::max(targetStyle, installedFonts.capabilities.slope.maximum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            ASSERT(font.style.isValid());
-            if (font.style.includes(targetStyle))
</del><ins>+            auto slope = font.capabilities.slope;
+            ASSERT(slope.isValid());
+            if (slope.includes(targetStyle))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.style.minimum &gt; targetStyle || font.style.maximum &lt; targetStyle);
-            if (font.style.minimum &gt; targetStyle)
-                return font.style.minimum - targetStyle;
-            ASSERT(targetStyle &gt; font.style.maximum);
-            return threshold - font.style.maximum;
</del><ins>+            ASSERT(slope.minimum &gt; targetStyle || slope.maximum &lt; targetStyle);
+            if (slope.minimum &gt; targetStyle)
+                return slope.minimum - targetStyle;
+            ASSERT(targetStyle &gt; slope.maximum);
+            return threshold - slope.maximum;
</ins><span class="cx">         };
</span><del>-    } else if (targetStyle &gt;= 0) {
-        float threshold = std::max(targetStyle, installedFonts.styleBounds.maximum);
</del><ins>+    } else if (targetStyle &gt;= FontSelectionValue()) {
+        auto threshold = std::max(targetStyle, installedFonts.capabilities.slope.maximum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            ASSERT(font.style.isValid());
-            if (font.style.includes(targetStyle))
</del><ins>+            auto slope = font.capabilities.slope;
+            ASSERT(slope.isValid());
+            if (slope.includes(targetStyle))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.style.minimum &gt; targetStyle || font.style.maximum &lt; targetStyle);
-            if (font.style.maximum &gt;= 0 &amp;&amp; font.style.maximum &lt; targetStyle)
-                return targetStyle - font.style.maximum;
-            if (font.style.minimum &gt; targetStyle)
-                return font.style.minimum;
-            ASSERT(font.style.maximum &lt; 0);
-            return threshold - font.style.maximum;
</del><ins>+            ASSERT(slope.minimum &gt; targetStyle || slope.maximum &lt; targetStyle);
+            if (slope.maximum &gt;= FontSelectionValue() &amp;&amp; slope.maximum &lt; targetStyle)
+                return targetStyle - slope.maximum;
+            if (slope.minimum &gt; targetStyle)
+                return slope.minimum;
+            ASSERT(slope.maximum &lt; FontSelectionValue());
+            return threshold - slope.maximum;
</ins><span class="cx">         };
</span><del>-    } else if (targetStyle &gt; -italicThreshold) {
-        float threshold = std::min(targetStyle, installedFonts.styleBounds.minimum);
</del><ins>+    } else if (targetStyle &gt; -FontDatabase::italicThreshold()) {
+        auto threshold = std::min(targetStyle, installedFonts.capabilities.slope.minimum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            ASSERT(font.style.isValid());
-            if (font.style.includes(targetStyle))
</del><ins>+            auto slope = font.capabilities.slope;
+            ASSERT(slope.isValid());
+            if (slope.includes(targetStyle))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.style.minimum &gt; targetStyle || font.style.maximum &lt; targetStyle);
-            if (font.style.minimum &gt; targetStyle &amp;&amp; font.style.minimum &lt;= 0)
-                return font.style.minimum - targetStyle;
-            if (font.style.maximum &lt; targetStyle)
-                return -font.style.maximum;
-            ASSERT(font.style.minimum &gt; 0);
-            return font.style.minimum - threshold;
</del><ins>+            ASSERT(slope.minimum &gt; targetStyle || slope.maximum &lt; targetStyle);
+            if (slope.minimum &gt; targetStyle &amp;&amp; slope.minimum &lt;= FontSelectionValue())
+                return slope.minimum - targetStyle;
+            if (slope.maximum &lt; targetStyle)
+                return -slope.maximum;
+            ASSERT(slope.minimum &gt; FontSelectionValue());
+            return slope.minimum - threshold;
</ins><span class="cx">         };
</span><span class="cx">     } else {
</span><del>-        ASSERT(targetStyle &lt;= -italicThreshold);
-        float threshold = std::min(targetStyle, installedFonts.styleBounds.minimum);
</del><ins>+        ASSERT(targetStyle &lt;= -FontDatabase::italicThreshold());
+        auto threshold = std::min(targetStyle, installedFonts.capabilities.slope.minimum);
</ins><span class="cx">         computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
</span><del>-            ASSERT(font.style.isValid());
-            if (font.style.includes(targetStyle))
</del><ins>+            auto slope = font.capabilities.slope;
+            ASSERT(slope.isValid());
+            if (slope.includes(targetStyle))
</ins><span class="cx">                 return 0;
</span><del>-            ASSERT(font.style.minimum &gt; targetStyle || font.style.maximum &lt; targetStyle);
-            if (font.style.maximum &lt; targetStyle)
-                return targetStyle - font.style.maximum;
-            ASSERT(font.style.minimum &gt; targetStyle);
-            return font.style.minimum - threshold;
</del><ins>+            ASSERT(slope.minimum &gt; targetStyle || slope.maximum &lt; targetStyle);
+            if (slope.maximum &lt; targetStyle)
+                return targetStyle - slope.maximum;
+            ASSERT(slope.minimum &gt; targetStyle);
+            return slope.minimum - threshold;
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1133,42 +1115,43 @@
</span><span class="cx">     if (!minimumScore)
</span><span class="cx">         return std::nullopt;
</span><span class="cx">     auto&amp; winner = installedFonts.installedFonts[closestIndex];
</span><del>-    if (winner.style.includes(targetStyle))
</del><ins>+    auto slope = winner.capabilities.slope;
+    if (slope.includes(targetStyle))
</ins><span class="cx">         return targetStyle;
</span><del>-    if (winner.style.minimum &gt; targetStyle)
-        return winner.style.minimum;
-    ASSERT(winner.style.maximum &lt; targetStyle);
-    return winner.style.maximum;
</del><ins>+    if (slope.minimum &gt; targetStyle)
+        return slope.minimum;
+    ASSERT(slope.maximum &lt; targetStyle);
+    return slope.maximum;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void filterStyle(float target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline void filterStyle(FontSelectionValue target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     iterateActiveFonts(installedFonts, filter, [&amp;](auto&amp; installedFont, size_t i) {
</span><del>-        if (!installedFont.style.includes(target))
</del><ins>+        if (!installedFont.capabilities.slope.includes(target))
</ins><span class="cx">             filter[i] = false;
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline std::optional&lt;float&gt; findClosestWeight(float targetWeight, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline std::optional&lt;FontSelectionValue&gt; findClosestWeight(FontSelectionValue targetWeight, const FontDatabase::InstalledFontFamily&amp; installedFonts, const std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     {
</span><span class="cx">         // The spec states: &quot;If the desired weight is 400, 500 is checked first ... If the desired weight is 500, 400 is checked first&quot;
</span><del>-        IterateActiveFontsWithReturnCallback&lt;float&gt; searchFor400 = [&amp;](const FontDatabase::InstalledFont&amp; font, size_t) -&gt; std::optional&lt;float&gt; {
-            if (font.weight.includes(400))
-                return 400;
</del><ins>+        IterateActiveFontsWithReturnCallback&lt;FontSelectionValue&gt; searchFor400 = [&amp;](const FontDatabase::InstalledFont&amp; font, size_t) -&gt; std::optional&lt;FontSelectionValue&gt; {
+            if (font.capabilities.weight.includes(FontSelectionValue(400)))
+                return FontSelectionValue(400);
</ins><span class="cx">             return std::nullopt;
</span><span class="cx">         };
</span><del>-        IterateActiveFontsWithReturnCallback&lt;float&gt; searchFor500 = [&amp;](const FontDatabase::InstalledFont&amp; font, size_t) -&gt; std::optional&lt;float&gt; {
-            if (font.weight.includes(500))
-                return 500;
</del><ins>+        IterateActiveFontsWithReturnCallback&lt;FontSelectionValue&gt; searchFor500 = [&amp;](const FontDatabase::InstalledFont&amp; font, size_t) -&gt; std::optional&lt;FontSelectionValue&gt; {
+            if (font.capabilities.weight.includes(FontSelectionValue(500)))
+                return FontSelectionValue(500);
</ins><span class="cx">             return std::nullopt;
</span><span class="cx">         };
</span><del>-        if (targetWeight == 400) {
</del><ins>+        if (targetWeight == FontSelectionValue(400)) {
</ins><span class="cx">             if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor400))
</span><span class="cx">                 return result;
</span><span class="cx">             if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor500))
</span><span class="cx">                 return result;
</span><del>-        } else if (targetWeight == 500) {
</del><ins>+        } else if (targetWeight == FontSelectionValue(500)) {
</ins><span class="cx">             if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor500))
</span><span class="cx">                 return result;
</span><span class="cx">             if (auto result = iterateActiveFontsWithReturn(installedFonts, filter, searchFor400))
</span><span class="lines">@@ -1177,28 +1160,30 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::function&lt;float(const FontDatabase::InstalledFont&amp;)&gt; computeScore;
</span><del>-    if (targetWeight &lt;= weightThreshold) {
-        float threshold = std::min(targetWeight, installedFonts.weightBounds.minimum);
-        computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
-            if (font.weight.includes(targetWeight))
-                return 0;
-            ASSERT(font.weight.minimum &gt; targetWeight || font.weight.maximum &lt; targetWeight);
-            if (font.weight.maximum &lt; targetWeight)
-                return targetWeight - font.weight.maximum;
-            ASSERT(font.weight.minimum &gt; targetWeight);
-            return font.weight.minimum - threshold;
</del><ins>+    if (targetWeight &lt;= FontDatabase::weightThreshold()) {
+        auto threshold = std::min(targetWeight, installedFonts.capabilities.weight.minimum);
+        computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; FontSelectionValue {
+            auto weight = font.capabilities.weight;
+            if (weight.includes(targetWeight))
+                return FontSelectionValue();
+            ASSERT(weight.minimum &gt; targetWeight || weight.maximum &lt; targetWeight);
+            if (weight.maximum &lt; targetWeight)
+                return targetWeight - weight.maximum;
+            ASSERT(weight.minimum &gt; targetWeight);
+            return weight.minimum - threshold;
</ins><span class="cx">         };
</span><span class="cx">     } else {
</span><del>-        ASSERT(targetWeight &gt; weightThreshold);
-        float threshold = std::max(targetWeight, installedFonts.weightBounds.maximum);
-        computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; float {
-            if (font.weight.includes(targetWeight))
-                return 0;
-            ASSERT(font.weight.minimum &gt; targetWeight || font.weight.maximum &lt; targetWeight);
-            if (font.weight.minimum &gt; targetWeight)
-                return font.weight.minimum - targetWeight;
-            ASSERT(font.weight.maximum &lt; targetWeight);
-            return threshold - font.weight.maximum;
</del><ins>+        ASSERT(targetWeight &gt; FontDatabase::weightThreshold());
+        auto threshold = std::max(targetWeight, installedFonts.capabilities.weight.maximum);
+        computeScore = [&amp;, threshold](const FontDatabase::InstalledFont&amp; font) -&gt; FontSelectionValue {
+            auto weight = font.capabilities.weight;
+            if (weight.includes(targetWeight))
+                return FontSelectionValue();
+            ASSERT(weight.minimum &gt; targetWeight || weight.maximum &lt; targetWeight);
+            if (weight.minimum &gt; targetWeight)
+                return weight.minimum - targetWeight;
+            ASSERT(weight.maximum &lt; targetWeight);
+            return threshold - weight.maximum;
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1215,50 +1200,51 @@
</span><span class="cx">     if (!minimumScore)
</span><span class="cx">         return std::nullopt;
</span><span class="cx">     auto&amp; winner = installedFonts.installedFonts[closestIndex];
</span><del>-    if (winner.weight.includes(targetWeight))
</del><ins>+    auto weight = winner.capabilities.weight;
+    if (weight.includes(targetWeight))
</ins><span class="cx">         return targetWeight;
</span><del>-    if (winner.weight.minimum &gt; targetWeight)
-        return winner.weight.minimum;
-    ASSERT(winner.weight.maximum &lt; targetWeight);
-    return winner.weight.maximum;
</del><ins>+    if (weight.minimum &gt; targetWeight)
+        return weight.minimum;
+    ASSERT(weight.maximum &lt; targetWeight);
+    return weight.maximum;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void filterWeight(float target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</del><ins>+static inline void filterWeight(FontSelectionValue target, const FontDatabase::InstalledFontFamily&amp; installedFonts, std::unique_ptr&lt;bool[]&gt;&amp; filter)
</ins><span class="cx"> {
</span><span class="cx">     iterateActiveFonts(installedFonts, filter, [&amp;](auto&amp; installedFont, size_t i) {
</span><del>-        if (!installedFont.weight.includes(target))
</del><ins>+        if (!installedFont.capabilities.weight.includes(target))
</ins><span class="cx">             filter[i] = false;
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline float computeTargetWeight(FontWeight weight)
</del><ins>+static inline FontSelectionValue computeTargetWeight(FontWeight weight)
</ins><span class="cx"> {
</span><span class="cx">     switch (weight) {
</span><span class="cx">     case FontWeight100:
</span><del>-        return 100;
</del><ins>+        return FontSelectionValue(100);
</ins><span class="cx">     case FontWeight200:
</span><del>-        return 200;
</del><ins>+        return FontSelectionValue(200);
</ins><span class="cx">     case FontWeight300:
</span><del>-        return 300;
</del><ins>+        return FontSelectionValue(300);
</ins><span class="cx">     case FontWeight400:
</span><del>-        return 400;
</del><ins>+        return FontSelectionValue(400);
</ins><span class="cx">     case FontWeight500:
</span><del>-        return 500;
</del><ins>+        return FontSelectionValue(500);
</ins><span class="cx">     case FontWeight600:
</span><del>-        return 600;
</del><ins>+        return FontSelectionValue(600);
</ins><span class="cx">     case FontWeight700:
</span><del>-        return 700;
</del><ins>+        return FontSelectionValue(700);
</ins><span class="cx">     case FontWeight800:
</span><del>-        return 800;
</del><ins>+        return FontSelectionValue(800);
</ins><span class="cx">     case FontWeight900:
</span><del>-        return 900;
</del><ins>+        return FontSelectionValue(900);
</ins><span class="cx">     default:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><del>-        return 400;
</del><ins>+        return FontSelectionValue(400);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static const FontDatabase::InstalledFont* findClosestFont(const FontDatabase::InstalledFontFamily&amp; familyFonts, CTFontSymbolicTraits requestedTraits, FontWeight weight, float stretch)
</del><ins>+static const FontDatabase::InstalledFont* findClosestFont(const FontDatabase::InstalledFontFamily&amp; familyFonts, CTFontSymbolicTraits requestedTraits, FontWeight weight, FontSelectionValue stretch)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!familyFonts.isEmpty());
</span><span class="cx"> 
</span><span class="lines">@@ -1267,20 +1253,18 @@
</span><span class="cx">     for (size_t i = 0; i &lt; familyFonts.size(); ++i)
</span><span class="cx">         filter[i] = true;
</span><span class="cx"> 
</span><del>-    // FIXME: Implement this.
-    float targetStretch = stretch;
-    if (auto closestStretch = findClosestStretch(targetStretch, familyFonts, filter))
</del><ins>+    if (auto closestStretch = findClosestStretch(stretch, familyFonts, filter))
</ins><span class="cx">         filterStretch(closestStretch.value(), familyFonts, filter);
</span><span class="cx">     else
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    float targetStyle = requestedTraits &amp; kCTFontTraitItalic ? italicThreshold : 0;
</del><ins>+    FontSelectionValue targetStyle = requestedTraits &amp; kCTFontTraitItalic ? FontDatabase::italicThreshold() : FontSelectionValue();
</ins><span class="cx">     if (auto closestStyle = findClosestStyle(targetStyle, familyFonts, filter))
</span><span class="cx">         filterStyle(closestStyle.value(), familyFonts, filter);
</span><span class="cx">     else
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    float targetWeight = computeTargetWeight(weight);
</del><ins>+    FontSelectionValue targetWeight = computeTargetWeight(weight);
</ins><span class="cx">     if (auto closestWeight = findClosestWeight(targetWeight, familyFonts, filter))
</span><span class="cx">         filterWeight(closestWeight.value(), familyFonts, filter);
</span><span class="cx">     else
</span><span class="lines">@@ -1293,7 +1277,7 @@
</span><span class="cx"> 
</span><span class="cx"> #endif // !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
</span><span class="cx"> 
</span><del>-static RetainPtr&lt;CTFontRef&gt; platformFontLookupWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits requestedTraits, FontWeight weight, float stretch, float size)
</del><ins>+static RetainPtr&lt;CTFontRef&gt; platformFontLookupWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits requestedTraits, FontWeight weight, FontSelectionValue stretch, float size)
</ins><span class="cx"> {
</span><span class="cx">     const auto&amp; whitelist = fontWhitelist();
</span><span class="cx">     if (!isSystemFont(family) &amp;&amp; whitelist.size() &amp;&amp; !whitelist.contains(family))
</span><span class="lines">@@ -1316,7 +1300,8 @@
</span><span class="cx">         const auto&amp; postScriptFont = FontDatabase::singleton().fontForPostScriptName(family);
</span><span class="cx">         if (!postScriptFont.fontDescriptor)
</span><span class="cx">             return nullptr;
</span><del>-        if (((requestedTraits &amp; kCTFontTraitItalic) &amp;&amp; postScriptFont.style.maximum &lt; italicThreshold) || (weight &gt;= FontWeight600 &amp;&amp; postScriptFont.weight.maximum &lt; 600)) {
</del><ins>+        if (((requestedTraits &amp; kCTFontTraitItalic) &amp;&amp; postScriptFont.capabilities.slope.maximum &lt; FontDatabase::italicThreshold())
+            || (weight &gt;= FontWeight600 &amp;&amp; postScriptFont.capabilities.weight.maximum &lt; FontSelectionValue(600))) {
</ins><span class="cx">             auto postScriptFamilyName = adoptCF(static_cast&lt;CFStringRef&gt;(CTFontDescriptorCopyAttribute(postScriptFont.fontDescriptor.get(), kCTFontFamilyNameAttribute)));
</span><span class="cx">             if (!postScriptFamilyName)
</span><span class="cx">                 return nullptr;
</span><span class="lines">@@ -1356,7 +1341,7 @@
</span><span class="cx">     FontCache::singleton().invalidate();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RetainPtr&lt;CTFontRef&gt; fontWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits desiredTraits, FontWeight weight, float stretch, const FontFeatureSettings&amp; featureSettings, const FontVariantSettings&amp; variantSettings, const FontVariationSettings&amp; variationSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode&amp; textRenderingMode, float size)
</del><ins>+static RetainPtr&lt;CTFontRef&gt; fontWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits desiredTraits, FontWeight weight, FontSelectionValue stretch, const FontFeatureSettings&amp; featureSettings, const FontVariantSettings&amp; variantSettings, const FontVariationSettings&amp; variationSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode&amp; textRenderingMode, float size)
</ins><span class="cx"> {
</span><span class="cx">     if (family.isEmpty())
</span><span class="cx">         return nullptr;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformtextTextFlagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/TextFlags.h (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/TextFlags.h        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Source/WebCore/platform/text/TextFlags.h        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -23,9 +23,10 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef TextFlags_h
-#define TextFlags_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> enum TextRenderingMode { AutoTextRendering, OptimizeSpeed, OptimizeLegibility, GeometricPrecision };
</span><span class="lines">@@ -397,6 +398,162 @@
</span><span class="cx">     FontWeightMask = FontWeight100Mask | FontWeight200Mask | FontWeight300Mask | FontWeight400Mask | FontWeight500Mask | FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// Unclamped, unchecked, signed fixed-point number representing a value used for font variations.
+// Sixteen bits in total, one sign bit, two fractional bits, means the smallest positive representable value is 0.25,
+// the maximum representable value is 8191.75, and the minimum representable value is -8192.
+class FontSelectionValue {
+public:
+    FontSelectionValue() = default;
+
+    // Explicit because it is lossy.
+    explicit FontSelectionValue(int x)
+        : m_backing(x * fractionalEntropy)
+    {
+    }
+
+    // Explicit because it is lossy.
+    explicit FontSelectionValue(float x)
+        : m_backing(x * fractionalEntropy)
+    {
+    }
+
+    operator float() const
+    {
+        // floats have 23 fractional bits, but only 14 fractional bits are necessary, so every value can be represented losslessly.
+        return m_backing / static_cast&lt;float&gt;(fractionalEntropy);
+    }
+
+    FontSelectionValue operator+(const FontSelectionValue other) const
+    {
+        return FontSelectionValue(m_backing + other.m_backing, RawTag::RawTag);
+    }
+
+    FontSelectionValue operator-(const FontSelectionValue other) const
+    {
+        return FontSelectionValue(m_backing - other.m_backing, RawTag::RawTag);
+    }
+
+    FontSelectionValue operator*(const FontSelectionValue other) const
+    {
+        return FontSelectionValue(static_cast&lt;int32_t&gt;(m_backing) * other.m_backing / fractionalEntropy, RawTag::RawTag);
+    }
+
+    FontSelectionValue operator/(const FontSelectionValue other) const
+    {
+        return FontSelectionValue(static_cast&lt;int32_t&gt;(m_backing) / other.m_backing * fractionalEntropy, RawTag::RawTag);
+    }
+
+    FontSelectionValue operator-() const
+    {
+        return FontSelectionValue(-m_backing, RawTag::RawTag);
+    }
+
+    bool operator==(const FontSelectionValue other) const
+    {
+        return m_backing == other.m_backing;
+    }
+
+    bool operator!=(const FontSelectionValue other) const
+    {
+        return !operator==(other);
+    }
+
+    bool operator&lt;(const FontSelectionValue other) const
+    {
+        return m_backing &lt; other.m_backing;
+    }
+
+    bool operator&lt;=(const FontSelectionValue other) const
+    {
+        return m_backing &lt;= other.m_backing;
+    }
+
+    bool operator&gt;(const FontSelectionValue other) const
+    {
+        return m_backing &gt; other.m_backing;
+    }
+
+    bool operator&gt;=(const FontSelectionValue other) const
+    {
+        return m_backing &gt;= other.m_backing;
+    }
+
+    int16_t rawValue() const
+    {
+        return m_backing;
+    }
+
+    static FontSelectionValue maximumValue()
+    {
+        static NeverDestroyed&lt;FontSelectionValue&gt; result = FontSelectionValue(std::numeric_limits&lt;int16_t&gt;::max(), RawTag::RawTag);
+        return result.get();
+    }
+
+    static FontSelectionValue minimumValue()
+    {
+        static NeverDestroyed&lt;FontSelectionValue&gt; result = FontSelectionValue(std::numeric_limits&lt;int16_t&gt;::min(), RawTag::RawTag);
+        return result.get();
+    }
+
+private:
+    enum class RawTag { RawTag };
+
+    FontSelectionValue(int16_t rawValue, RawTag)
+        : m_backing(rawValue)
+    {
+    }
+
+    static constexpr int fractionalEntropy = 4;
+    int16_t m_backing { 0 };
+};
+
+// [Inclusive, Inclusive]
+struct FontSelectionRange {
+    bool isValid() const
+    {
+        return minimum &lt;= maximum;
+    }
+
+    void expand(const FontSelectionRange&amp; other)
+    {
+        ASSERT(other.isValid());
+        if (!isValid())
+            *this = other;
+        else {
+            minimum = std::min(minimum, other.minimum);
+            maximum = std::max(maximum, other.maximum);
+        }
+        ASSERT(isValid());
+    }
+
+    bool includes(FontSelectionValue target) const
+    {
+        return target &gt;= minimum &amp;&amp; target &lt;= maximum;
+    }
+
+    FontSelectionValue minimum { FontSelectionValue(1) };
+    FontSelectionValue maximum { FontSelectionValue(0) };
+};
+
+struct FontSelectionRequest {
+    FontSelectionValue weight;
+    FontSelectionValue width;
+    FontSelectionValue slope;
+};
+
+struct FontSelectionCapabilities {
+    void expand(const FontSelectionCapabilities&amp; capabilities)
+    {
+        weight.expand(capabilities.weight);
+        width.expand(capabilities.width);
+        slope.expand(capabilities.slope);
+    }
+
+    FontSelectionRange weight;
+    FontSelectionRange width;
+    FontSelectionRange slope;
+};
+
</ins><span class="cx"> enum class Kerning {
</span><span class="cx">     Auto,
</span><span class="cx">     Normal,
</span><span class="lines">@@ -404,5 +561,3 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Tools/ChangeLog        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-03-02  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Migrate font-stretch to use fixed-point values
+        https://bugs.webkit.org/show_bug.cgi?id=169107
+
+        Reviewed by Dean Jackson.
+
+        Update to new types.
+
+        * TestWebKitAPI/Tests/WebCore/FontCache.cpp:
+        (TestWebKitAPI::createPlatformFont):
+
</ins><span class="cx"> 2017-03-02  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update WKWebsiteDatastoreConfiguration SPI.
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreFontCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/FontCache.cpp (213340 => 213341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/FontCache.cpp        2017-03-03 02:45:28 UTC (rev 213340)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/FontCache.cpp        2017-03-03 03:17:35 UTC (rev 213341)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx">     description.setOneFamily(familyNameString);
</span><span class="cx">     description.setWeight(weight);
</span><span class="cx">     description.setItalic(italic);
</span><del>-    description.setStretch(stretch);
</del><ins>+    description.setStretch(FontSelectionValue(stretch));
</ins><span class="cx">     description.setComputedSize(size);
</span><span class="cx"> 
</span><span class="cx">     auto&amp; fontCache = FontCache::singleton();
</span></span></pre>
</div>
</div>

</body>
</html>