<!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>[213528] 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/213528">213528</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2017-03-07 11:26:21 -0800 (Tue, 07 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Parsing font descriptors inside @font-face needs to accept ranges
https://bugs.webkit.org/show_bug.cgi?id=168893

Reviewed by Dean Jackson.

Source/WebCore:

Parse font-weight, font-stretch, and font-style ranges according to
https://drafts.csswg.org/css-fonts-4/#font-prop-desc. There is one difference, though:
as documented in https://github.com/w3c/csswg-drafts/issues/783, slashes are a better
delimiters than hyphens, so this patch implements that instead. I'll update the spec to
include slashes as soon as possible.

Because this patch is all about creating FontSelectionValues from fonts, it doesn't
actually modify the font selection algorithm, and therefore only tests the creation of
these new values. The font selection algorithm itself is already tested elsewhere.

This new work is behind the ENABLE(VARIATION_FONTS) flag.

Test: fast/text/font-selection-font-face-parse.html

* css/CSSFontFace.cpp:
(WebCore::calculateWeightRange):
(WebCore::calculateStretchRange):
(WebCore::calculateItalicRange):
* css/parser/CSSPropertyParser.cpp:
(WebCore::consumeFontWeightRange):
(WebCore::consumeFontStretchRange):
(WebCore::consumeFontStyleRange):
(WebCore::CSSPropertyParser::parseFontFaceDescriptor):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::extractVariationBounds):
(WebCore::variationCapabilitiesForFontDescriptor):
(WebCore::capabilitiesForFontDescriptor):

LayoutTests:

