<!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>[193587] branches/safari-601.1.46-branch</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/193587">193587</a></dd>
<dt>Author</dt> <dd>ddkilzer@apple.com</dd>
<dt>Date</dt> <dd>2015-12-06 13:32:41 -0800 (Sun, 06 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/190697">r190697</a>. rdar://problem/23769727</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601146branchLayoutTestsChangeLog">branches/safari-601.1.46-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601146branchLayoutTestscss3fontfeaturesettingsrendering2expectedhtml">branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html</a></li>
<li><a href="#branchessafari601146branchLayoutTestscss3fontfeaturesettingsrendering2html">branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2.html</a></li>
<li><a href="#branchessafari601146branchToolsChangeLog">branches/safari-601.1.46-branch/Tools/ChangeLog</a></li>
<li><a href="#branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp">branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp</a></li>
<li><a href="#branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesFontCreatorh">branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h</a></li>
<li><a href="#branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesmaincpp">branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp</a></li>
<li><a href="#branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj">branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari601146branchLayoutTestscss3resourcesFontWithFeaturesttf">branches/safari-601.1.46-branch/LayoutTests/css3/resources/FontWithFeatures.ttf</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601146branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/LayoutTests/ChangeLog (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/ChangeLog        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/LayoutTests/ChangeLog        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -1,5 +1,20 @@
</span><span class="cx"> 2015-12-06  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r190697. rdar://problem/23769727
+
+    2015-10-07  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+            Test font-variant-* and font-feature-settings with TrueType fonts
+            https://bugs.webkit.org/show_bug.cgi?id=149776
+
+            Reviewed by Simon Fraser.
+
+            * css3/font-feature-settings-rendering-2-expected.html:
+            * css3/font-feature-settings-rendering-2.html:
+            * css3/resources/FontWithFeatures.ttf: Added.
+
+2015-12-06  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r193575. rdar://problem/23769689
</span><span class="cx"> 
</span><span class="cx">     2015-09-23  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchLayoutTestscss3fontfeaturesettingsrendering2expectedhtml"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -6,6 +6,10 @@
</span><span class="cx">     font-family: &quot;FontFeaturesTest&quot;;
</span><span class="cx">     src: url(&quot;resources/FontWithFeatures.otf&quot;) format(&quot;opentype&quot;);
</span><span class="cx"> }
</span><ins>+@font-face {
+    font-family: &quot;FontFeaturesTestTTF&quot;;
+    src: url(&quot;resources/FontWithFeatures.ttf&quot;) format(&quot;truetype&quot;);
+}
</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">@@ -43,5 +47,39 @@
</span><span class="cx"> &lt;span style=&quot;font-family: FontFeaturesTest;&quot;&gt;BA&lt;/span&gt;
</span><span class="cx"> &lt;span style=&quot;font-family: FontFeaturesTest;&quot;&gt;BA&lt;/span&gt;
</span><span class="cx"> &lt;/div&gt;
</span><ins>+&lt;div&gt;&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;span style=&quot;font-family: FontFeaturesTestTTF;&quot;&gt;BA&lt;/span&gt;
+&lt;/div&gt;
</ins><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="branchessafari601146branchLayoutTestscss3fontfeaturesettingsrendering2html"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2.html (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2.html        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/LayoutTests/css3/font-feature-settings-rendering-2.html        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -6,56 +6,97 @@
</span><span class="cx">     font-family: &quot;FontFeaturesTest&quot;;
</span><span class="cx">     src: url(&quot;resources/FontWithFeatures.otf&quot;) format(&quot;opentype&quot;);
</span><span class="cx"> }
</span><ins>+@font-face {
+    font-family: &quot;FontFeaturesTestTTF&quot;;
+    src: url(&quot;resources/FontWithFeatures.ttf&quot;) format(&quot;truetype&quot;);
+}
</ins><span class="cx"> &lt;/style&gt;
</span><span class="cx"> &lt;/head&gt;
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> This tests that font features are able to be turned on and off as desired. It uses a special font
</span><span class="cx"> designed specifically for this purpose. The test passes if you see a sequence of alternating check
</span><span class="cx"> marks and X below.
</span><del>-&lt;div id=&quot;insertionpoint&quot;&gt;&lt;/div&gt;
</del><ins>+&lt;div id=&quot;insertionPoint&quot;&gt;&lt;/div&gt;
+&lt;div id=&quot;insertionPoint2&quot;&gt;&lt;/div&gt;
</ins><span class="cx"> &lt;script&gt;
</span><del>-var insertionpoint = document.getElementById(&quot;insertionpoint&quot;);
-function addElement(feature, c) {
</del><ins>+var insertionPoint = document.getElementById(&quot;insertionPoint&quot;);
+var insertionPoint2 = document.getElementById(&quot;insertionPoint2&quot;);
+function addElement(placeToInsert, familyName, feature, c) {
</ins><span class="cx">     [&quot;0&quot;, &quot;1&quot;].map(function(state) {
</span><span class="cx">         var element = document.createElement(&quot;span&quot;);
</span><span class="cx">         element.textContent = c;
</span><del>-        element.style.fontFamily = &quot;FontFeaturesTest&quot;;
</del><ins>+        element.style.fontFamily = familyName;
</ins><span class="cx">         element.style.fontFeatureSettings = '&quot;' + feature + '&quot; ' + state;
</span><del>-        insertionpoint.appendChild(element);
</del><ins>+        placeToInsert.appendChild(element);
</ins><span class="cx">     });
</span><del>-    insertionpoint.appendChild(document.createTextNode(&quot; &quot;));
</del><ins>+    placeToInsert.appendChild(document.createTextNode(&quot; &quot;));
</ins><span class="cx"> }
</span><del>-addElement(&quot;liga&quot;, &quot;C&quot;);
-addElement(&quot;clig&quot;, &quot;D&quot;);
-addElement(&quot;dlig&quot;, &quot;E&quot;);
-addElement(&quot;hlig&quot;, &quot;F&quot;);
-addElement(&quot;calt&quot;, &quot;G&quot;);
-addElement(&quot;subs&quot;, &quot;H&quot;);
-addElement(&quot;sups&quot;, &quot;I&quot;);
-addElement(&quot;smcp&quot;, &quot;J&quot;);
-addElement(&quot;c2sc&quot;, &quot;K&quot;);
-addElement(&quot;pcap&quot;, &quot;L&quot;);
-addElement(&quot;c2pc&quot;, &quot;M&quot;);
-addElement(&quot;unic&quot;, &quot;N&quot;);
-addElement(&quot;titl&quot;, &quot;O&quot;);
-addElement(&quot;lnum&quot;, &quot;P&quot;);
-addElement(&quot;onum&quot;, &quot;Q&quot;);
-addElement(&quot;pnum&quot;, &quot;R&quot;);
-addElement(&quot;tnum&quot;, &quot;S&quot;);
-addElement(&quot;frac&quot;, &quot;T&quot;);
-//addElement(&quot;afrc&quot;, &quot;U&quot;);
-addElement(&quot;ordn&quot;, &quot;V&quot;);
-addElement(&quot;zero&quot;, &quot;W&quot;);
-addElement(&quot;hist&quot;, &quot;X&quot;);
-addElement(&quot;jp78&quot;, &quot;Y&quot;);
-addElement(&quot;jp83&quot;, &quot;Z&quot;);
-addElement(&quot;jp90&quot;, &quot;a&quot;);
-addElement(&quot;jp04&quot;, &quot;b&quot;);
-addElement(&quot;smpl&quot;, &quot;c&quot;);
-addElement(&quot;trad&quot;, &quot;d&quot;);
-addElement(&quot;fwid&quot;, &quot;e&quot;);
-addElement(&quot;pwid&quot;, &quot;f&quot;);
-addElement(&quot;ruby&quot;, &quot;g&quot;);
</del><ins>+
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;liga&quot;, &quot;C&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;clig&quot;, &quot;D&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;dlig&quot;, &quot;E&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;hlig&quot;, &quot;F&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;calt&quot;, &quot;G&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;subs&quot;, &quot;H&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;sups&quot;, &quot;I&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;smcp&quot;, &quot;J&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;c2sc&quot;, &quot;K&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;pcap&quot;, &quot;L&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;c2pc&quot;, &quot;M&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;unic&quot;, &quot;N&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;titl&quot;, &quot;O&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;lnum&quot;, &quot;P&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;onum&quot;, &quot;Q&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;pnum&quot;, &quot;R&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;tnum&quot;, &quot;S&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;frac&quot;, &quot;T&quot;);
+//addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;afrc&quot;, &quot;U&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;ordn&quot;, &quot;V&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;zero&quot;, &quot;W&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;hist&quot;, &quot;X&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;jp78&quot;, &quot;Y&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;jp83&quot;, &quot;Z&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;jp90&quot;, &quot;a&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;jp04&quot;, &quot;b&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;smpl&quot;, &quot;c&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;trad&quot;, &quot;d&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;fwid&quot;, &quot;e&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;pwid&quot;, &quot;f&quot;);
+addElement(insertionPoint, &quot;FontFeaturesTest&quot;, &quot;ruby&quot;, &quot;g&quot;);
+
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;liga&quot;, &quot;C&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;liga&quot;, &quot;D&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;clig&quot;, &quot;C&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;clig&quot;, &quot;D&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;dlig&quot;, &quot;G&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;hlig&quot;, &quot;I&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;calt&quot;, &quot;L&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;subs&quot;, &quot;O&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;sups&quot;, &quot;P&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;smcp&quot;, &quot;S&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;c2sc&quot;, &quot;V&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;pcap&quot;, &quot;T&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;c2pc&quot;, &quot;W&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;unic&quot;, &quot;Y&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;titl&quot;, &quot;a&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;lnum&quot;, &quot;c&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;onum&quot;, &quot;d&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;pnum&quot;, &quot;f&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;tnum&quot;, &quot;g&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;frac&quot;, &quot;i&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;afrc&quot;, &quot;j&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;ordn&quot;, &quot;Q&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;zero&quot;, &quot;k&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;hist&quot;, &quot;K&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;jp78&quot;, &quot;m&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;jp83&quot;, &quot;n&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;jp90&quot;, &quot;o&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;jp04&quot;, &quot;p&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;smpl&quot;, &quot;q&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;trad&quot;, &quot;r&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;fwid&quot;, &quot;t&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;pwid&quot;, &quot;u&quot;);
+addElement(insertionPoint2, &quot;FontFeaturesTestTTF&quot;, &quot;ruby&quot;, &quot;v&quot;);
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="branchessafari601146branchLayoutTestscss3resourcesFontWithFeaturesttf"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/css3/resources/FontWithFeatures.ttf (0 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/css3/resources/FontWithFeatures.ttf                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/css3/resources/FontWithFeatures.ttf        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+true \x80@OS/2H\xE0Yb\xCCdcmap\xD5\xAF0jfeat\xA7Rp\x9Clglyf\xC8(\xD5\xC3headeD\xF9 6hheag7X$hmtx\xD4 \x86|\xD4loca\xAB9P\xD8maxpk( morx\xC9BH @name\x9FW!\x88+\x8Epost/ \xF4TKBW\xFF\xFFf\xFF\xFC\xFF\xFF \xFF\xFFD
+ (AZaz&amp;Zz\xFF\xFFAa\xFF\xFF\xFF\xDA\xFF\xA0        \xB4$\xD8
+
+\xE0\x80+%\xF0\x80&amp;\xFC\x80\x80\x80\x80$\x80# 0\x80'&lt;,@\x80/\\x807h;        .  c+ccccc !&quot;c$%&amp;c()*-c0123 456c89:&lt;\xC8\xC8  \xC8X\xFD\xA8\xC8X\xFD\xA8\xC8\xC8\xB6\xBC\xC82\xFA\x902\xFE&gt;\xFE\xD4\xF42\xFF\x90\xFF\xCE\xFE&gt;,22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\
 xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\x
 CE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xF
 Ep\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xF
 Ep\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xF
 F\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE
 \x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90
 \xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp
 2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90\x902\xFEp22\xB6\xB6 \xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&amp;\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x
 90\x902\xFEpZ2M_&lt;\xF5f5\xC8\xC8222222222222222222222222222222222222222222222222222'X\xA7\xF6E\x94\xE32\x81\xD0n\xBD [\xAA\xF9H\x97\xE65\x84\xD3&quot;q\xC0^\xAD\xFC        K        \x9A        \xE9
+8
+\x87
+\xD6 % t \xC3  a \xB0 \xFF+N+\x9D+\xEC;\x8A\xD9(w\xC65\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF5.D\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFF        D\xFF\xFF\xFF\xFF
+D\xFF\xFF\xFF\xFF D$\xFF\xFF\xFF\xFF D$\xFF\xFF\xFF\xFF+D
+c\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD%c\xFF\xFF\xFF\xFFD%\xFF\xFF\xFF\xFFD%\xFF\xFF\xFF\xFFD&amp;c\xFF\xFF\xFF\xFFD&amp;\xFF\xFF\xFF\xFFD&amp;\xFF\xFF\xFF\xFFDc\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFDc\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFDc\xFF\xFF\xFF\xFFD\xFF\xFF\xF
 F\xFFD\xFF\xFF\xFF\xFFDc\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFF D\xFF\xFF\xFF\xFF!D c\xFF\xFF\xFF\xFF&quot;D \xFF\xFF\xFF\xFF#D \xFF\xFF\xFF\xFF$D\xFF\xFF\xFF\xFF%Dc\xFF\xFF\xFF\xFF&amp;D\xFF\xFF\xFF\xFF'D\xFF\xFF\xFF\xFF(D\xFF\xFF\xFF\xFF
 )D \xFF\xFF\xFF\xFF*D\xFF\xFF\xFF\xFF+D\xFF\xFF\xFF\xFF,Dc\xFF\xFF\xFF\xFF-D\xFF\xFF\xFF\xFF.D\xFF\xFF\xFF\xFF/D\xFF\xFF\xFF\xFF0=\xE2        .b\x9E\xD4Bt        \xB0.\xEE
+* \  \x9A+\xDA.R+v\x98\xB4\xDELh\x92\xC8HLn\x98\xC0 \xDE!&quot;:#l$\x90%\xBA&amp;\xF2'&amp;(B)l*\xA0,\xD4-/,0R1|2\xB03\xE44        5        L6        \x867        \xC28        \xE29
+ :
+:;
+l&lt;
+\x86MylesFontkLigaturesTypekCommonLigaturesOnSelectorkContextualLigaturesOnSelectorkCommonLigaturesOffSelectorkContextualLigaturesOffSelectorkRareLigaturesOnSelectorkRareLigaturesOffSelectorkHistoricalLigaturesOnSelectorkHistoricalLigaturesOffSelectorkHistoricalLigaturesOnSelectorkContextualAlternatesTypekContextualAlternatesOnSelectorkContextualAlternatesOffSelectorkVerticalPositionTypedefaultUnusedSelectorkInferiorsSelectorkSuperiorsSelectorkOrdinalsSelectorkLowerCaseTypedefaultUnusedSelec
 torkLowerCaseSmallCapsSelectorkLowerCasePetiteCapsSelectorkUpperCaseTypedefaultUnusedSelectorkUpperCaseSmallCapsSelectorkUpperCasePetiteCapsSelectorkLetterCaseTypedefaultUnusedSelector14kStyleOptionsTypedefaultUnusedSelectorkTitlingCapsSelectorkNumberCaseTypedefaultUnusedSelectorkUpperCaseNumbersSelectorkLowerCaseNumbersSelectorkNumberSpacingTypedefaultUnusedSelectorkProportionalNumbersSelectorkMonospacedNumbersSelectorkFractionsTypedefaultUnusedSelectorkDiagonalFractionsSelectorkVerticalFr
 actionsSelectorkTypographicExtrasTypekSlashedZeroOnSelectorkCharacterShapeTypedefaultUnusedSelectorkJIS1978CharactersSelectorkJIS1983CharactersSelectorkJIS1990CharactersSelectorkJIS2004CharactersSelectorkSimplifiedCharactersSelectorkTraditionalCharactersSelectorkTextSpacingTypedefaultUnusedSelectorkMonospacedTextSelectorkProportionalTextSelectorkRubyKanaTypekRubyKanaOnSelector
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="branchessafari601146branchToolsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Tools/ChangeLog (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Tools/ChangeLog        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/Tools/ChangeLog        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -1,5 +1,104 @@
</span><span class="cx"> 2015-12-06  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r190697. rdar://problem/23769727
+
+    2015-10-07  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+            Test font-variant-* and font-feature-settings with TrueType fonts
+            https://bugs.webkit.org/show_bug.cgi?id=149776
+
+            Reviewed by Simon Fraser.
+
+            This test extends our existing FontWithFeatures project to be able to generate a
+            TrueType font. This font is conceptually similar as the existing OpenType font,
+            except the feature -&gt; character mapping is different.
+
+            The font itself only supports the following characters:
+            ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+            However, the shape of these letters are either an X or a check mark.
+            The letter &quot;A&quot; always is a check mark.
+            The letter &quot;B&quot; always is an X.
+            Each font feature has an letter associated with it. When the font feature is enabled,
+            that letter is shown as a check mark. For example, when
+            &quot;kLowerCaseType / kLowerCaseSmallCapsSelector&quot; is enabled, &quot;S&quot; is shown as a check
+            mark.
+
+            Here are the mappings of font features to letters:
+            kLigaturesType / kCommonLigaturesOnSelector: C
+            kLigaturesType / kContextualLigaturesOnSelector: D
+            kLigaturesType / kRareLigaturesOnSelector: G
+            kLigaturesType / kHistoricalLigaturesOnSelector: I
+            kContextualAlternatesType / kContextualAlternatesOnSelector: L
+            kVerticalPositionType / kInferiorsSelector: O
+            kVerticalPositionType / kSuperiorsSelector: P
+            kLowerCaseType / kLowerCaseSmallCapsSelector: S
+            kUpperCaseType / kUpperCaseSmallCapsSelector: V
+            kLowerCaseType / kLowerCasePetiteCapsSelector: T
+            kUpperCaseType / kUpperCasePetiteCapsSelector: W
+            kLetterCaseType / 14: Y
+            kStyleOptionsType / kTitlingCapsSelector: a
+            kNumberCaseType / kUpperCaseNumbersSelector: c
+            kNumberCaseType / kLowerCaseNumbersSelector: d
+            kNumberSpacingType / kProportionalNumbersSelector: f
+            kNumberSpacingType / kMonospacedNumbersSelector: g
+            kFractionsType / kDiagonalFractionsSelector: i
+            kFractionsType / kVerticalFractionsSelector: j
+            kVerticalPositionType / kOrdinalsSelector: Q
+            kTypographicExtrasType / kSlashedZeroOnSelector: k
+            kLigaturesType / kHistoricalLigaturesOnSelector: K
+            kCharacterShapeType / kJIS1978CharactersSelector: m
+            kCharacterShapeType / kJIS1983CharactersSelector: n
+            kCharacterShapeType / kJIS1990CharactersSelector: o
+            kCharacterShapeType / kJIS2004CharactersSelector: p
+            kCharacterShapeType / kSimplifiedCharactersSelector: q
+            kCharacterShapeType / kTraditionalCharactersSelector: r
+            kTextSpacingType / kMonospacedTextSelector: t
+            kTextSpacingType / kProportionalTextSelector: u
+            kRubyKanaType / kRubyKanaOnSelector: v
+
+            * FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj:
+            * FontWithFeatures/FontWithFeatures/FontCreator.cpp:
+            (CFFBuilder::moveTo):
+            (CFFBuilder::lineTo):
+            (GLYFBuilder::GLYFBuilder):
+            (GLYFBuilder::takeResult):
+            (GLYFBuilder::moveTo):
+            (GLYFBuilder::lineTo):
+            (GLYFBuilder::closePath):
+            (GLYFBuilder::writePoint):
+            (GLYFBuilder::append16):
+            (generateBoxCharString):
+            (generateCheckCharString):
+            (generateXCharString):
+            (itemForGlyph):
+            (Generator::generate):
+            (Generator::insertSelector):
+            (Generator::insertFeature):
+            (Generator::generateFeatureDescription):
+            (Generator::appendCFFTable):
+            (Generator::appendGLYFTable):
+            (Generator::appendLOCATable):
+            (Generator::appendFEATTable):
+            (Generator::appendMetamorphosisChain):
+            (Generator::appendMORXTable):
+            (Generator::appendHEADTable):
+            (Generator::appendHMTXTable):
+            (Generator::appendNameSubtable):
+            (Generator::append2ByteASCIIString):
+            (Generator::appendNAMETable):
+            (generateFont):
+            (CFFBuilder::curveToCubic): Deleted.
+            (charStringForGlyph): Deleted.
+            * FontWithFeatures/FontWithFeatures/FontCreator.h:
+            * FontWithFeatures/FontWithFeatures/main.cpp:
+            (constructFontWithTrueTypeFeature):
+            (constructFontWithOpenTypeFeature):
+            (drawText):
+            (main):
+            (drawTextWithFeature): Deleted.
+
+2015-12-06  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r193575. rdar://problem/23769689
</span><span class="cx"> 
</span><span class="cx">     2015-09-23  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -82,7 +82,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static const char rLineTo = 0x05;
</span><del>-static const char rrCurveTo = 0x08;
</del><span class="cx"> static const char endChar = 0x0e;
</span><span class="cx"> static const char rMoveTo = 0x15;
</span><span class="cx"> 
</span><span class="lines">@@ -102,14 +101,9 @@
</span><span class="cx">         return std::move(result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void moveTo(std::pair&lt;float, float&gt; targetPoint, bool closed)
</del><ins>+    void moveTo(std::pair&lt;float, float&gt; targetPoint)
</ins><span class="cx">     {
</span><del>-        if (closed &amp;&amp; !result.empty())
-            closePath();
-
-        std::pair&lt;float, float&gt; destination = targetPoint;
-
-        writePoint(destination);
</del><ins>+        writePoint(targetPoint);
</ins><span class="cx">         result.push_back(rMoveTo);
</span><span class="cx"> 
</span><span class="cx">         startingPoint = current;
</span><span class="lines">@@ -117,24 +111,10 @@
</span><span class="cx"> 
</span><span class="cx">     void lineTo(std::pair&lt;float, float&gt; targetPoint)
</span><span class="cx">     {
</span><del>-        std::pair&lt;float, float&gt; destination = targetPoint;
-
-        writePoint(destination);
</del><ins>+        writePoint(targetPoint);
</ins><span class="cx">         result.push_back(rLineTo);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void curveToCubic(std::pair&lt;float, float&gt; point1, std::pair&lt;float, float&gt; point2, std::pair&lt;float, float&gt; targetPoint)
-    {
-        std::pair&lt;float, float&gt; destination1 = point1;
-        std::pair&lt;float, float&gt; destination2 = point2;
-        std::pair&lt;float, float&gt; destination3 = targetPoint;
-
-        writePoint(destination1);
-        writePoint(destination2);
-        writePoint(destination3);
-        result.push_back(rrCurveTo);
-    }
-
</del><span class="cx">     void closePath()
</span><span class="cx">     {
</span><span class="cx">         if (current != startingPoint)
</span><span class="lines">@@ -156,10 +136,94 @@
</span><span class="cx">     std::pair&lt;float, float&gt; current;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class GLYFBuilder {
+public:
+    GLYFBuilder(float, std::pair&lt;float, float&gt;)
+    {
+    }
+
+    std::vector&lt;uint8_t&gt; takeResult()
+    {
+        std::vector&lt;uint8_t&gt; result;
+        append16(result, endPtsOfContours.size());
+        append16(result, clampTo&lt;int16_t&gt;(minX));
+        append16(result, clampTo&lt;int16_t&gt;(minY));
+        append16(result, clampTo&lt;int16_t&gt;(maxX));
+        append16(result, clampTo&lt;int16_t&gt;(maxY));
+
+        for (uint16_t p : endPtsOfContours)
+            append16(result, p);
+        append16(result, 0);
+        for (uint8_t f : flags)
+            result.push_back(f);
+        for (uint16_t c : xCoordinates)
+            append16(result, c);
+        for (uint16_t c : yCoordinates)
+            append16(result, c);
+
+        return result;
+    }
+
+    void moveTo(std::pair&lt;float, float&gt; targetPoint)
+    {
+        writePoint(targetPoint, true);
+
+        startingPoint = current;
+    }
+
+    void lineTo(std::pair&lt;float, float&gt; targetPoint)
+    {
+        writePoint(targetPoint, true);
+    }
+
+    void closePath()
+    {
+        if (current != startingPoint)
+            lineTo(startingPoint);
+        endPtsOfContours.push_back(pointCount - 1);
+    }
+
+private:
+    void writePoint(std::pair&lt;float, float&gt; destination, bool onCurve)
+    {
+        flags.push_back(onCurve ? 1 : 0); // Flags
+
+        std::pair&lt;float, float&gt; delta = std::make_pair(destination.first - current.first, destination.second - current.second);
+        xCoordinates.push_back(delta.first);
+        yCoordinates.push_back(delta.second);
+
+        current = destination;
+        minX = std::min(minX, destination.first);
+        maxX = std::max(maxX, destination.first);
+        minY = std::min(minY, destination.second);
+        maxY = std::max(maxY, destination.second);
+        ++pointCount;
+    }
+
+    static void append16(std::vector&lt;uint8_t&gt;&amp; destination, uint16_t value)
+    {
+        destination.push_back(value &gt;&gt; 8);
+        destination.push_back(value);
+    }
+
+    std::vector&lt;uint16_t&gt; endPtsOfContours;
+    std::vector&lt;uint8_t&gt; flags;
+    std::vector&lt;int16_t&gt; xCoordinates;
+    std::vector&lt;int16_t&gt; yCoordinates;
+    std::pair&lt;float, float&gt; startingPoint;
+    std::pair&lt;float, float&gt; current;
+    float minX { std::numeric_limits&lt;float&gt;::max() };
+    float maxX { std::numeric_limits&lt;float&gt;::min() };
+    float minY { std::numeric_limits&lt;float&gt;::max() };
+    float maxY { std::numeric_limits&lt;float&gt;::min() };
+    unsigned pointCount { 0 };
+};
+
+template &lt;typename T&gt;
</ins><span class="cx"> std::vector&lt;uint8_t&gt; generateBoxCharString()
</span><span class="cx"> {
</span><del>-    CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
-    builder.moveTo(std::make_pair(200.f, 200.f), false);
</del><ins>+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(200.f, 200.f));
</ins><span class="cx">     builder.lineTo(std::make_pair(200.f, 800.f));
</span><span class="cx">     builder.lineTo(std::make_pair(800.f, 800.f));
</span><span class="cx">     builder.lineTo(std::make_pair(800.f, 200.f));
</span><span class="lines">@@ -167,10 +231,11 @@
</span><span class="cx">     return builder.takeResult();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template &lt;typename T&gt;
</ins><span class="cx"> std::vector&lt;uint8_t&gt; generateCheckCharString()
</span><span class="cx"> {
</span><del>-    CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
-    builder.moveTo(std::make_pair(200.f, 500.f), false);
</del><ins>+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(200.f, 500.f));
</ins><span class="cx">     builder.lineTo(std::make_pair(250.f, 550.f));
</span><span class="cx">     builder.lineTo(std::make_pair(500.f, 300.f));
</span><span class="cx">     builder.lineTo(std::make_pair(900.f, 700.f));
</span><span class="lines">@@ -180,10 +245,11 @@
</span><span class="cx">     return builder.takeResult();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template &lt;typename T&gt;
</ins><span class="cx"> std::vector&lt;uint8_t&gt; generateXCharString()
</span><span class="cx"> {
</span><del>-    CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
-    builder.moveTo(std::make_pair(500.0f, 550.0f), false);
</del><ins>+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(500.0f, 550.0f));
</ins><span class="cx">     builder.lineTo(std::make_pair(900.f, 950.f));
</span><span class="cx">     builder.lineTo(std::make_pair(950.f, 900.f));
</span><span class="cx">     builder.lineTo(std::make_pair(550.f, 500.f));
</span><span class="lines">@@ -199,7 +265,8 @@
</span><span class="cx">     return builder.takeResult();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::vector&lt;uint8_t&gt;&amp; charStringForGlyph(uint16_t glyph, std::vector&lt;uint8_t&gt;&amp; boxCharString, std::vector&lt;uint8_t&gt;&amp; checkCharString, std::vector&lt;uint8_t&gt;&amp; xCharString)
</del><ins>+template&lt;typename T&gt;
+const T&amp; itemForGlyph(uint16_t glyph, const T&amp; boxCharString, const T&amp; checkCharString, const T&amp; xCharString)
</ins><span class="cx"> {
</span><span class="cx">     if (!glyph)
</span><span class="cx">         return boxCharString;
</span><span class="lines">@@ -208,18 +275,43 @@
</span><span class="cx">     return xCharString;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+struct FeatureSelector {
+    uint16_t selector;
+    std::string name;
+    uint16_t stringIndex;
+    bool defaultSelector;
+};
+
+struct FeatureType {
+    uint16_t type;
+    std::string name;
+    uint16_t stringIndex;
+    size_t settingTableOffsetLocation;
+    std::vector&lt;FeatureSelector&gt; selectors;
+    bool exclusive;
+};
+
</ins><span class="cx"> class Generator {
</span><span class="cx"> public:
</span><del>-    std::vector&lt;uint8_t&gt; generate()
</del><ins>+    std::vector&lt;uint8_t&gt; generate(Type type)
</ins><span class="cx">     {
</span><del>-        uint16_t numTables = 10;
</del><ins>+        featureDescription = generateFeatureDescription();
+
+        uint16_t numTables = type == Type::OpenType ? 10 : 12;
</ins><span class="cx">         uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables);
</span><span class="cx">         uint16_t searchRange = roundedNumTables * 16; // searchRange: &quot;(Maximum power of 2 &lt;= numTables) x 16.&quot;
</span><span class="cx"> 
</span><del>-        result.push_back('O');
-        result.push_back('T');
-        result.push_back('T');
-        result.push_back('O');
</del><ins>+        if (type == Type::OpenType) {
+            result.push_back('O');
+            result.push_back('T');
+            result.push_back('T');
+            result.push_back('O');
+        } else {
+            result.push_back('t');
+            result.push_back('r');
+            result.push_back('u');
+            result.push_back('e');
+        }
</ins><span class="cx">         append16(numTables);
</span><span class="cx">         append16(searchRange);
</span><span class="cx">         append16(integralLog2(roundedNumTables)); // entrySelector: &quot;Log2(maximum power of 2 &lt;= numTables).&quot;
</span><span class="lines">@@ -231,15 +323,25 @@
</span><span class="cx">         for (size_t i = 0; i &lt; directoryEntrySize * numTables; ++i)
</span><span class="cx">             result.push_back(0);
</span><span class="cx"> 
</span><del>-        appendTable(&quot;CFF &quot;, &amp;Generator::appendCFFTable);
-        appendTable(&quot;GSUB&quot;, &amp;Generator::appendGSUBTable);
</del><ins>+        if (type == Type::OpenType) {
+            appendTable(&quot;CFF &quot;, &amp;Generator::appendCFFTable);
+            appendTable(&quot;GSUB&quot;, &amp;Generator::appendGSUBTable);
+        }
</ins><span class="cx">         appendTable(&quot;OS/2&quot;, &amp;Generator::appendOS2Table);
</span><span class="cx">         appendTable(&quot;cmap&quot;, &amp;Generator::appendCMAPTable);
</span><ins>+        if (type == Type::TrueType) {
+            appendTable(&quot;feat&quot;, &amp;Generator::appendFEATTable);
+            appendTable(&quot;glyf&quot;, &amp;Generator::appendGLYFTable);
+        }
</ins><span class="cx">         auto headTableOffset = result.size();
</span><span class="cx">         appendTable(&quot;head&quot;, &amp;Generator::appendHEADTable);
</span><span class="cx">         appendTable(&quot;hhea&quot;, &amp;Generator::appendHHEATable);
</span><span class="cx">         appendTable(&quot;hmtx&quot;, &amp;Generator::appendHMTXTable);
</span><ins>+        if (type == Type::TrueType)
+            appendTable(&quot;loca&quot;, &amp;Generator::appendLOCATable);
</ins><span class="cx">         appendTable(&quot;maxp&quot;, &amp;Generator::appendMAXPTable);
</span><ins>+        if (type == Type::TrueType)
+            appendTable(&quot;morx&quot;, &amp;Generator::appendMORXTable);
</ins><span class="cx">         appendTable(&quot;name&quot;, &amp;Generator::appendNAMETable);
</span><span class="cx">         appendTable(&quot;post&quot;, &amp;Generator::appendPOSTTable);
</span><span class="cx"> 
</span><span class="lines">@@ -248,6 +350,7 @@
</span><span class="cx">         // checksumAdjustment: &quot;To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory,
</span><span class="cx">         // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK.&quot;
</span><span class="cx">         overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, result.size()));
</span><ins>+
</ins><span class="cx">         return std::move(result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -331,6 +434,132 @@
</span><span class="cx">         result[location + 2] = value &gt;&gt; 8;
</span><span class="cx">         result[location + 3] = value;
</span><span class="cx">     }
</span><ins>+
+    void insertSelector(std::vector&lt;FeatureSelector&gt;&amp; selectors, uint16_t selector, std::string selectorString, bool defaultSelector)
+    {
+        selectors.push_back({selector, selectorString, m_stringIndex++, defaultSelector});
+    }
+
+    void insertFeature(std::vector&lt;FeatureType&gt;&amp; result, uint16_t type, std::string typeString, uint16_t selector, std::string selectorString, bool exclusive)
+    {
+        // O(n) but performance is not an issue here
+        for (size_t i = 0; i &lt; result.size(); ++i) {
+            if (result[i].type == type) {
+                insertSelector(result[i].selectors, selector, selectorString, false);
+                return;
+            }
+        }
+        result.push_back({type, typeString, m_stringIndex++, 0, std::vector&lt;FeatureSelector&gt;(), exclusive});
+        insertSelector(result[result.size() - 1].selectors, selector, selectorString, true);
+    }
+
+    static const uint16_t kCharacterShapeType = 20;
+    static const uint16_t kContextualAlternatesType = 36;
+    static const uint16_t kFractionsType = 11;
+    static const uint16_t kLetterCaseType = 3;
+    static const uint16_t kLigaturesType = 1;
+    static const uint16_t kLowerCaseType = 37;
+    static const uint16_t kNumberCaseType = 21;
+    static const uint16_t kNumberSpacingType = 6;
+    static const uint16_t kRubyKanaType = 28;
+    static const uint16_t kStyleOptionsType = 19;
+    static const uint16_t kTextSpacingType = 22;
+    static const uint16_t kTypographicExtrasType = 14;
+    static const uint16_t kUpperCaseType = 38;
+    static const uint16_t kVerticalPositionType = 10;
+
+    static const uint16_t kCommonLigaturesOffSelector = 3;
+    static const uint16_t kCommonLigaturesOnSelector = 2;
+    static const uint16_t kContextualAlternatesOffSelector = 1;
+    static const uint16_t kContextualAlternatesOnSelector = 0;
+    static const uint16_t kContextualLigaturesOffSelector = 19;
+    static const uint16_t kContextualLigaturesOnSelector = 18;
+    static const uint16_t kDiagonalFractionsSelector = 2;
+    static const uint16_t kHistoricalLigaturesOffSelector = 21;
+    static const uint16_t kHistoricalLigaturesOnSelector = 20;
+    static const uint16_t kInferiorsSelector = 2;
+    static const uint16_t kJIS1978CharactersSelector = 2;
+    static const uint16_t kJIS1983CharactersSelector = 3;
+    static const uint16_t kJIS1990CharactersSelector = 4;
+    static const uint16_t kJIS2004CharactersSelector = 11;
+    static const uint16_t kLowerCaseNumbersSelector = 0;
+    static const uint16_t kLowerCasePetiteCapsSelector = 2;
+    static const uint16_t kLowerCaseSmallCapsSelector = 1;
+    static const uint16_t kMonospacedNumbersSelector = 0;
+    static const uint16_t kMonospacedTextSelector = 1;
+    static const uint16_t kOrdinalsSelector = 3;
+    static const uint16_t kProportionalNumbersSelector = 1;
+    static const uint16_t kProportionalTextSelector = 0;
+    static const uint16_t kRareLigaturesOffSelector = 5;
+    static const uint16_t kRareLigaturesOnSelector = 4;
+    static const uint16_t kRubyKanaOnSelector = 2;
+    static const uint16_t kRubyKanaSelector = 1;
+    static const uint16_t kSimplifiedCharactersSelector = 1;
+    static const uint16_t kSlashedZeroOnSelector = 4;
+    static const uint16_t kSuperiorsSelector = 1;
+    static const uint16_t kTitlingCapsSelector = 4;
+    static const uint16_t kTraditionalCharactersSelector = 0;
+    static const uint16_t kUpperCaseNumbersSelector = 1;
+    static const uint16_t kUpperCasePetiteCapsSelector = 2;
+    static const uint16_t kUpperCaseSmallCapsSelector = 1;
+    static const uint16_t kVerticalFractionsSelector = 1;
+
+    static const uint16_t defaultUnusedSelector = 99;
+
+    std::vector&lt;FeatureType&gt; generateFeatureDescription()
+    {
+        std::vector&lt;FeatureType&gt; result;
+
+        // For any given feature type, the first selector inside it is the default selector for that type.
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kCommonLigaturesOnSelector, &quot;kCommonLigaturesOnSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kContextualLigaturesOnSelector, &quot;kContextualLigaturesOnSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kCommonLigaturesOffSelector, &quot;kCommonLigaturesOffSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kContextualLigaturesOffSelector, &quot;kContextualLigaturesOffSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kRareLigaturesOnSelector, &quot;kRareLigaturesOnSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kRareLigaturesOffSelector, &quot;kRareLigaturesOffSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kHistoricalLigaturesOnSelector, &quot;kHistoricalLigaturesOnSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kHistoricalLigaturesOffSelector, &quot;kHistoricalLigaturesOffSelector&quot;, false);
+        insertFeature(result, kContextualAlternatesType, &quot;kContextualAlternatesType&quot;, kContextualAlternatesOnSelector, &quot;kContextualAlternatesOnSelector&quot;, false);
+        insertFeature(result, kContextualAlternatesType, &quot;kContextualAlternatesType&quot;, kContextualAlternatesOffSelector, &quot;kContextualAlternatesOffSelector&quot;, false);
+        insertFeature(result, kVerticalPositionType, &quot;kVerticalPositionType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kVerticalPositionType, &quot;kVerticalPositionType&quot;, kInferiorsSelector, &quot;kInferiorsSelector&quot;, true);
+        insertFeature(result, kVerticalPositionType, &quot;kVerticalPositionType&quot;, kSuperiorsSelector, &quot;kSuperiorsSelector&quot;, true);
+        insertFeature(result, kLowerCaseType, &quot;kLowerCaseType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kUpperCaseType, &quot;kUpperCaseType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kLowerCaseType, &quot;kLowerCaseType&quot;, kLowerCaseSmallCapsSelector, &quot;kLowerCaseSmallCapsSelector&quot;, true);
+        insertFeature(result, kUpperCaseType, &quot;kUpperCaseType&quot;, kUpperCaseSmallCapsSelector, &quot;kUpperCaseSmallCapsSelector&quot;, true);
+        insertFeature(result, kLowerCaseType, &quot;kLowerCaseType&quot;, kLowerCasePetiteCapsSelector, &quot;kLowerCasePetiteCapsSelector&quot;, true);
+        insertFeature(result, kUpperCaseType, &quot;kUpperCaseType&quot;, kUpperCasePetiteCapsSelector, &quot;kUpperCasePetiteCapsSelector&quot;, true);
+        insertFeature(result, kLetterCaseType, &quot;kLetterCaseType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kLetterCaseType, &quot;kLetterCaseType&quot;, 14, &quot;14&quot;, true);
+        insertFeature(result, kStyleOptionsType, &quot;kStyleOptionsType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kStyleOptionsType, &quot;kStyleOptionsType&quot;, kTitlingCapsSelector, &quot;kTitlingCapsSelector&quot;, true);
+        insertFeature(result, kNumberCaseType, &quot;kNumberCaseType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kNumberCaseType, &quot;kNumberCaseType&quot;, kUpperCaseNumbersSelector, &quot;kUpperCaseNumbersSelector&quot;, true);
+        insertFeature(result, kNumberCaseType, &quot;kNumberCaseType&quot;, kLowerCaseNumbersSelector, &quot;kLowerCaseNumbersSelector&quot;, true);
+        insertFeature(result, kNumberSpacingType, &quot;kNumberSpacingType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kNumberSpacingType, &quot;kNumberSpacingType&quot;, kProportionalNumbersSelector, &quot;kProportionalNumbersSelector&quot;, true);
+        insertFeature(result, kNumberSpacingType, &quot;kNumberSpacingType&quot;, kMonospacedNumbersSelector, &quot;kMonospacedNumbersSelector&quot;, true);
+        insertFeature(result, kFractionsType, &quot;kFractionsType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kFractionsType, &quot;kFractionsType&quot;, kDiagonalFractionsSelector, &quot;kDiagonalFractionsSelector&quot;, true);
+        insertFeature(result, kFractionsType, &quot;kFractionsType&quot;, kVerticalFractionsSelector, &quot;kVerticalFractionsSelector&quot;, true);
+        insertFeature(result, kVerticalPositionType, &quot;kVerticalPositionType&quot;, kOrdinalsSelector, &quot;kOrdinalsSelector&quot;, true);
+        insertFeature(result, kTypographicExtrasType, &quot;kTypographicExtrasType&quot;, kSlashedZeroOnSelector, &quot;kSlashedZeroOnSelector&quot;, false);
+        insertFeature(result, kLigaturesType, &quot;kLigaturesType&quot;, kHistoricalLigaturesOnSelector, &quot;kHistoricalLigaturesOnSelector&quot;, false);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kJIS1978CharactersSelector, &quot;kJIS1978CharactersSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kJIS1983CharactersSelector, &quot;kJIS1983CharactersSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kJIS1990CharactersSelector, &quot;kJIS1990CharactersSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kJIS2004CharactersSelector, &quot;kJIS2004CharactersSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kSimplifiedCharactersSelector, &quot;kSimplifiedCharactersSelector&quot;, true);
+        insertFeature(result, kCharacterShapeType, &quot;kCharacterShapeType&quot;, kTraditionalCharactersSelector, &quot;kTraditionalCharactersSelector&quot;, true);
+        insertFeature(result, kTextSpacingType, &quot;kTextSpacingType&quot;, defaultUnusedSelector, &quot;defaultUnusedSelector&quot;, true);
+        insertFeature(result, kTextSpacingType, &quot;kTextSpacingType&quot;, kMonospacedTextSelector, &quot;kMonospacedTextSelector&quot;, true);
+        insertFeature(result, kTextSpacingType, &quot;kTextSpacingType&quot;, kProportionalTextSelector, &quot;kProportionalTextSelector&quot;, true);
+        insertFeature(result, kRubyKanaType, &quot;kRubyKanaType&quot;, kRubyKanaOnSelector, &quot;kRubyKanaOnSelector&quot;, false);
+
+        return result;
+    }
</ins><span class="cx">     
</span><span class="cx">     void appendCFFTable()
</span><span class="cx">     {
</span><span class="lines">@@ -418,9 +647,9 @@
</span><span class="cx">             append16(i);
</span><span class="cx"> 
</span><span class="cx">         // CharStrings INDEX
</span><del>-        std::vector&lt;uint8_t&gt; boxCharString = generateBoxCharString();
-        std::vector&lt;uint8_t&gt; checkCharString = generateCheckCharString();
-        std::vector&lt;uint8_t&gt; xCharString = generateXCharString();
</del><ins>+        std::vector&lt;uint8_t&gt; boxCharString = generateBoxCharString&lt;CFFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; checkCharString = generateCheckCharString&lt;CFFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; xCharString = generateXCharString&lt;CFFBuilder&gt;();
</ins><span class="cx">         assert(numGlyphs &gt; 26);
</span><span class="cx">         overwrite32(charstringsOffsetLocation, static_cast&lt;uint32_t&gt;(result.size() - startingOffset));
</span><span class="cx">         append16(numGlyphs);
</span><span class="lines">@@ -428,15 +657,134 @@
</span><span class="cx">         offset = 1;
</span><span class="cx">         append32(offset);
</span><span class="cx">         for (uint16_t glyph = 0; glyph &lt; numGlyphs; ++glyph) {
</span><del>-            offset += charStringForGlyph(glyph, boxCharString, checkCharString, xCharString).size();
</del><ins>+            offset += itemForGlyph(glyph, boxCharString, checkCharString, xCharString).size();
</ins><span class="cx">             append32(offset);
</span><span class="cx">         }
</span><span class="cx">         for (uint16_t glyph = 0; glyph &lt; numGlyphs; ++glyph) {
</span><del>-            std::vector&lt;uint8_t&gt;&amp; charString = charStringForGlyph(glyph, boxCharString, checkCharString, xCharString);
</del><ins>+            const std::vector&lt;uint8_t&gt;&amp; charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString);
</ins><span class="cx">             result.insert(result.end(), charString.begin(), charString.end());
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Keep in sync with loca
+    void appendGLYFTable()
+    {
+        std::vector&lt;uint8_t&gt; boxCharString = generateBoxCharString&lt;GLYFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; checkCharString = generateCheckCharString&lt;GLYFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; xCharString = generateXCharString&lt;GLYFBuilder&gt;();
+        for (uint16_t glyph = 0; glyph &lt; numGlyphs; ++glyph) {
+            const std::vector&lt;uint8_t&gt;&amp; charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString);
+            result.insert(result.end(), charString.begin(), charString.end());
+        }
+    }
+
+    // Keep in sync with glyf
+    void appendLOCATable()
+    {
+        std::vector&lt;uint8_t&gt; boxCharString = generateBoxCharString&lt;GLYFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; checkCharString = generateCheckCharString&lt;GLYFBuilder&gt;();
+        std::vector&lt;uint8_t&gt; xCharString = generateXCharString&lt;GLYFBuilder&gt;();
+        uint32_t index = 0;
+        for (uint16_t glyph = 0; glyph &lt; numGlyphs; ++glyph) {
+            append32(index);
+            index += itemForGlyph(glyph, boxCharString, checkCharString, xCharString).size();
+        }
+        append32(index);
+    }
+
+    void appendFEATTable()
+    {
+        size_t tableLocation = result.size();
+        append32(0x00010000); // Version
+        append16(featureDescription.size()); // Number of entries in the feature name array
+        append16(0); // reserved
+        append32(0); // reserved
+
+        // Feature name array
+        for (FeatureType&amp; type : featureDescription) {
+            append16(type.type); // Feature type
+            append16(type.selectors.size()); // Number of settings
+            type.settingTableOffsetLocation = result.size();
+            append32(0); // Offset in bytes from beginning of this table to feature's setting name array
+            append16(type.exclusive ? 0x8000 : 0); // Flags. 0x8000 = Exclusive
+            append16(type.stringIndex + m_baseStringIndex); // Index in the name table for the name of this feature
+        }
+
+        // Setting name array
+        for (FeatureType&amp; type : featureDescription) {
+            overwrite32(type.settingTableOffsetLocation, static_cast&lt;uint32_t&gt;(result.size() - tableLocation));
+            for (FeatureSelector&amp; selector : type.selectors) {
+                append16(selector.selector); // Setting: kNormalPositionSelector (initial setting is default)
+                append16(selector.stringIndex + m_baseStringIndex); // Index in the name table for the name of this setting
+            }
+        }
+    }
+
+    void appendMetamorphosisChain(const FeatureType&amp; type, const FeatureSelector&amp; selector, uint16_t glyphToReplace, uint16_t withMe)
+    {
+        size_t chainLocation = result.size();
+        append32(type.exclusive &amp;&amp; selector.defaultSelector ? 1 : 0); // Default flags
+        size_t chainSizeLocation = result.size();
+        append32(0); // Placeholder for chain length in bytes (padded to multiple of 4)
+        append32(2); // Number of feature subtable entries
+        append32(1); // Number of subtables in the chain
+
+        // Feature table
+        append16(type.type); // Feature type
+        append16(selector.selector); // Feature selector
+        append32(1); // Enable flags
+        append32(0xFFFFFFFF); // disable flags
+
+        // Feature table 2
+        append16(0); // Feature type: kAllTypographicFeaturesType
+        append16(1); // Feature selector: kAllTypeFeaturesOffSelector
+        append32(0); // Enable flags
+        append32(0); // disable flags
+
+        // Metamorphosis subtable
+        size_t metamorphosisSubtableSizeLocation = result.size();
+        append32(0); // Placeholder for chain length in bytes (padded to multiple of 4)
+        append32(4); // Coverage flags and subtable type. Subtable type 4: Noncontextual (&quot;swash&quot;) subtable
+        append32(1); // subFeature flags
+
+        // Non-contextual glyph substitution subtable
+        append16(6); // Lookup format: sorted list of (glyph index, lookup value) pairs
+        
+        // BinSrchHeader
+        append16(4); // Size of a lookup unit for this search in bytes
+        append16(1); // Number of units to be searched
+        append16(4); // Search range: The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits.
+        append16(0); // Entry selector: The log base 2 of the largest power of 2 less than or equal to the value of nUnits.
+        append16(0); // Range shift: The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits.
+        // Entries
+        append16(glyphToReplace);
+        append16(withMe);
+
+        overwrite32(metamorphosisSubtableSizeLocation, static_cast&lt;uint32_t&gt;(result.size() - metamorphosisSubtableSizeLocation));
+
+        while (result.size() % 4)
+            result.push_back(0);
+        overwrite32(chainSizeLocation, static_cast&lt;uint32_t&gt;(result.size() - chainLocation));
+    }
+
+    void appendMORXTable()
+    {
+        append16(2); // Version
+        append16(0); // Unused
+        size_t numberOfChainsLocation = result.size();
+        append32(0); // Number of metamorphosis chains placeholder
+
+        int count = 0;
+        for (FeatureType&amp; type : featureDescription) {
+            for (FeatureSelector&amp; selector : type.selectors) {
+                appendMetamorphosisChain(type, selector, count + 3, 1);
+                count++;
+            }
+        }
+    
+        overwrite32(numberOfChainsLocation, count);
+    }
+
</ins><span class="cx">     void appendSubstitutionSubtable(size_t subtableRecordLocation, uint16_t iGetReplaced, uint16_t replacedWithMe)
</span><span class="cx">     {
</span><span class="cx">         overwrite16(subtableRecordLocation + 6, result.size() - subtableRecordLocation);
</span><span class="lines">@@ -677,7 +1025,7 @@
</span><span class="cx">         append16(0); // Traits
</span><span class="cx">         append16(3); // Smallest readable size in pixels
</span><span class="cx">         append16(0); // Might contain LTR or RTL glyphs
</span><del>-        append16(0); // Short offsets in the 'loca' table. However, OTF fonts don't have a 'loca' table so this is irrelevant
</del><ins>+        append16(1); // Long offsets in the 'loca' table.
</ins><span class="cx">         append16(0); // Glyph data format
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -705,8 +1053,8 @@
</span><span class="cx">     void appendHMTXTable()
</span><span class="cx">     {
</span><span class="cx">         for (unsigned i = 0; i &lt; numGlyphs; ++i) {
</span><del>-            append16(clampTo&lt;uint16_t&gt;(unitsPerEm)); // horizontal advance
-            append16(clampTo&lt;int16_t&gt;(0)); // left side bearing
</del><ins>+            append16(clampTo&lt;uint16_t&gt;(static_cast&lt;int32_t&gt;(unitsPerEm))); // horizontal advance
+            append16(itemForGlyph(i, 200, 200, 50)); // left side bearing
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -728,25 +1076,47 @@
</span><span class="cx">         append16(numGlyphs); // Maximum number of glyphs referenced at top level
</span><span class="cx">         append16(0); // No compound glyphs
</span><span class="cx">     }
</span><del>-    
-    void appendNAMETable()
</del><ins>+
+    void appendNameSubtable(const std::string&amp; s, uint16_t nameIdentifier)
</ins><span class="cx">     {
</span><del>-        std::string fontName = &quot;MylesFont&quot;;
-
-        append16(0); // Format selector
-        append16(1); // Number of name records in table
-        append16(18); // Offset in bytes to the beginning of name character strings
-
</del><span class="cx">         append16(0); // Unicode
</span><span class="cx">         append16(3); // Unicode version 2.0 or later
</span><span class="cx">         append16(0); // Language
</span><del>-        append16(1); // Name identifier. 1 = Font family
-        append16(fontName.length());
-        append16(0); // Offset into name data
</del><ins>+        append16(m_baseStringIndex + nameIdentifier); // Name identifier
+        append16(s.length());
+        append16(m_nameOffset); // Offset into name data
+        m_nameOffset += s.size() * 2; // Code units get 2 bytes each
+    }
</ins><span class="cx"> 
</span><del>-        for (auto codeUnit : fontName)
</del><ins>+    void append2ByteASCIIString(std::string&amp; s)
+    {
+        for (auto codeUnit : s)
</ins><span class="cx">             append16(codeUnit);
</span><span class="cx">     }
</span><ins>+
+    void appendNAMETable()
+    {
+        std::string familyName = &quot;MylesFont&quot;; // 1: Font Family
+
+        uint16_t numberOfRecords = m_stringIndex + 1;
+        append16(0); // Format selector
+        append16(numberOfRecords); // Number of name records in table
+        append16(6 + 12 * numberOfRecords); // Offset in bytes to the beginning of name character strings
+
+        appendNameSubtable(familyName, 1); // 1: Font Family
+        for (FeatureType&amp; type : featureDescription) {
+            appendNameSubtable(type.name, type.stringIndex);
+            for (FeatureSelector&amp; selector : type.selectors)
+                appendNameSubtable(selector.name, selector.stringIndex);
+        }
+
+        append2ByteASCIIString(familyName);
+        for (FeatureType&amp; type : featureDescription) {
+            append2ByteASCIIString(type.name);
+            for (FeatureSelector&amp; selector : type.selectors)
+                append2ByteASCIIString(selector.name);
+        }
+    }
</ins><span class="cx">     
</span><span class="cx">     void appendPOSTTable()
</span><span class="cx">     {
</span><span class="lines">@@ -796,10 +1166,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned m_tablesAppendedCount { 0 };
</span><ins>+    unsigned m_nameOffset { 0 };
+    static constexpr uint16_t m_baseStringIndex { 257 };
+    uint16_t m_stringIndex { 0 };
+    std::vector&lt;FeatureType&gt; featureDescription;
</ins><span class="cx">     std::vector&lt;uint8_t&gt; result;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-std::vector&lt;uint8_t&gt; generateFont()
</del><ins>+std::vector&lt;uint8_t&gt; generateFont(Type type)
</ins><span class="cx"> {
</span><del>-    return Generator().generate();
</del><ins>+    return Generator().generate(type);
</ins><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesFontCreatorh"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -28,6 +28,11 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;vector&gt;
</span><span class="cx"> 
</span><del>-std::vector&lt;uint8_t&gt; generateFont();
</del><ins>+enum class Type {
+    OpenType,
+    TrueType
+};
</ins><span class="cx"> 
</span><ins>+std::vector&lt;uint8_t&gt; generateFont(Type);
+
</ins><span class="cx"> #endif /* FontCreator_h */
</span></span></pre></div>
<a id="branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesmaincpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -32,12 +32,32 @@
</span><span class="cx"> #include &lt;ImageIO/ImageIO.h&gt;
</span><span class="cx"> #include &lt;fstream&gt;
</span><span class="cx"> 
</span><del>-void drawTextWithFeature(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value, CGPoint location)
</del><ins>+static CTFontDescriptorRef constructFontWithTrueTypeFeature(CTFontDescriptorRef fontDescriptor, int type, int selector)
</ins><span class="cx"> {
</span><del>-    CGFloat fontSize = 25;
-    CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
-    CGContextSetTextPosition(context, location.x, location.y);
</del><ins>+    CFNumberRef typeValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &amp;type);
+    CFNumberRef selectorValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &amp;selector);
+    CFTypeRef featureDictionaryKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey };
+    CFTypeRef featureDictionaryValues[] = { typeValue, selectorValue };
+    CFDictionaryRef featureDictionary = CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, 2, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks);
+    CFRelease(typeValue);
+    CFRelease(selectorValue);
</ins><span class="cx"> 
</span><ins>+    CFTypeRef featureSettingsValues[] = { featureDictionary };
+    CFArrayRef fontFeatureSettings = CFArrayCreate(kCFAllocatorDefault, featureSettingsValues, 1, &amp;kCFTypeArrayCallBacks);
+    CFRelease(featureDictionary);
+
+    CFTypeRef fontDescriptorKeys[] = { kCTFontFeatureSettingsAttribute };
+    CFTypeRef fontDescriptorValues[] = { fontFeatureSettings };
+    CFDictionaryRef fontDescriptorAttributes = CFDictionaryCreate(kCFAllocatorDefault, fontDescriptorKeys, fontDescriptorValues, 1, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks);
+    CFRelease(fontFeatureSettings);
+
+    CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes);
+    CFRelease(fontDescriptorAttributes);
+    return modifiedFontDescriptor;
+}
+
+static CTFontDescriptorRef constructFontWithOpenTypeFeature(CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value)
+{
</ins><span class="cx">     CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &amp;value);
</span><span class="cx">     CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
</span><span class="cx">     CFTypeRef featureDictionaryValues[] = { feature, featureValue };
</span><span class="lines">@@ -55,14 +75,20 @@
</span><span class="cx"> 
</span><span class="cx">     CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes);
</span><span class="cx">     CFRelease(fontDescriptorAttributes);
</span><ins>+    return modifiedFontDescriptor;
+}
</ins><span class="cx"> 
</span><del>-    CTFontRef font = CTFontCreateWithFontDescriptor(modifiedFontDescriptor, fontSize, nullptr);
-    CFRelease(modifiedFontDescriptor);
</del><ins>+static void drawText(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef prefix, CGPoint location)
+{
+    CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
+    CGContextSetTextPosition(context, location.x, location.y);
</ins><span class="cx"> 
</span><ins>+    CGFloat fontSize = 25;
+    CTFontRef font = CTFontCreateWithFontDescriptor(fontDescriptor, fontSize, nullptr);
+
</ins><span class="cx">     CFMutableStringRef string = CFStringCreateMutable(kCFAllocatorDefault, 0);
</span><del>-    CFStringAppend(string, feature);
-    CFStringAppend(string, value ? CFSTR(&quot;  (on)&quot;) : CFSTR(&quot; (off)&quot;));
-    CFStringAppend(string, CFSTR(&quot;: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;));
</del><ins>+    CFStringAppend(string, prefix);
+    CFStringAppend(string, CFSTR(&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;));
</ins><span class="cx"> 
</span><span class="cx">     CGColorRef red = CGColorCreateGenericRGB(1, 0, 0, 1);
</span><span class="cx">     CFTypeRef lineKeys[] = { kCTForegroundColorAttributeName };
</span><span class="lines">@@ -72,16 +98,16 @@
</span><span class="cx"> 
</span><span class="cx">     CFAttributedStringRef attributedString = CFAttributedStringCreate(kCFAllocatorDefault, string, lineAttributes);
</span><span class="cx">     CFRelease(lineAttributes);
</span><del>-    CFRelease(string);
</del><span class="cx"> 
</span><span class="cx">     CFMutableAttributedStringRef mutableAttributedString = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, attributedString);
</span><span class="cx">     CFRelease(attributedString);
</span><span class="cx"> 
</span><span class="cx">     CTFontRef monospaceFont = CTFontCreateWithName(CFSTR(&quot;Courier&quot;), fontSize, nullptr);
</span><del>-    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, 12), kCTFontAttributeName, monospaceFont);
</del><ins>+    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, CFStringGetLength(prefix)), kCTFontAttributeName, monospaceFont);
</ins><span class="cx">     CFRelease(monospaceFont);
</span><span class="cx"> 
</span><del>-    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(12, 52), kCTFontAttributeName, font);
</del><ins>+    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(CFStringGetLength(prefix), CFStringGetLength(string) - CFStringGetLength(prefix)), kCTFontAttributeName, font);
+    CFRelease(string);
</ins><span class="cx">     CFRelease(font);
</span><span class="cx"> 
</span><span class="cx">     CTLineRef line = CTLineCreateWithAttributedString(mutableAttributedString);
</span><span class="lines">@@ -93,13 +119,14 @@
</span><span class="cx"> 
</span><span class="cx"> int main(int argc, const char * argv[])
</span><span class="cx"> {
</span><del>-    size_t width = 2000;
</del><ins>+    size_t width = 2500;
</ins><span class="cx">     size_t height = 2000;
</span><span class="cx">     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
</span><span class="cx">     CGContextRef context = CGBitmapContextCreate(nullptr, width, height, 8, width * 4, colorSpace, kCGImageAlphaNoneSkipLast);
</span><span class="cx">     CGColorSpaceRelease(colorSpace);
</span><del>-    const std::vector&lt;uint8_t&gt; fontVector = generateFont();
-    std::ofstream outputFile(&quot;/Volumes/Data/home/mmaxfield/tmp/output.otf&quot;, std::ios::out | std::ios::binary);
</del><ins>+    Type type = Type::TrueType;
+    const std::vector&lt;uint8_t&gt; fontVector = generateFont(type);
+    std::ofstream outputFile(&quot;/Volumes/Data/home/mmaxfield/tmp/output.ttf&quot;, std::ios::out | std::ios::binary);
</ins><span class="cx">     for (uint8_t b : fontVector)
</span><span class="cx">         outputFile &lt;&lt; b;
</span><span class="cx">     outputFile.close();
</span><span class="lines">@@ -108,15 +135,85 @@
</span><span class="cx">     CTFontDescriptorRef fontDescriptor = CTFontManagerCreateFontDescriptorFromData(fontData);
</span><span class="cx">     CFRelease(fontData);
</span><span class="cx"> 
</span><del>-    CFTypeRef featureValues[] = { CFSTR(&quot;liga&quot;), CFSTR(&quot;clig&quot;), CFSTR(&quot;dlig&quot;), CFSTR(&quot;hlig&quot;), CFSTR(&quot;calt&quot;), CFSTR(&quot;subs&quot;), CFSTR(&quot;sups&quot;), CFSTR(&quot;smcp&quot;), CFSTR(&quot;c2sc&quot;), CFSTR(&quot;pcap&quot;), CFSTR(&quot;c2pc&quot;), CFSTR(&quot;unic&quot;), CFSTR(&quot;titl&quot;), CFSTR(&quot;onum&quot;), CFSTR(&quot;pnum&quot;), CFSTR(&quot;tnum&quot;), CFSTR(&quot;frac&quot;), CFSTR(&quot;afrc&quot;), CFSTR(&quot;ordn&quot;), CFSTR(&quot;zero&quot;), CFSTR(&quot;hist&quot;), CFSTR(&quot;jp78&quot;), CFSTR(&quot;jp83&quot;), CFSTR(&quot;jp90&quot;), CFSTR(&quot;jp04&quot;), CFSTR(&quot;smpl&quot;), CFSTR(&quot;trad&quot;), CFSTR(&quot;fwid&quot;), CFSTR(&quot;pwid&quot;), CFSTR(&quot;ruby&quot;) };
-    CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValues, 30, &amp;kCFTypeArrayCallBacks);
</del><ins>+    if (type == Type::OpenType) {
+        CFTypeRef featureValuesOpenType[] = { CFSTR(&quot;liga&quot;), CFSTR(&quot;clig&quot;), CFSTR(&quot;dlig&quot;), CFSTR(&quot;hlig&quot;), CFSTR(&quot;calt&quot;), CFSTR(&quot;subs&quot;), CFSTR(&quot;sups&quot;), CFSTR(&quot;smcp&quot;), CFSTR(&quot;c2sc&quot;), CFSTR(&quot;pcap&quot;), CFSTR(&quot;c2pc&quot;), CFSTR(&quot;unic&quot;), CFSTR(&quot;titl&quot;), CFSTR(&quot;onum&quot;), CFSTR(&quot;pnum&quot;), CFSTR(&quot;tnum&quot;), CFSTR(&quot;frac&quot;), CFSTR(&quot;afrc&quot;), CFSTR(&quot;ordn&quot;), CFSTR(&quot;zero&quot;), CFSTR(&quot;hist&quot;), CFSTR(&quot;jp78&quot;), CFSTR(&quot;jp83&quot;), CFSTR(&quot;jp90&quot;), CFSTR(&quot;jp04&quot;), CFSTR(&quot;smpl&quot;), CFSTR(&quot;trad&quot;), CFSTR(&quot;fwid&quot;), CFSTR(&quot;pwid&quot;), CFSTR(&quot;ruby&quot;) };
+        CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValuesOpenType, 30, &amp;kCFTypeArrayCallBacks);
</ins><span class="cx"> 
</span><del>-    for (CFIndex i = 0; i &lt; CFArrayGetCount(features); ++i) {
-        drawTextWithFeature(context, fontDescriptor, static_cast&lt;CFStringRef&gt;(CFArrayGetValueAtIndex(features, i)), 1, CGPointMake(25, 1950 - 50 * i));
-        drawTextWithFeature(context, fontDescriptor, static_cast&lt;CFStringRef&gt;(CFArrayGetValueAtIndex(features, i)), 0, CGPointMake(25, 1925 - 50 * i));
</del><ins>+        for (CFIndex i = 0; i &lt; CFArrayGetCount(features); ++i) {
+            CFStringRef feature = static_cast&lt;CFStringRef&gt;(CFArrayGetValueAtIndex(features, i));
+            CTFontDescriptorRef modifiedFontDescriptor = constructFontWithOpenTypeFeature(fontDescriptor, feature, 1);
+            CFMutableStringRef prefix = CFStringCreateMutable(kCFAllocatorDefault, 0);
+            CFStringAppend(prefix, feature);
+            CFStringAppend(prefix, CFSTR(&quot;  (on): &quot;));
+            drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1950 - 50 * i));
+            CFRelease(prefix);
+            CFRelease(modifiedFontDescriptor);
+
+            modifiedFontDescriptor = constructFontWithOpenTypeFeature(fontDescriptor, feature, 0);
+            prefix = CFStringCreateMutable(kCFAllocatorDefault, 0);
+            CFStringAppend(prefix, feature);
+            CFStringAppend(prefix, CFSTR(&quot; (off): &quot;));
+            drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1925 - 50 * i));
+            CFRelease(prefix);
+            CFRelease(modifiedFontDescriptor);
+        }
+
+        CFRelease(features);
+    } else {
+        __block int i = 0;
+        void (^handler)(uint16_t type, CFStringRef typeString, uint16_t selector, CFStringRef selectorString) = ^(uint16_t type, CFStringRef typeString, uint16_t selector, CFStringRef selectorString)
+        {
+            CTFontDescriptorRef modifiedFontDescriptor = constructFontWithTrueTypeFeature(fontDescriptor, type, selector);
+            CFMutableStringRef prefix = CFStringCreateMutable(kCFAllocatorDefault, 0);
+            CFStringAppend(prefix, typeString);
+            CFStringAppend(prefix, CFSTR(&quot;: &quot;));
+            CFStringAppend(prefix, selectorString);
+            CFStringAppend(prefix, CFSTR(&quot;: &quot;));
+            while (CFStringGetLength(prefix) &lt; 65)
+                CFStringAppend(prefix, CFSTR(&quot; &quot;));
+            drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1950 - 40 * i));
+            CFRelease(prefix);
+            CFRelease(modifiedFontDescriptor);
+            ++i;
+        };
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kCommonLigaturesOnSelector, CFSTR(&quot;kCommonLigaturesOnSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kContextualLigaturesOnSelector, CFSTR(&quot;kContextualLigaturesOnSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kCommonLigaturesOffSelector, CFSTR(&quot;kCommonLigaturesOffSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kContextualLigaturesOffSelector, CFSTR(&quot;kContextualLigaturesOffSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kRareLigaturesOnSelector, CFSTR(&quot;kRareLigaturesOnSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kRareLigaturesOffSelector, CFSTR(&quot;kRareLigaturesOffSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kHistoricalLigaturesOnSelector, CFSTR(&quot;kHistoricalLigaturesOnSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kHistoricalLigaturesOffSelector, CFSTR(&quot;kHistoricalLigaturesOffSelector&quot;));
+        handler(kContextualAlternatesType, CFSTR(&quot;kContextualAlternatesType&quot;), kContextualAlternatesOnSelector, CFSTR(&quot;kContextualAlternatesOnSelector&quot;));
+        handler(kContextualAlternatesType, CFSTR(&quot;kContextualAlternatesType&quot;), kContextualAlternatesOffSelector, CFSTR(&quot;kContextualAlternatesOffSelector&quot;));
+        handler(kVerticalPositionType, CFSTR(&quot;kVerticalPositionType&quot;), kInferiorsSelector, CFSTR(&quot;kInferiorsSelector&quot;));
+        handler(kVerticalPositionType, CFSTR(&quot;kVerticalPositionType&quot;), kSuperiorsSelector, CFSTR(&quot;kSuperiorsSelector&quot;));
+        handler(kLowerCaseType, CFSTR(&quot;kLowerCaseType&quot;), kLowerCaseSmallCapsSelector, CFSTR(&quot;kLowerCaseSmallCapsSelector&quot;));
+        handler(kUpperCaseType, CFSTR(&quot;kUpperCaseType&quot;), kUpperCaseSmallCapsSelector, CFSTR(&quot;kUpperCaseSmallCapsSelector&quot;));
+        handler(kLowerCaseType, CFSTR(&quot;kLowerCaseType&quot;), kLowerCasePetiteCapsSelector, CFSTR(&quot;kLowerCasePetiteCapsSelector&quot;));
+        handler(kUpperCaseType, CFSTR(&quot;kUpperCaseType&quot;), kUpperCasePetiteCapsSelector, CFSTR(&quot;kUpperCasePetiteCapsSelector&quot;));
+        handler(kLetterCaseType, CFSTR(&quot;kLetterCaseType&quot;), 14, CFSTR(&quot;14&quot;));
+        handler(kStyleOptionsType, CFSTR(&quot;kStyleOptionsType&quot;), kTitlingCapsSelector, CFSTR(&quot;kTitlingCapsSelector&quot;));
+        handler(kNumberCaseType, CFSTR(&quot;kNumberCaseType&quot;), kUpperCaseNumbersSelector, CFSTR(&quot;kUpperCaseNumbersSelector&quot;));
+        handler(kNumberCaseType, CFSTR(&quot;kNumberCaseType&quot;), kLowerCaseNumbersSelector, CFSTR(&quot;kLowerCaseNumbersSelector&quot;));
+        handler(kNumberSpacingType, CFSTR(&quot;kNumberSpacingType&quot;), kProportionalNumbersSelector, CFSTR(&quot;kProportionalNumbersSelector&quot;));
+        handler(kNumberSpacingType, CFSTR(&quot;kNumberSpacingType&quot;), kMonospacedNumbersSelector, CFSTR(&quot;kMonospacedNumbersSelector&quot;));
+        handler(kFractionsType, CFSTR(&quot;kFractionsType&quot;), kDiagonalFractionsSelector, CFSTR(&quot;kDiagonalFractionsSelector&quot;));
+        handler(kFractionsType, CFSTR(&quot;kFractionsType&quot;), kVerticalFractionsSelector, CFSTR(&quot;kVerticalFractionsSelector&quot;));
+        handler(kVerticalPositionType, CFSTR(&quot;kVerticalPositionType&quot;), kOrdinalsSelector, CFSTR(&quot;kOrdinalsSelector&quot;));
+        handler(kTypographicExtrasType, CFSTR(&quot;kTypographicExtrasType&quot;), kSlashedZeroOnSelector, CFSTR(&quot;kSlashedZeroOnSelector&quot;));
+        handler(kLigaturesType, CFSTR(&quot;kLigaturesType&quot;), kHistoricalLigaturesOnSelector, CFSTR(&quot;kHistoricalLigaturesOnSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kJIS1978CharactersSelector, CFSTR(&quot;kJIS1978CharactersSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kJIS1983CharactersSelector, CFSTR(&quot;kJIS1983CharactersSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kJIS1990CharactersSelector, CFSTR(&quot;kJIS1990CharactersSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kJIS2004CharactersSelector, CFSTR(&quot;kJIS2004CharactersSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kSimplifiedCharactersSelector, CFSTR(&quot;kSimplifiedCharactersSelector&quot;));
+        handler(kCharacterShapeType, CFSTR(&quot;kCharacterShapeType&quot;), kTraditionalCharactersSelector, CFSTR(&quot;kTraditionalCharactersSelector&quot;));
+        handler(kTextSpacingType, CFSTR(&quot;kTextSpacingType&quot;), kMonospacedTextSelector, CFSTR(&quot;kMonospacedTextSelector&quot;));
+        handler(kTextSpacingType, CFSTR(&quot;kTextSpacingType&quot;), kProportionalTextSelector, CFSTR(&quot;kProportionalTextSelector&quot;));
+        handler(kRubyKanaType, CFSTR(&quot;kRubyKanaType&quot;), kRubyKanaOnSelector, CFSTR(&quot;kRubyKanaOnSelector&quot;));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    CFRelease(features);
</del><span class="cx">     CFRelease(fontDescriptor);
</span><span class="cx">     CGImageRef image = CGBitmapContextCreateImage(context);
</span><span class="cx">     CGContextRelease(context);
</span></span></pre></div>
<a id="branchessafari601146branchToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj (193586 => 193587)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj        2015-12-06 21:21:01 UTC (rev 193586)
+++ branches/safari-601.1.46-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj        2015-12-06 21:32:41 UTC (rev 193587)
</span><span class="lines">@@ -186,7 +186,7 @@
</span><span class="cx">                                 GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
</span><span class="cx">                                 GCC_WARN_UNUSED_FUNCTION = YES;
</span><span class="cx">                                 GCC_WARN_UNUSED_VARIABLE = YES;
</span><del>-                                MACOSX_DEPLOYMENT_TARGET = 10.11;
</del><ins>+                                MACOSX_DEPLOYMENT_TARGET = 10.10;
</ins><span class="cx">                                 MTL_ENABLE_DEBUG_INFO = YES;
</span><span class="cx">                                 ONLY_ACTIVE_ARCH = YES;
</span><span class="cx">                                 SDKROOT = macosx;
</span><span class="lines">@@ -222,7 +222,7 @@
</span><span class="cx">                                 GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
</span><span class="cx">                                 GCC_WARN_UNUSED_FUNCTION = YES;
</span><span class="cx">                                 GCC_WARN_UNUSED_VARIABLE = YES;
</span><del>-                                MACOSX_DEPLOYMENT_TARGET = 10.11;
</del><ins>+                                MACOSX_DEPLOYMENT_TARGET = 10.10;
</ins><span class="cx">                                 MTL_ENABLE_DEBUG_INFO = NO;
</span><span class="cx">                                 SDKROOT = macosx;
</span><span class="cx">                         };
</span><span class="lines">@@ -261,6 +261,7 @@
</span><span class="cx">                                 C28626AB1BA902B9001961D6 /* Release */,
</span><span class="cx">                         );
</span><span class="cx">                         defaultConfigurationIsVisible = 0;
</span><ins>+                        defaultConfigurationName = Release;
</ins><span class="cx">                 };
</span><span class="cx"> /* End XCConfigurationList section */
</span><span class="cx">         };
</span></span></pre>
</div>
</div>

</body>
</html>