* fast/text/font-selection-font-face-parse-expected.txt:
* fast/text/font-selection-font-face-parse.html:
* platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt:
Variations are off on El Capitan, so this platform needs explicit results.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasttextfontselectionfontfaceparseexpectedtxt">trunk/LayoutTests/fast/text/font-selection-font-face-parse-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttextfontselectionfontfaceparsehtml">trunk/LayoutTests/fast/text/font-selection-font-face-parse.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFacecpp">trunk/Source/WebCore/css/CSSFontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSPropertyParsercpp">trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp">trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsplatformmacelcapitanfasttextfontselectionfontfaceparseexpectedtxt">trunk/LayoutTests/platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/LayoutTests/ChangeLog        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-03-07  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Parsing font descriptors inside @font-face needs to accept ranges
+        https://bugs.webkit.org/show_bug.cgi?id=168893
+
+        Reviewed by Dean Jackson.
+
+        * fast/text/font-selection-font-face-parse-expected.txt:
+        * fast/text/font-selection-font-face-parse.html:
+        * platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt:
+        Variations are off on El Capitan, so this platform needs explicit results.
+
</ins><span class="cx"> 2017-03-07  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move webrtc/descriptionGetters.html to webrtc/libwebrtc/descriptionGetters.html
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextfontselectionfontfaceparseexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/font-selection-font-face-parse-expected.txt (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/font-selection-font-face-parse-expected.txt        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/LayoutTests/fast/text/font-selection-font-face-parse-expected.txt        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -16,6 +16,19 @@
</span><span class="cx"> PASS weightTestSheet.cssRules[15].style.fontWeight is &quot;7&quot;
</span><span class="cx"> PASS weightTestSheet.cssRules[16].style.fontWeight is &quot;300&quot;
</span><span class="cx"> PASS weightTestSheet.cssRules[17].style.fontWeight is &quot;200&quot;
</span><ins>+PASS weightTestSheet.cssRules[18].style.fontWeight is &quot;100 / 200&quot;
+PASS weightTestSheet.cssRules[19].style.fontWeight is &quot;100 / 200&quot;
+PASS weightTestSheet.cssRules[20].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[21].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[22].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[23].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[24].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[25].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[26].style.fontWeight is &quot;1 / 2&quot;
+PASS weightTestSheet.cssRules[27].style.fontWeight is &quot;-2 / -1&quot;
+PASS weightTestSheet.cssRules[28].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[29].style.fontWeight is &quot;7 / 8&quot;
+PASS weightTestSheet.cssRules[30].style.fontWeight is &quot;2 / 7&quot;
</ins><span class="cx"> PASS stretchTestSheet.cssRules[0].style.fontStretch is &quot;1%&quot;
</span><span class="cx"> PASS stretchTestSheet.cssRules[1].style.fontStretch is &quot;2&quot;
</span><span class="cx"> PASS stretchTestSheet.cssRules[2].style.fontStretch is &quot;ultra-condensed&quot;
</span><span class="lines">@@ -30,6 +43,32 @@
</span><span class="cx"> PASS stretchTestSheet.cssRules[11].style.fontStretch is &quot;&quot;
</span><span class="cx"> PASS stretchTestSheet.cssRules[12].style.fontStretch is &quot;&quot;
</span><span class="cx"> PASS stretchTestSheet.cssRules[13].style.fontStretch is &quot;7&quot;
</span><ins>+PASS stretchTestSheet.cssRules[14].style.fontStretch is &quot;100 / 200&quot;
+PASS stretchTestSheet.cssRules[15].style.fontStretch is &quot;100 / 200&quot;
+PASS stretchTestSheet.cssRules[16].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[17].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[18].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[19].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[20].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[21].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[22].style.fontStretch is &quot;1 / 2&quot;
+PASS stretchTestSheet.cssRules[23].style.fontStretch is &quot;-2 / -1&quot;
+PASS stretchTestSheet.cssRules[24].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[25].style.fontStretch is &quot;100% / 200%&quot;
+PASS stretchTestSheet.cssRules[26].style.fontStretch is &quot;100% / 200%&quot;
+PASS stretchTestSheet.cssRules[27].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[28].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[29].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[30].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[31].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[32].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[33].style.fontStretch is &quot;1% / 2%&quot;
+PASS stretchTestSheet.cssRules[34].style.fontStretch is &quot;-2% / -1%&quot;
+PASS stretchTestSheet.cssRules[35].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[36].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[37].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[38].style.fontStretch is &quot;7 / 8&quot;
+PASS stretchTestSheet.cssRules[39].style.fontStretch is &quot;2 / 7&quot;
</ins><span class="cx"> PASS styleTestSheet.cssRules[0].style.fontStyle is &quot;1deg&quot;
</span><span class="cx"> PASS styleTestSheet.cssRules[1].style.fontStyle is &quot;200grad&quot;
</span><span class="cx"> PASS styleTestSheet.cssRules[2].style.fontStyle is &quot;6.28318rad&quot;
</span><span class="lines">@@ -43,6 +82,33 @@
</span><span class="cx"> PASS styleTestSheet.cssRules[10].style.fontStyle is &quot;&quot;
</span><span class="cx"> PASS styleTestSheet.cssRules[11].style.fontStyle is &quot;7&quot;
</span><span class="cx"> PASS styleTestSheet.cssRules[12].style.fontStyle is &quot;calc(1441deg)&quot;
</span><ins>+PASS styleTestSheet.cssRules[13].style.fontStyle is &quot;100 / 200&quot;
+PASS styleTestSheet.cssRules[14].style.fontStyle is &quot;100 / 200&quot;
+PASS styleTestSheet.cssRules[15].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[16].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[17].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[18].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[19].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[20].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[21].style.fontStyle is &quot;1 / 2&quot;
+PASS styleTestSheet.cssRules[22].style.fontStyle is &quot;-2 / -1&quot;
+PASS styleTestSheet.cssRules[23].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[24].style.fontStyle is &quot;100deg / 200deg&quot;
+PASS styleTestSheet.cssRules[25].style.fontStyle is &quot;100deg / 200deg&quot;
+PASS styleTestSheet.cssRules[26].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[27].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[28].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[29].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[30].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[31].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[32].style.fontStyle is &quot;1deg / 2deg&quot;
+PASS styleTestSheet.cssRules[33].style.fontStyle is &quot;-2deg / -1deg&quot;
+PASS styleTestSheet.cssRules[34].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[35].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[36].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[37].style.fontStyle is &quot;2deg / 1turn&quot;
+PASS styleTestSheet.cssRules[38].style.fontStyle is &quot;7 / 8&quot;
+PASS styleTestSheet.cssRules[39].style.fontStyle is &quot;2 / 7&quot;
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextfontselectionfontfaceparsehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/font-selection-font-face-parse.html (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/font-selection-font-face-parse.html        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/LayoutTests/fast/text/font-selection-font-face-parse.html        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -56,6 +56,45 @@
</span><span class="cx"> @font-face {
</span><span class="cx">     font-weight: calc(150 + 50);
</span><span class="cx"> }
</span><ins>+@font-face {
+    font-weight: 100/200;
+}
+@font-face {
+    font-weight: 100 / 200;
+}
+@font-face {
+    font-weight: a 100 / 200;
+}
+@font-face {
+    font-weight: 100 / 200 a;
+}
+@font-face {
+    font-weight: 100 a / 200;
+}
+@font-face {
+    font-weight: 100 a/ 200;
+}
+@font-face {
+    font-weight: 100 /a 200;
+}
+@font-face {
+    font-weight: 100 / a200;
+}
+@font-face {
+    font-weight: 1 / 2;
+}
+@font-face {
+    font-weight: -2 / -1;
+}
+@font-face {
+    font-weight: 2 / 1;
+}
+@font-face {
+    font-weight: calc(3 + 4) / 8;
+}
+@font-face {
+    font-weight: 2 / calc(3 + 4);
+}
</ins><span class="cx"> &lt;/style&gt;
</span><span class="cx"> 
</span><span class="cx"> &lt;style id=&quot;stretchTest&quot;&gt;
</span><span class="lines">@@ -101,6 +140,84 @@
</span><span class="cx"> @font-face {
</span><span class="cx">     font-stretch: calc(3 + 4);
</span><span class="cx"> }
</span><ins>+@font-face {
+    font-stretch: 100/200;
+}
+@font-face {
+    font-stretch: 100 / 200;
+}
+@font-face {
+    font-stretch: a 100 / 200;
+}
+@font-face {
+    font-stretch: 100 / 200 a;
+}
+@font-face {
+    font-stretch: 100 a / 200;
+}
+@font-face {
+    font-stretch: 100 a/ 200;
+}
+@font-face {
+    font-stretch: 100 /a 200;
+}
+@font-face {
+    font-stretch: 100 / a200;
+}
+@font-face {
+    font-stretch: 1 / 2;
+}
+@font-face {
+    font-stretch: -2 / -1;
+}
+@font-face {
+    font-stretch: 2 / 1;
+}
+@font-face {
+    font-stretch: 100%/200%;
+}
+@font-face {
+    font-stretch: 100% / 200%;
+}
+@font-face {
+    font-stretch: a 100% / 200%;
+}
+@font-face {
+    font-stretch: 100% / 200% a;
+}
+@font-face {
+    font-stretch: 100% a / 200%;
+}
+@font-face {
+    font-stretch: 100% a/ 200%;
+}
+@font-face {
+    font-stretch: 100% /a 200%;
+}
+@font-face {
+    font-stretch: 100% / a200%;
+}
+@font-face {
+    font-stretch: 1% / 2%;
+}
+@font-face {
+    font-stretch: -2% / -1%;
+}
+@font-face {
+    font-stretch: 2% / 1%;
+}
+@font-face {
+    font-stretch: 1 / 2%;
+}
+@font-face {
+    font-stretch: 1% / 2;
+}
+@font-face {
+    font-stretch: calc(3 + 4) / 8;
+}
+@font-face {
+    font-stretch: 2 / calc(3 + 4);
+}
</ins><span class="cx"> &lt;/style&gt;
</span><span class="cx"> 
</span><span class="cx"> &lt;style id=&quot;styleTest&quot;&gt;
</span><span class="lines">@@ -143,6 +260,87 @@
</span><span class="cx"> @font-face {
</span><span class="cx">     font-style: oblique calc(4turn + 1deg);
</span><span class="cx"> }
</span><ins>+@font-face {
+    font-style: oblique 100/200;
+}
+@font-face {
+    font-style: oblique 100 / 200;
+}
+@font-face {
+    font-style: oblique a 100 / 200;
+}
+@font-face {
+    font-style: oblique 100 / 200 a;
+}
+@font-face {
+    font-style: oblique 100 a / 200;
+}
+@font-face {
+    font-style: oblique 100 a/ 200;
+}
+@font-face {
+    font-style: oblique 100 /a 200;
+}
+@font-face {
+    font-style: oblique 100 / a200;
+}
+@font-face {
+    font-style: oblique 1 / 2;
+}
+@font-face {
+    font-style: oblique -2 / -1;
+}
+@font-face {
+    font-style: oblique 2 / 1;
+}
+@font-face {
+    font-style: oblique 100deg/200deg;
+}
+@font-face {
+    font-style: oblique 100deg / 200deg;
+}
+@font-face {
+    font-style: oblique a 100deg / 200deg;
+}
+@font-face {
+    font-style: oblique 100deg / 200deg a;
+}
+@font-face {
+    font-style: oblique 100deg a / 200deg;
+}
+@font-face {
+    font-style: oblique 100deg a/ 200deg;
+}
+@font-face {
+    font-style: oblique 100deg /a 200deg;
+}
+@font-face {
+    font-style: oblique 100deg / a200deg;
+}
+@font-face {
+    font-style: oblique 1deg / 2deg;
+}
+@font-face {
+    font-style: oblique -2deg / -1deg;
+}
+@font-face {
+    font-style: oblique 2deg / 1deg;
+}
+@font-face {
+    font-style: oblique 1 / 2deg;
+}
+@font-face {
+    font-style: oblique 1deg / 2;
+}
+@font-face {
+    font-style: oblique 2deg / 1turn;
+}
+@font-face {
+    font-style: oblique calc(3 + 4) / 8;
+}
+@font-face {
+    font-style: oblique 2 / calc(3 + 4);
+}
</ins><span class="cx"> &lt;/style&gt;
</span><span class="cx"> &lt;/head&gt;
</span><span class="cx"> &lt;body&gt;
</span><span class="lines">@@ -166,6 +364,19 @@
</span><span class="cx"> shouldBeEqualToString(&quot;weightTestSheet.cssRules[15].style.fontWeight&quot;, &quot;7&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;weightTestSheet.cssRules[16].style.fontWeight&quot;, &quot;300&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;weightTestSheet.cssRules[17].style.fontWeight&quot;, &quot;200&quot;);
</span><ins>+shouldBeEqualToString(&quot;weightTestSheet.cssRules[18].style.fontWeight&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[19].style.fontWeight&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[20].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[21].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[22].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[23].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[24].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[25].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[26].style.fontWeight&quot;, &quot;1 / 2&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[27].style.fontWeight&quot;, &quot;-2 / -1&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[28].style.fontWeight&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[29].style.fontWeight&quot;, &quot;7 / 8&quot;);
+shouldBeEqualToString(&quot;weightTestSheet.cssRules[30].style.fontWeight&quot;, &quot;2 / 7&quot;);
</ins><span class="cx"> 
</span><span class="cx"> var stretchTestSheet = document.getElementById(&quot;stretchTest&quot;).sheet;
</span><span class="cx"> shouldBeEqualToString(&quot;stretchTestSheet.cssRules[0].style.fontStretch&quot;, &quot;1%&quot;);
</span><span class="lines">@@ -182,6 +393,32 @@
</span><span class="cx"> shouldBeEqualToString(&quot;stretchTestSheet.cssRules[11].style.fontStretch&quot;, &quot;&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;stretchTestSheet.cssRules[12].style.fontStretch&quot;, &quot;&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;stretchTestSheet.cssRules[13].style.fontStretch&quot;, &quot;7&quot;);
</span><ins>+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[14].style.fontStretch&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[15].style.fontStretch&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[16].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[17].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[18].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[19].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[20].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[21].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[22].style.fontStretch&quot;, &quot;1 / 2&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[23].style.fontStretch&quot;, &quot;-2 / -1&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[24].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[25].style.fontStretch&quot;, &quot;100% / 200%&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[26].style.fontStretch&quot;, &quot;100% / 200%&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[27].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[28].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[29].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[30].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[31].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[32].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[33].style.fontStretch&quot;, &quot;1% / 2%&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[34].style.fontStretch&quot;, &quot;-2% / -1%&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[35].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[36].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[37].style.fontStretch&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[38].style.fontStretch&quot;, &quot;7 / 8&quot;);
+shouldBeEqualToString(&quot;stretchTestSheet.cssRules[39].style.fontStretch&quot;, &quot;2 / 7&quot;);
</ins><span class="cx"> 
</span><span class="cx"> var styleTestSheet = document.getElementById(&quot;styleTest&quot;).sheet;
</span><span class="cx"> shouldBeEqualToString(&quot;styleTestSheet.cssRules[0].style.fontStyle&quot;, &quot;1deg&quot;);
</span><span class="lines">@@ -197,6 +434,34 @@
</span><span class="cx"> shouldBeEqualToString(&quot;styleTestSheet.cssRules[10].style.fontStyle&quot;, &quot;&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;styleTestSheet.cssRules[11].style.fontStyle&quot;, &quot;7&quot;);
</span><span class="cx"> shouldBeEqualToString(&quot;styleTestSheet.cssRules[12].style.fontStyle&quot;, &quot;calc(1441deg)&quot;);
</span><ins>+
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[13].style.fontStyle&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[14].style.fontStyle&quot;, &quot;100 / 200&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[15].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[16].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[17].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[18].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[19].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[20].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[21].style.fontStyle&quot;, &quot;1 / 2&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[22].style.fontStyle&quot;, &quot;-2 / -1&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[23].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[24].style.fontStyle&quot;, &quot;100deg / 200deg&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[25].style.fontStyle&quot;, &quot;100deg / 200deg&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[26].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[27].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[28].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[29].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[30].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[31].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[32].style.fontStyle&quot;, &quot;1deg / 2deg&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[33].style.fontStyle&quot;, &quot;-2deg / -1deg&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[34].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[35].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[36].style.fontStyle&quot;, &quot;&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[37].style.fontStyle&quot;, &quot;2deg / 1turn&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[38].style.fontStyle&quot;, &quot;7 / 8&quot;);
+shouldBeEqualToString(&quot;styleTestSheet.cssRules[39].style.fontStyle&quot;, &quot;2 / 7&quot;);
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacelcapitanfasttextfontselectionfontfaceparseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt (0 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -0,0 +1,115 @@
</span><ins>+PASS weightTestSheet.cssRules[0].style.fontWeight is &quot;1&quot;
+PASS weightTestSheet.cssRules[1].style.fontWeight is &quot;100&quot;
+PASS weightTestSheet.cssRules[2].style.fontWeight is &quot;200&quot;
+PASS weightTestSheet.cssRules[3].style.fontWeight is &quot;300&quot;
+PASS weightTestSheet.cssRules[4].style.fontWeight is &quot;400&quot;
+PASS weightTestSheet.cssRules[5].style.fontWeight is &quot;normal&quot;
+PASS weightTestSheet.cssRules[6].style.fontWeight is &quot;500&quot;
+PASS weightTestSheet.cssRules[7].style.fontWeight is &quot;600&quot;
+PASS weightTestSheet.cssRules[8].style.fontWeight is &quot;700&quot;
+PASS weightTestSheet.cssRules[9].style.fontWeight is &quot;bold&quot;
+PASS weightTestSheet.cssRules[10].style.fontWeight is &quot;800&quot;
+PASS weightTestSheet.cssRules[11].style.fontWeight is &quot;900&quot;
+PASS weightTestSheet.cssRules[12].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[13].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[14].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[15].style.fontWeight is &quot;7&quot;
+PASS weightTestSheet.cssRules[16].style.fontWeight is &quot;300&quot;
+PASS weightTestSheet.cssRules[17].style.fontWeight is &quot;200&quot;
+FAIL weightTestSheet.cssRules[18].style.fontWeight should be 100 / 200. Was .
+FAIL weightTestSheet.cssRules[19].style.fontWeight should be 100 / 200. Was .
+PASS weightTestSheet.cssRules[20].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[21].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[22].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[23].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[24].style.fontWeight is &quot;&quot;
+PASS weightTestSheet.cssRules[25].style.fontWeight is &quot;&quot;
+FAIL weightTestSheet.cssRules[26].style.fontWeight should be 1 / 2. Was .
+FAIL weightTestSheet.cssRules[27].style.fontWeight should be -2 / -1. Was .
+PASS weightTestSheet.cssRules[28].style.fontWeight is &quot;&quot;
+FAIL weightTestSheet.cssRules[29].style.fontWeight should be 7 / 8. Was .
+FAIL weightTestSheet.cssRules[30].style.fontWeight should be 2 / 7. Was .
+PASS stretchTestSheet.cssRules[0].style.fontStretch is &quot;1%&quot;
+PASS stretchTestSheet.cssRules[1].style.fontStretch is &quot;2&quot;
+PASS stretchTestSheet.cssRules[2].style.fontStretch is &quot;ultra-condensed&quot;
+PASS stretchTestSheet.cssRules[3].style.fontStretch is &quot;extra-condensed&quot;
+PASS stretchTestSheet.cssRules[4].style.fontStretch is &quot;condensed&quot;
+PASS stretchTestSheet.cssRules[5].style.fontStretch is &quot;semi-condensed&quot;
+PASS stretchTestSheet.cssRules[6].style.fontStretch is &quot;normal&quot;
+PASS stretchTestSheet.cssRules[7].style.fontStretch is &quot;semi-expanded&quot;
+PASS stretchTestSheet.cssRules[8].style.fontStretch is &quot;expanded&quot;
+PASS stretchTestSheet.cssRules[9].style.fontStretch is &quot;extra-expanded&quot;
+PASS stretchTestSheet.cssRules[10].style.fontStretch is &quot;ultra-expanded&quot;
+PASS stretchTestSheet.cssRules[11].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[12].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[13].style.fontStretch is &quot;7&quot;
+FAIL stretchTestSheet.cssRules[14].style.fontStretch should be 100 / 200. Was .
+FAIL stretchTestSheet.cssRules[15].style.fontStretch should be 100 / 200. Was .
+PASS stretchTestSheet.cssRules[16].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[17].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[18].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[19].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[20].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[21].style.fontStretch is &quot;&quot;
+FAIL stretchTestSheet.cssRules[22].style.fontStretch should be 1 / 2. Was .
+FAIL stretchTestSheet.cssRules[23].style.fontStretch should be -2 / -1. Was .
+PASS stretchTestSheet.cssRules[24].style.fontStretch is &quot;&quot;
+FAIL stretchTestSheet.cssRules[25].style.fontStretch should be 100% / 200%. Was .
+FAIL stretchTestSheet.cssRules[26].style.fontStretch should be 100% / 200%. Was .
+PASS stretchTestSheet.cssRules[27].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[28].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[29].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[30].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[31].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[32].style.fontStretch is &quot;&quot;
+FAIL stretchTestSheet.cssRules[33].style.fontStretch should be 1% / 2%. Was .
+FAIL stretchTestSheet.cssRules[34].style.fontStretch should be -2% / -1%. Was .
+PASS stretchTestSheet.cssRules[35].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[36].style.fontStretch is &quot;&quot;
+PASS stretchTestSheet.cssRules[37].style.fontStretch is &quot;&quot;
+FAIL stretchTestSheet.cssRules[38].style.fontStretch should be 7 / 8. Was .
+FAIL stretchTestSheet.cssRules[39].style.fontStretch should be 2 / 7. Was .
+PASS styleTestSheet.cssRules[0].style.fontStyle is &quot;1deg&quot;
+PASS styleTestSheet.cssRules[1].style.fontStyle is &quot;200grad&quot;
+PASS styleTestSheet.cssRules[2].style.fontStyle is &quot;6.28318rad&quot;
+PASS styleTestSheet.cssRules[3].style.fontStyle is &quot;4turn&quot;
+PASS styleTestSheet.cssRules[4].style.fontStyle is &quot;5&quot;
+PASS styleTestSheet.cssRules[5].style.fontStyle is &quot;20&quot;
+PASS styleTestSheet.cssRules[6].style.fontStyle is &quot;italic&quot;
+PASS styleTestSheet.cssRules[7].style.fontStyle is &quot;oblique&quot;
+PASS styleTestSheet.cssRules[8].style.fontStyle is &quot;normal&quot;
+PASS styleTestSheet.cssRules[9].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[10].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[11].style.fontStyle is &quot;7&quot;
+PASS styleTestSheet.cssRules[12].style.fontStyle is &quot;calc(1441deg)&quot;
+FAIL styleTestSheet.cssRules[13].style.fontStyle should be 100 / 200. Was .
+FAIL styleTestSheet.cssRules[14].style.fontStyle should be 100 / 200. Was .
+PASS styleTestSheet.cssRules[15].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[16].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[17].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[18].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[19].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[20].style.fontStyle is &quot;&quot;
+FAIL styleTestSheet.cssRules[21].style.fontStyle should be 1 / 2. Was .
+FAIL styleTestSheet.cssRules[22].style.fontStyle should be -2 / -1. Was .
+PASS styleTestSheet.cssRules[23].style.fontStyle is &quot;&quot;
+FAIL styleTestSheet.cssRules[24].style.fontStyle should be 100deg / 200deg. Was .
+FAIL styleTestSheet.cssRules[25].style.fontStyle should be 100deg / 200deg. Was .
+PASS styleTestSheet.cssRules[26].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[27].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[28].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[29].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[30].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[31].style.fontStyle is &quot;&quot;
+FAIL styleTestSheet.cssRules[32].style.fontStyle should be 1deg / 2deg. Was .
+FAIL styleTestSheet.cssRules[33].style.fontStyle should be -2deg / -1deg. Was .
+PASS styleTestSheet.cssRules[34].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[35].style.fontStyle is &quot;&quot;
+PASS styleTestSheet.cssRules[36].style.fontStyle is &quot;&quot;
+FAIL styleTestSheet.cssRules[37].style.fontStyle should be 2deg / 1turn. Was .
+FAIL styleTestSheet.cssRules[38].style.fontStyle should be 7 / 8. Was .
+FAIL styleTestSheet.cssRules[39].style.fontStyle should be 2 / 7. Was .
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins><span class="cx">Property changes on: trunk/LayoutTests/platform/mac-elcapitan/fast/text/font-selection-font-face-parse-expected.txt
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<ins>+Author Date Id Rev URL
</ins><span class="cx">\ No newline at end of property
</span><a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/Source/WebCore/ChangeLog        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2017-03-07  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Parsing font descriptors inside @font-face needs to accept ranges
+        https://bugs.webkit.org/show_bug.cgi?id=168893
+
+        Reviewed by Dean Jackson.
+
+        Parse font-weight, font-stretch, and font-style ranges according to
+        https://drafts.csswg.org/css-fonts-4/#font-prop-desc. There is one difference, though:
+        as documented in https://github.com/w3c/csswg-drafts/issues/783, slashes are a better
+        delimiters than hyphens, so this patch implements that instead. I'll update the spec to
+        include slashes as soon as possible.
+
+        Because this patch is all about creating FontSelectionValues from fonts, it doesn't
+        actually modify the font selection algorithm, and therefore only tests the creation of
+        these new values. The font selection algorithm itself is already tested elsewhere.
+
+        This new work is behind the ENABLE(VARIATION_FONTS) flag.
+
+        Test: fast/text/font-selection-font-face-parse.html
+
+        * css/CSSFontFace.cpp:
+        (WebCore::calculateWeightRange):
+        (WebCore::calculateStretchRange):
+        (WebCore::calculateItalicRange):
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::consumeFontWeightRange):
+        (WebCore::consumeFontStretchRange):
+        (WebCore::consumeFontStyleRange):
+        (WebCore::CSSPropertyParser::parseFontFaceDescriptor):
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::extractVariationBounds):
+        (WebCore::variationCapabilitiesForFontDescriptor):
+        (WebCore::capabilitiesForFontDescriptor):
+
</ins><span class="cx"> 2017-03-07  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Animated GIFs fail to play in multi-column layout
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFace.cpp (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFace.cpp        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/Source/WebCore/css/CSSFontFace.cpp        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -126,7 +126,20 @@
</span><span class="cx"> 
</span><span class="cx"> static FontSelectionRange calculateWeightRange(CSSValue&amp; value)
</span><span class="cx"> {
</span><del>-    // FIXME: Parse range-based values.
</del><ins>+    if (value.isValueList()) {
+        auto&amp; valueList = downcast&lt;CSSValueList&gt;(value);
+        ASSERT(valueList.length() == 2);
+        if (valueList.length() != 2)
+            return { normalWeightValue(), normalWeightValue() };
+        ASSERT(valueList.item(0)-&gt;isPrimitiveValue());
+        ASSERT(valueList.item(1)-&gt;isPrimitiveValue());
+        auto&amp; value0 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(0));
+        auto&amp; value1 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(1));
+        ASSERT(value0.isNumber());
+        ASSERT(value1.isNumber());
+        return { FontSelectionValue::clampFloat(value0.floatValue()), FontSelectionValue::clampFloat(value1.floatValue()) };
+    }
+
</ins><span class="cx">     ASSERT(is&lt;CSSPrimitiveValue&gt;(value));
</span><span class="cx">     auto&amp; primitiveValue = downcast&lt;CSSPrimitiveValue&gt;(value);
</span><span class="cx"> 
</span><span class="lines">@@ -162,7 +175,20 @@
</span><span class="cx"> 
</span><span class="cx"> static FontSelectionRange calculateStretchRange(CSSValue&amp; value)
</span><span class="cx"> {
</span><del>-    // FIXME: Parse range-based values.
</del><ins>+    if (value.isValueList()) {
+        auto&amp; valueList = downcast&lt;CSSValueList&gt;(value);
+        ASSERT(valueList.length() == 2);
+        if (valueList.length() != 2)
+            return { normalStretchValue(), normalStretchValue() };
+        ASSERT(valueList.item(0)-&gt;isPrimitiveValue());
+        ASSERT(valueList.item(1)-&gt;isPrimitiveValue());
+        auto&amp; value0 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(0));
+        auto&amp; value1 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(1));
+        ASSERT(value0.isPercentage() || value0.isNumber());
+        ASSERT(value1.isPercentage() || value1.isNumber());
+        return { FontSelectionValue::clampFloat(value0.floatValue()), FontSelectionValue::clampFloat(value1.floatValue()) };
+    }
+
</ins><span class="cx">     ASSERT(is&lt;CSSPrimitiveValue&gt;(value));
</span><span class="cx">     const auto&amp; primitiveValue = downcast&lt;CSSPrimitiveValue&gt;(value);
</span><span class="cx"> 
</span><span class="lines">@@ -198,7 +224,20 @@
</span><span class="cx"> 
</span><span class="cx"> static FontSelectionRange calculateItalicRange(CSSValue&amp; value)
</span><span class="cx"> {
</span><del>-    // FIXME: Parse range-based values.
</del><ins>+    if (value.isValueList()) {
+        auto&amp; valueList = downcast&lt;CSSValueList&gt;(value);
+        ASSERT(valueList.length() == 2);
+        if (valueList.length() != 2)
+            return { normalItalicValue(), normalItalicValue() };
+        ASSERT(valueList.item(0)-&gt;isPrimitiveValue());
+        ASSERT(valueList.item(1)-&gt;isPrimitiveValue());
+        auto&amp; value0 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(0));
+        auto&amp; value1 = downcast&lt;CSSPrimitiveValue&gt;(*valueList.item(1));
+        ASSERT(value0.isAngle() || value0.isNumber() || value0.isCalculated());
+        ASSERT(value1.isAngle() || value1.isNumber() || value1.isCalculated());
+        return { FontSelectionValue::clampFloat(value0.floatValue(CSSPrimitiveValue::CSS_DEG)), FontSelectionValue::clampFloat(value1.floatValue(CSSPrimitiveValue::CSS_DEG)) };
+    }
+
</ins><span class="cx">     ASSERT(is&lt;CSSPrimitiveValue&gt;(value));
</span><span class="cx">     const auto&amp; primitiveValue = downcast&lt;CSSPrimitiveValue&gt;(value);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSPropertyParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -888,6 +888,30 @@
</span><span class="cx">     return consumeNumber(range, ValueRangeAll);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(VARIATION_FONTS)
+static RefPtr&lt;CSSValue&gt; consumeFontWeightRange(CSSParserTokenRange&amp; range)
+{
+    if (auto result = consumeFontWeightKeywordValue(range))
+        return result;
+    auto firstNumber = consumeNumber(range, ValueRangeAll);
+    if (!firstNumber)
+        return nullptr;
+    if (range.atEnd())
+        return firstNumber;
+    if (!consumeSlashIncludingWhitespace(range))
+        return nullptr;
+    auto secondNumber = consumeNumber(range, ValueRangeAll);
+    if (!secondNumber)
+        return nullptr;
+    if (firstNumber-&gt;floatValue() &gt; secondNumber-&gt;floatValue())
+        return nullptr;
+    auto result = CSSValueList::createSlashSeparated();
+    result-&gt;append(firstNumber.releaseNonNull());
+    result-&gt;append(secondNumber.releaseNonNull());
+    return RefPtr&lt;CSSValue&gt;(WTFMove(result));
+}
+#endif
+
</ins><span class="cx"> static RefPtr&lt;CSSPrimitiveValue&gt; consumeFontStretchKeywordValue(CSSParserTokenRange&amp; range)
</span><span class="cx"> {
</span><span class="cx">     return consumeIdent&lt;CSSValueUltraCondensed, CSSValueExtraCondensed, CSSValueCondensed, CSSValueSemiCondensed, CSSValueNormal, CSSValueSemiExpanded, CSSValueExpanded, CSSValueExtraExpanded, CSSValueUltraExpanded&gt;(range);
</span><span class="lines">@@ -902,6 +926,47 @@
</span><span class="cx">     return consumeNumber(range, ValueRangeAll);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(VARIATION_FONTS)
+static RefPtr&lt;CSSValue&gt; consumeFontStretchRange(CSSParserTokenRange&amp; range)
+{
+    if (auto result = consumeFontStretchKeywordValue(range))
+        return result;
+    if (auto firstPercent = consumePercent(range, ValueRangeAll)) {
+        if (range.atEnd())
+            return firstPercent;
+        if (!consumeSlashIncludingWhitespace(range))
+            return nullptr;
+        auto secondPercent = consumePercent(range, ValueRangeAll);
+        if (!secondPercent)
+            return nullptr;
+        if (firstPercent-&gt;floatValue() &gt; secondPercent-&gt;floatValue())
+            return nullptr;
+        auto result = CSSValueList::createSlashSeparated();
+        result-&gt;append(firstPercent.releaseNonNull());
+        result-&gt;append(secondPercent.releaseNonNull());
+        return RefPtr&lt;CSSValue&gt;(WTFMove(result));
+    }
+
+    if (auto firstNumber = consumeNumber(range, ValueRangeAll)) {
+        if (range.atEnd())
+            return firstNumber;
+        if (!consumeSlashIncludingWhitespace(range))
+            return nullptr;
+        auto secondNumber = consumeNumber(range, ValueRangeAll);
+        if (!secondNumber)
+            return nullptr;
+        if (firstNumber-&gt;floatValue() &gt; secondNumber-&gt;floatValue())
+            return nullptr;
+        auto result = CSSValueList::createSlashSeparated();
+        result-&gt;append(firstNumber.releaseNonNull());
+        result-&gt;append(secondNumber.releaseNonNull());
+        return RefPtr&lt;CSSValue&gt;(WTFMove(result));
+    }
+
+    return nullptr;
+}
+#endif
+
</ins><span class="cx"> static RefPtr&lt;CSSPrimitiveValue&gt; consumeFontStyleKeywordValue(CSSParserTokenRange&amp; range)
</span><span class="cx"> {
</span><span class="cx">     return consumeIdent&lt;CSSValueNormal, CSSValueItalic, CSSValueOblique&gt;(range);
</span><span class="lines">@@ -924,6 +989,54 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(VARIATION_FONTS)
+static RefPtr&lt;CSSValue&gt; consumeFontStyleRange(CSSParserTokenRange&amp; range, CSSParserMode cssParserMode)
+{
+    if (auto result = consumeFontStyleKeywordValue(range)) {
+        if (result-&gt;valueID() == CSSValueOblique) {
+            if (range.atEnd())
+                return result;
+
+            if (auto firstAngle = consumeAngle(range, cssParserMode)) {
+                if (range.atEnd())
+                    return firstAngle;
+                if (!consumeSlashIncludingWhitespace(range))
+                    return nullptr;
+                auto secondAngle = consumeAngle(range, cssParserMode);
+                if (!secondAngle)
+                    return nullptr;
+                if (firstAngle-&gt;floatValue(CSSPrimitiveValue::CSS_DEG) &gt; secondAngle-&gt;floatValue(CSSPrimitiveValue::CSS_DEG))
+                    return nullptr;
+                auto result = CSSValueList::createSlashSeparated();
+                result-&gt;append(firstAngle.releaseNonNull());
+                result-&gt;append(secondAngle.releaseNonNull());
+                return RefPtr&lt;CSSValue&gt;(WTFMove(result));
+            }
+
+            if (auto firstNumber = consumeNumber(range, ValueRangeAll)) {
+                if (range.atEnd())
+                    return firstNumber;
+                if (!consumeSlashIncludingWhitespace(range))
+                    return nullptr;
+                auto secondNumber = consumeNumber(range, ValueRangeAll);
+                if (!secondNumber)
+                    return nullptr;
+                if (firstNumber-&gt;floatValue() &gt; secondNumber-&gt;floatValue())
+                    return nullptr;
+                auto result = CSSValueList::createSlashSeparated();
+                result-&gt;append(firstNumber.releaseNonNull());
+                result-&gt;append(secondNumber.releaseNonNull());
+                return RefPtr&lt;CSSValue&gt;(WTFMove(result));
+            }
+
+            return nullptr;
+        }
+        return result;
+    }
+    return nullptr;
+}
+#endif
+
</ins><span class="cx"> static String concatenateFamilyName(CSSParserTokenRange&amp; range)
</span><span class="cx"> {
</span><span class="cx">     StringBuilder builder;
</span><span class="lines">@@ -4220,16 +4333,25 @@
</span><span class="cx">         parsedValue = consumeFontFaceUnicodeRange(m_range);
</span><span class="cx">         break;
</span><span class="cx">     case CSSPropertyFontWeight:
</span><del>-        // FIXME: Parse range-based values.
</del><ins>+#if ENABLE(VARIATION_FONTS)
+        parsedValue = consumeFontWeightRange(m_range);
+#else
</ins><span class="cx">         parsedValue = consumeFontWeight(m_range);
</span><ins>+#endif
</ins><span class="cx">         break;
</span><span class="cx">     case CSSPropertyFontStretch:
</span><del>-        // FIXME: Parse range-based values.
</del><ins>+#if ENABLE(VARIATION_FONTS)
+        parsedValue = consumeFontStretchRange(m_range);
+#else
</ins><span class="cx">         parsedValue = consumeFontStretch(m_range);
</span><ins>+#endif
</ins><span class="cx">         break;
</span><span class="cx">     case CSSPropertyFontStyle:
</span><del>-        // FIXME: Parse range-based values.
</del><ins>+#if ENABLE(VARIATION_FONTS)
+        parsedValue = consumeFontStyleRange(m_range, m_context.mode);
+#else
</ins><span class="cx">         parsedValue = consumeFontStyle(m_range, m_context.mode);
</span><ins>+#endif
</ins><span class="cx">         break;
</span><span class="cx">     case CSSPropertyFontVariantCaps:
</span><span class="cx">         parsedValue = consumeFontVariantCaps(m_range);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp (213527 => 213528)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2017-03-07 19:21:02 UTC (rev 213527)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2017-03-07 19:26:21 UTC (rev 213528)
</span><span class="lines">@@ -828,50 +828,127 @@
</span><span class="cx">     HashMap&lt;String, InstalledFont&gt; m_postScriptNameToFontDescriptors;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct VariationCapabilities {
+    std::optional&lt;FontSelectionRange&gt; weight;
+    std::optional&lt;FontSelectionRange&gt; width;
+    std::optional&lt;FontSelectionRange&gt; slope;
+};
+
+#if ENABLE(VARIATION_FONTS)
+static std::optional&lt;FontSelectionRange&gt; extractVariationBounds(CFDictionaryRef axis)
+{
+    CFNumberRef minimumValue = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey));
+    CFNumberRef maximumValue = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey));
+    float rawMinimumValue = 0;
+    float rawMaximumValue = 0;
+    CFNumberGetValue(minimumValue, kCFNumberFloatType, &amp;rawMinimumValue);
+    CFNumberGetValue(maximumValue, kCFNumberFloatType, &amp;rawMaximumValue);
+    if (rawMinimumValue &lt; rawMaximumValue)
+        return {{ FontSelectionValue(rawMinimumValue), FontSelectionValue(rawMaximumValue) }};
+    return std::nullopt;
+}
+#endif
+
+static VariationCapabilities variationCapabilitiesForFontDescriptor(CTFontDescriptorRef fontDescriptor)
+{
+    VariationCapabilities result;
+
+#if ENABLE(VARIATION_FONTS)
+    if (!adoptCF(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontVariationAttribute)))
+        return result;
+
+    auto variations = adoptCF(CTFontCopyVariationAxes(adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor, 0, nullptr)).get()));
+    if (!variations)
+        return result;
+
+    auto axisCount = CFArrayGetCount(variations.get());
+    if (!axisCount)
+        return result;
+
+    for (CFIndex i = 0; i &lt; axisCount; ++i) {
+        CFDictionaryRef axis = static_cast&lt;CFDictionaryRef&gt;(CFArrayGetValueAtIndex(variations.get(), i));
+        CFNumberRef axisIdentifier = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey));
+        uint32_t rawAxisIdentifier = 0;
+        Boolean success = CFNumberGetValue(axisIdentifier, kCFNumberSInt32Type, &amp;rawAxisIdentifier);
+        ASSERT_UNUSED(success, success);
+        if (rawAxisIdentifier == 0x77676874) // 'wght'
+            result.weight = extractVariationBounds(axis);
+        else if (rawAxisIdentifier == 0x77647468) // 'wdth'
+            result.width = extractVariationBounds(axis);
+        else if (rawAxisIdentifier == 0x736C6E74) // 'slnt'
+            result.slope = extractVariationBounds(axis);
+    }
+#else
+    UNUSED_PARAM(fontDescriptor);
+#endif
+
+    return result;
+}
+
</ins><span class="cx"> FontSelectionCapabilities capabilitiesForFontDescriptor(CTFontDescriptorRef fontDescriptor)
</span><span class="cx"> {
</span><span class="cx">     if (!fontDescriptor)
</span><span class="cx">         return { };
</span><span class="cx"> 
</span><del>-    auto traits = adoptCF(static_cast&lt;CFDictionaryRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
-    FontSelectionValue width;
-    FontSelectionValue slant;
-    FontSelectionValue weight;
-    if (traits) {
-        width = stretchFromCoreTextTraits(traits.get());
</del><ins>+    VariationCapabilities variationCapabilities = variationCapabilitiesForFontDescriptor(fontDescriptor);
</ins><span class="cx"> 
</span><del>-        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 ? italicValue() : normalItalicValue();
-        }
</del><ins>+#if SHOULD_USE_CORE_TEXT_FONT_LOOKUP
+    bool weightComesFromTraits = !variationCapabilities.weight;
+#else
+    bool weightComesFromTraits = false;
+#endif
</ins><span class="cx"> 
</span><ins>+    if (!variationCapabilities.slope || !variationCapabilities.width || weightComesFromTraits) {
+        auto traits = adoptCF(static_cast&lt;CFDictionaryRef&gt;(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute)));
+        if (traits) {
+            if (!variationCapabilities.width) {
+                auto widthValue = stretchFromCoreTextTraits(traits.get());
+                variationCapabilities.width = {{ widthValue, widthValue }};
+            }
+
+            if (!variationCapabilities.slope) {
+                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);
+                    auto slopeValue = symbolicTraits &amp; kCTFontTraitItalic ? italicValue() : normalItalicValue();
+                    variationCapabilities.slope = {{ slopeValue, slopeValue }};
+                } else
+                    variationCapabilities.slope = {{ normalItalicValue(), normalItalicValue() }};
+            }
+
</ins><span class="cx"> #if SHOULD_USE_CORE_TEXT_FONT_LOOKUP
</span><del>-        auto weightNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontWeightTrait));
-        if (weightNumber) {
-            CGFloat ctWeight;
-            auto success = CFNumberGetValue(weightNumber, kCFNumberCGFloatType, &amp;ctWeight);
-            ASSERT_UNUSED(success, success);
-            weight = fontWeightFromCoreText(ctWeight);
</del><ins>+            if (!variationCapabilities.weight) {
+                auto weightNumber = static_cast&lt;CFNumberRef&gt;(CFDictionaryGetValue(traits.get(), kCTFontWeightTrait));
+                if (weightNumber) {
+                    CGFloat ctWeight;
+                    auto success = CFNumberGetValue(weightNumber, kCFNumberCGFloatType, &amp;ctWeight);
+                    ASSERT_UNUSED(success, success);
+                    auto weightValue = fontWeightFromCoreText(ctWeight);
+                    variationCapabilities.weight = {{ weightValue, weightValue }};
+                } else
+                    variationCapabilities.weight = {{ normalWeightValue(), normalWeightValue() }};
+            }
+#endif
</ins><span class="cx">         }
</span><del>-#endif
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
</span><del>-    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);
</del><ins>+    if (!variationCapabilities.weight) {
+        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);
+            auto weightValue = FontSelectionValue(cssWeight);
+            variationCapabilities.weight = {{ weightValue, weightValue }};
+        } else
+            variationCapabilities.weight = {{ normalWeightValue(), normalWeightValue() }};
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    // FIXME: Educate this function about font variations.
-
-    return { { weight, weight }, { width, width }, { slant, slant } };
</del><ins>+    return { variationCapabilities.weight.value(), variationCapabilities.width.value(), variationCapabilities.slope.value() };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if !SHOULD_USE_CORE_TEXT_FONT_LOOKUP
</span></span></pre>
</div>
</div>

</body>
</html>