<!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>[193518] branches/safari-601-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/193518">193518</a></dd>
<dt>Author</dt> <dd>matthew_hanson@apple.com</dd>
<dt>Date</dt> <dd>2015-12-05 10:30:14 -0800 (Sat, 05 Dec 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/189890">r189890</a>. rdar://problem/23769735</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestsChangeLog">branches/safari-601-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601branchLayoutTestsplatformeflTestExpectations">branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations</a></li>
<li><a href="#branchessafari601branchLayoutTestsplatformwinTestExpectations">branches/safari-601-branch/LayoutTests/platform/win/TestExpectations</a></li>
<li><a href="#branchessafari601branchToolsChangeLog">branches/safari-601-branch/Tools/ChangeLog</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestscss3fontfeaturesettingsrendering2expectedhtml">branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html</a></li>
<li><a href="#branchessafari601branchLayoutTestscss3fontfeaturesettingsrendering2html">branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html</a></li>
<li><a href="#branchessafari601branchLayoutTestscss3resourcesFontWithFeaturesotf">branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.otf</a></li>
<li>branches/safari-601-branch/Tools/FontWithFeatures/</li>
<li>branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/</li>
<li><a href="#branchessafari601branchToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp">branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp</a></li>
<li><a href="#branchessafari601branchToolsFontWithFeaturesFontWithFeaturesFontCreatorh">branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h</a></li>
<li><a href="#branchessafari601branchToolsFontWithFeaturesFontWithFeaturesmaincpp">branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp</a></li>
<li>branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/</li>
<li><a href="#branchessafari601branchToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj">branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/ChangeLog (193517 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-05 18:30:10 UTC (rev 193517)
+++ branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -1,5 +1,22 @@
</span><span class="cx"> 2015-12-05 Matthew Hanson <matthew_hanson@apple.com>
</span><span class="cx">
</span><ins>+ Merge r189890. rdar://problem/23769735
+
+ 2015-09-16 Myles C. Maxfield <mmaxfield@apple.com>
+
+ Create a font which can be used for testing font features
+ https://bugs.webkit.org/show_bug.cgi?id=149237
+
+ Reviewed by Simon Fraser.
+
+ * css3/font-feature-settings-rendering-2-expected.html: Added.
+ * css3/font-feature-settings-rendering-2.html: Added.
+ * css3/resources/FontWithFeatures.otf: Added.
+ * platform/efl/TestExpectations:
+ * platform/win/TestExpectations:
+
+2015-12-05 Matthew Hanson <matthew_hanson@apple.com>
+
</ins><span class="cx"> Merge r188146. rdar://problem/23769732
</span><span class="cx">
</span><span class="cx"> 2015-08-07 Myles C. Maxfield <mmaxfield@apple.com>
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestscss3fontfeaturesettingsrendering2expectedhtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html         (rev 0)
+++ branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: "FontFeaturesTest";
+ src: url("resources/FontWithFeatures.otf") format("opentype");
+}
+</style>
+</head>
+<body>
+This tests that font features are able to be turned on and off as desired. It uses a special font
+designed specifically for this purpose. The test passes if you see a sequence of alternating check
+marks and X below.
+<div><span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+<span style="font-family: FontFeaturesTest;">BA</span>
+</div>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestscss3fontfeaturesettingsrendering2html"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html         (rev 0)
+++ branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: "FontFeaturesTest";
+ src: url("resources/FontWithFeatures.otf") format("opentype");
+}
+</style>
+</head>
+<body>
+This tests that font features are able to be turned on and off as desired. It uses a special font
+designed specifically for this purpose. The test passes if you see a sequence of alternating check
+marks and X below.
+<div id="insertionpoint"></div>
+<script>
+var insertionpoint = document.getElementById("insertionpoint");
+function addElement(feature, c) {
+ ["0", "1"].map(function(state) {
+ var element = document.createElement("span");
+ element.textContent = c;
+ element.style.fontFamily = "FontFeaturesTest";
+ element.style.webkitFontFeatureSettings = '"' + feature + '" ' + state;
+ insertionpoint.appendChild(element);
+ });
+ insertionpoint.appendChild(document.createTextNode(" "));
+}
+addElement("liga", "C");
+addElement("clig", "D");
+addElement("dlig", "E");
+addElement("hlig", "F");
+addElement("calt", "G");
+addElement("subs", "H");
+addElement("sups", "I");
+addElement("smcp", "J");
+addElement("c2sc", "K");
+addElement("pcap", "L");
+addElement("c2pc", "M");
+addElement("unic", "N");
+addElement("titl", "O");
+addElement("onum", "P");
+addElement("pnum", "Q");
+addElement("tnum", "R");
+addElement("frac", "S");
+//addElement("afrc", "T");
+addElement("ordn", "U");
+addElement("zero", "V");
+addElement("hist", "W");
+addElement("jp78", "X");
+addElement("jp83", "Y");
+addElement("jp90", "Z");
+addElement("jp04", "a");
+addElement("smpl", "b");
+addElement("trad", "c");
+addElement("fwid", "d");
+addElement("pwid", "e");
+addElement("ruby", "f");
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestscss3resourcesFontWithFeaturesotf"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.otf (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.otf         (rev 0)
+++ branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.otf        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+OTTO
+\x80 CFF \x94[\xA9D\xAC";GSUB\xC5b\xBB\xFE"\xE8\x94OS/2H\xE0Yb'|dcmap\xD5\xAF'\xE0jheadeD\xF8(L6hheag7(\x84$hmtx(\xA8\xD4maxpk)| name\xA8)\x9C$post)\xC0
+MylesFont9\x87\x87q\xDA
+MylesFont        
++ !"#$%&'()*+,-./012345I\xA7G\xE7\x87'\xC7g\xA7G\xE7\x87'\xC7        g
+
+\xA7G\xE7\x87+'+\xC7g\xA7G\xE7\x87'\xC7g\xA7G\xE7\x87'\xC7g\xA7G\xE7\x87'\xC7g\xA7G\xE7 \x87\xFF\xFF\xFF\xFF\xC8\xFF\xC8\xFF\xFFX\xFFX\xFF\xFF\xFF\xFD\xA8\xFF\xFD\xA8\xFF\xFF\xFF\xFF\xFF\xC8\xFF\xF4\xFF2\xFF2\xFF\xFA\xFF\xFF\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFE>\xFF\xFE>\xFF\xFE\xD4\xFF,\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\x
FF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xF
F\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE
\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp
\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90
\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp
\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp
\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF
\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF
2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x
90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x
90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\x
FEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\
x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF
2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2
\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90
\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp
\xFF\xFF\xFF\xFF\xF4\xFF&\xFF\x90\xFF\x90\xFF2\xFF\xFF\xCE\xFF\xFEp\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFF\xCE\xFF\xFF\xCE\xFF\xFEp\xFF\x90\xFF\xFEp\xFF\xFEp\xFF\xFF\xCE\xFF2\xFF\x90\xFF\x90\xFF\xFEp\xFF\x90\xFF2\xFF2\xFF\x90\xFF\xFEp
+X\xC2DFLT\xFF\xFF        
++liga\xB6clig\xBCdlig\xC2hlig\xC8calt\xCEsubs\xD4sups\xDAsmcp\xE0c2sc\xE6pcap\xECc2pc\xF2unic\xF8titl\xFEonumpnum
+tnumfracafrcordn"zero(hist.jp784jp83:jp90@jp04FsmplLtradRfwidXpwid^rubyd        
++>FNV^fnv~\x86\x8E\x96\x9E\xA6\xAE\xB6\xBE\xC6\xCE\xD6\xDE\xE6\xEE\xF6\xFE&\xF0\xF6\xFC &,28>DJPV\bhntz\x80\x86\x8C\x92\x98\x9E        
++ \xF4TKBW\xFF\xFFf\xFF\xFC\xFF\xFF \xFF\xFFD
+(AZaz&Zz\xFF\xFFAa\xFF\xFF\xFF\xDA\xFF\xA0y\xF6\x9C_<\xF5f55\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF5        MylesFont
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsplatformeflTestExpectations"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations (193517 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations        2015-12-05 18:30:10 UTC (rev 193517)
+++ branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -81,6 +81,8 @@
</span><span class="cx"> # This test has been added for ios port since r185842.
</span><span class="cx"> fast/text/arabic-times-new-roman.html [ Skip ]
</span><span class="cx">
</span><ins>+css3/font-feature-settings-rendering-2.html [ Skip ]
+
</ins><span class="cx"> # ----------------------------------------
</span><span class="cx"> # Tests which also fail in other platforms
</span><span class="cx"> # ----------------------------------------
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsplatformwinTestExpectations"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/platform/win/TestExpectations (193517 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/platform/win/TestExpectations        2015-12-05 18:30:10 UTC (rev 193517)
+++ branches/safari-601-branch/LayoutTests/platform/win/TestExpectations        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -458,6 +458,7 @@
</span><span class="cx">
</span><span class="cx"> # Font feature settings is not implemented.
</span><span class="cx"> css3/font-feature-settings-rendering.html [ Skip ]
</span><ins>+css3/font-feature-settings-rendering-2.html [ Skip ]
</ins><span class="cx">
</span><span class="cx"> # TODO HiDPI tests require test infrastructure enhancements (e.g. testRunner.setBackingScaleFactor)
</span><span class="cx"> # https://bugs.webkit.org/show_bug.cgi?id=87919
</span></span></pre></div>
<a id="branchessafari601branchToolsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Tools/ChangeLog (193517 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Tools/ChangeLog        2015-12-05 18:30:10 UTC (rev 193517)
+++ branches/safari-601-branch/Tools/ChangeLog        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -1,3 +1,118 @@
</span><ins>+2015-12-05 Matthew Hanson <matthew_hanson@apple.com>
+
+ Merge r189890. rdar://problem/23769735
+
+ 2015-09-16 Myles C. Maxfield <mmaxfield@apple.com>
+
+ Create a font which can be used for testing font features
+ https://bugs.webkit.org/show_bug.cgi?id=149237
+
+ Reviewed by Simon Fraser.
+
+ This patch adds a new project in the Tools/ directory which generates a font which can
+ be used for testing font features. This is a standalone project consisting of two files:
+ 1. A file which actually generates the byte vector representing the font. This file has
+ a single public function: std::vector<uint8_t> generateFont(). This file is not platform
+ specific, and only relies on the C++ STL.
+ 2. A file with a main() which calls generateFont() and writes out the font, as well as
+ uses the font to render some demonstration text into a .png file. This file is platform
+ specific.
+
+ 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 "A" always is a check mark.
+ The letter "B" always is an X.
+ Without any font features turned on, the rest of the letters are shown as 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 "smcp" is enabled, "J" is shown
+ as a check mark.
+
+ Here are the mappings of font features to letters:
+ liga: C
+ clig: D
+ dlig: E
+ hlig: F
+ calt: G
+ subs: H
+ sups: I
+ smcp: J
+ c2sc: K
+ pcap: L
+ c2pc: M
+ unic: N
+ titl: O
+ onum: P
+ pnum: Q
+ tnum: R
+ frac: S
+ afrc: T
+ ordn: U
+ zero: V
+ hist: W
+ jp78: X
+ jp83: Y
+ jp90: Z
+ jp04: a
+ smpl: b
+ trad: c
+ fwid: d
+ pwid: e
+ ruby: f
+
+ * FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj: Added.
+ * FontWithFeatures/FontWithFeatures/FontCreator.cpp: Added.
+ (integralLog2):
+ (roundDownToPowerOfTwo):
+ (isFourByteAligned):
+ (clampTo):
+ (append32):
+ (writeCFFEncodedNumber):
+ (CFFBuilder::CFFBuilder):
+ (CFFBuilder::takeResult):
+ (CFFBuilder::moveTo):
+ (CFFBuilder::lineTo):
+ (CFFBuilder::curveToCubic):
+ (CFFBuilder::closePath):
+ (CFFBuilder::writePoint):
+ (generateBoxCharString):
+ (generateCheckCharString):
+ (generateXCharString):
+ (charStringForGlyph):
+ (Generator::generate):
+ (Generator::Placeholder::Placeholder):
+ (Generator::Placeholder::populate):
+ (Generator::Placeholder::~Placeholder):
+ (Generator::placeholder):
+ (Generator::append16):
+ (Generator::append32):
+ (Generator::append32BitCode):
+ (Generator::overwrite16):
+ (Generator::overwrite32):
+ (Generator::appendCFFTable):
+ (Generator::appendSubstitutionSubtable):
+ (Generator::appendScriptSubtable):
+ (Generator::appendGSUBTable):
+ (Generator::appendOS2Table):
+ (Generator::appendFormat12CMAPTable):
+ (Generator::appendFormat4CMAPTable):
+ (Generator::appendCMAPTable):
+ (Generator::appendHEADTable):
+ (Generator::appendHHEATable):
+ (Generator::appendHMTXTable):
+ (Generator::appendMAXPTable):
+ (Generator::appendNAMETable):
+ (Generator::appendPOSTTable):
+ (Generator::calculateChecksum):
+ (Generator::appendTable):
+ (generateFont):
+ * FontWithFeatures/FontWithFeatures/FontCreator.h: Added.
+ * FontWithFeatures/FontWithFeatures/main.cpp: Added.
+ (drawTextWithFeature):
+ (main):
+
</ins><span class="cx"> 2015-10-27 Matthew Hanson <matthew_hanson@apple.com>
</span><span class="cx">
</span><span class="cx"> Merge r191395. rdar://problem/22847057
</span></span></pre></div>
<a id="branchessafari601branchToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp         (rev 0)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,788 @@
</span><ins>+//
+// FontCreator.cpp
+// FontWithFeatures
+//
+// Created by Litherum on 9/15/15.
+// Copyright © 2015 Litherum. All rights reserved.
+//
+
+#include "FontCreator.h"
+
+#include <array>
+#include <cassert>
+#include <string>
+
+static const size_t headerSize = 12;
+static const size_t directoryEntrySize = 16;
+static const int16_t unitsPerEm = 1024;
+static const uint16_t numGlyphs = 26 * 2 + 1;
+
+static inline uint16_t integralLog2(uint16_t x)
+{
+ uint16_t result = 0;
+ while (x >>= 1)
+ ++result;
+ return result;
+}
+
+static inline uint16_t roundDownToPowerOfTwo(uint16_t x)
+{
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ return (x >> 1) + 1;
+}
+
+static inline bool isFourByteAligned(size_t x)
+{
+ return !(x & 3);
+}
+
+// Assumption: T2 can hold every value that a T1 can hold.
+template<typename T1, typename T2> static inline T1 clampTo(T2 x)
+{
+ x = std::min(x, static_cast<T2>(std::numeric_limits<T1>::max()));
+ x = std::max(x, static_cast<T2>(std::numeric_limits<T1>::min()));
+ return static_cast<T1>(x);
+}
+
+template <typename V>
+static inline void append32(V& result, uint32_t value)
+{
+ result.push_back(value >> 24);
+ result.push_back(value >> 16);
+ result.push_back(value >> 8);
+ result.push_back(value);
+}
+
+template <typename V>
+static void writeCFFEncodedNumber(V& vector, float number)
+{
+ vector.push_back(0xFF);
+ // Convert to 16.16 fixed-point
+ append32(vector, clampTo<int32_t>(number * 0x10000));
+}
+
+static const char rLineTo = 0x05;
+static const char rrCurveTo = 0x08;
+static const char endChar = 0x0e;
+static const char rMoveTo = 0x15;
+
+class CFFBuilder {
+public:
+ CFFBuilder(float width, std::pair<float, float> origin)
+ {
+ writeCFFEncodedNumber(result, width);
+ writeCFFEncodedNumber(result, origin.first);
+ writeCFFEncodedNumber(result, origin.second);
+ result.push_back(rMoveTo);
+ }
+
+ std::vector<uint8_t> takeResult()
+ {
+ result.push_back(endChar);
+ return std::move(result);
+ }
+
+ void moveTo(std::pair<float, float> targetPoint, bool closed)
+ {
+ if (closed && !result.empty())
+ closePath();
+
+ std::pair<float, float> destination = targetPoint;
+
+ writePoint(destination);
+ result.push_back(rMoveTo);
+
+ startingPoint = current;
+ }
+
+ void lineTo(std::pair<float, float> targetPoint)
+ {
+ std::pair<float, float> destination = targetPoint;
+
+ writePoint(destination);
+ result.push_back(rLineTo);
+ }
+
+ void curveToCubic(std::pair<float, float> point1, std::pair<float, float> point2, std::pair<float, float> targetPoint)
+ {
+ std::pair<float, float> destination1 = point1;
+ std::pair<float, float> destination2 = point2;
+ std::pair<float, float> destination3 = targetPoint;
+
+ writePoint(destination1);
+ writePoint(destination2);
+ writePoint(destination3);
+ result.push_back(rrCurveTo);
+ }
+
+ void closePath()
+ {
+ if (current != startingPoint)
+ lineTo(startingPoint);
+ }
+
+private:
+ void writePoint(std::pair<float, float> destination)
+ {
+ std::pair<float, float> delta = std::make_pair(destination.first - current.first, destination.second - current.second);
+ writeCFFEncodedNumber(result, delta.first);
+ writeCFFEncodedNumber(result, delta.second);
+
+ current = destination;
+ }
+
+ std::vector<uint8_t> result;
+ std::pair<float, float> startingPoint;
+ std::pair<float, float> current;
+};
+
+std::vector<uint8_t> generateBoxCharString()
+{
+ CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
+ builder.moveTo(std::make_pair(200.f, 200.f), false);
+ builder.lineTo(std::make_pair(200.f, 800.f));
+ builder.lineTo(std::make_pair(800.f, 800.f));
+ builder.lineTo(std::make_pair(800.f, 200.f));
+ builder.closePath();
+ return builder.takeResult();
+}
+
+std::vector<uint8_t> generateCheckCharString()
+{
+ CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
+ builder.moveTo(std::make_pair(200.f, 500.f), false);
+ builder.lineTo(std::make_pair(250.f, 550.f));
+ builder.lineTo(std::make_pair(500.f, 300.f));
+ builder.lineTo(std::make_pair(900.f, 700.f));
+ builder.lineTo(std::make_pair(950.f, 650.f));
+ builder.lineTo(std::make_pair(500.f, 200.f));
+ builder.closePath();
+ return builder.takeResult();
+}
+
+std::vector<uint8_t> generateXCharString()
+{
+ CFFBuilder builder(unitsPerEm, std::make_pair(0.f, 0.f));
+ builder.moveTo(std::make_pair(500.0f, 550.0f), false);
+ builder.lineTo(std::make_pair(900.f, 950.f));
+ builder.lineTo(std::make_pair(950.f, 900.f));
+ builder.lineTo(std::make_pair(550.f, 500.f));
+ builder.lineTo(std::make_pair(950.f, 100.f));
+ builder.lineTo(std::make_pair(900.f, 50.f));
+ builder.lineTo(std::make_pair(500.f, 450.f));
+ builder.lineTo(std::make_pair(100.f, 50.f));
+ builder.lineTo(std::make_pair(50.f , 100.f));
+ builder.lineTo(std::make_pair(450.f, 500.f));
+ builder.lineTo(std::make_pair(50.f , 900.f));
+ builder.lineTo(std::make_pair(100.f, 950.f));
+ builder.closePath();
+ return builder.takeResult();
+}
+
+std::vector<uint8_t>& charStringForGlyph(uint16_t glyph, std::vector<uint8_t>& boxCharString, std::vector<uint8_t>& checkCharString, std::vector<uint8_t>& xCharString)
+{
+ if (!glyph)
+ return boxCharString;
+ if (glyph == 1)
+ return checkCharString;
+ return xCharString;
+}
+
+class Generator {
+public:
+ std::vector<uint8_t> generate()
+ {
+ uint16_t numTables = 10;
+ uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables);
+ uint16_t searchRange = roundedNumTables * 16; // searchRange: "(Maximum power of 2 <= numTables) x 16."
+
+ result.push_back('O');
+ result.push_back('T');
+ result.push_back('T');
+ result.push_back('O');
+ append16(numTables);
+ append16(searchRange);
+ append16(integralLog2(roundedNumTables)); // entrySelector: "Log2(maximum power of 2 <= numTables)."
+ append16(numTables * 16 - searchRange); // rangeShift: "NumTables x 16-searchRange."
+
+ assert(result.size() == headerSize);
+
+ // Leave space for the directory entries.
+ for (size_t i = 0; i < directoryEntrySize * numTables; ++i)
+ result.push_back(0);
+
+ appendTable("CFF ", &Generator::appendCFFTable);
+ appendTable("GSUB", &Generator::appendGSUBTable);
+ appendTable("OS/2", &Generator::appendOS2Table);
+ appendTable("cmap", &Generator::appendCMAPTable);
+ auto headTableOffset = result.size();
+ appendTable("head", &Generator::appendHEADTable);
+ appendTable("hhea", &Generator::appendHHEATable);
+ appendTable("hmtx", &Generator::appendHMTXTable);
+ appendTable("maxp", &Generator::appendMAXPTable);
+ appendTable("name", &Generator::appendNAMETable);
+ appendTable("post", &Generator::appendPOSTTable);
+
+ assert(numTables == m_tablesAppendedCount);
+
+ // checksumAdjustment: "To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory,
+ // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK."
+ overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, result.size()));
+ return std::move(result);
+ }
+
+private:
+ class Placeholder {
+ public:
+ Placeholder(Generator& generator, size_t baseOfOffset)
+ : generator(generator)
+ , baseOfOffset(baseOfOffset)
+ , location(generator.result.size())
+ {
+ generator.append16(0);
+ }
+
+ Placeholder(Placeholder&& other)
+ : generator(other.generator)
+ , baseOfOffset(other.baseOfOffset)
+ , location(other.location)
+ , active(other.active)
+ {
+ other.active = false;
+ }
+
+ void populate()
+ {
+ assert(active);
+ size_t delta = generator.result.size() - baseOfOffset;
+ assert(delta < std::numeric_limits<uint16_t>::max());
+ generator.overwrite16(location, delta);
+ active = false;
+ }
+
+ ~Placeholder()
+ {
+ assert(!active);
+ }
+
+ private:
+ Generator& generator;
+ const size_t baseOfOffset;
+ const size_t location;
+ bool active { true };
+ };
+
+ Placeholder placeholder(size_t baseOfOffset)
+ {
+ return Placeholder(*this, baseOfOffset);
+ }
+
+ void append16(uint16_t value)
+ {
+ result.push_back(value >> 8);
+ result.push_back(value);
+ }
+
+ void append32(uint32_t value)
+ {
+ ::append32(result, value);
+ }
+
+ void append32BitCode(const char code[4])
+ {
+ result.push_back(code[0]);
+ result.push_back(code[1]);
+ result.push_back(code[2]);
+ result.push_back(code[3]);
+ }
+
+ void overwrite16(size_t location, uint16_t value)
+ {
+ assert(result.size() >= location + 2);
+ result[location] = value >> 8;
+ result[location + 1] = value;
+ }
+
+ void overwrite32(size_t location, uint32_t value)
+ {
+ assert(result.size() >= location + 4);
+ result[location] = value >> 24;
+ result[location + 1] = value >> 16;
+ result[location + 2] = value >> 8;
+ result[location + 3] = value;
+ }
+
+ void appendCFFTable()
+ {
+ auto startingOffset = result.size();
+
+ // Header
+ result.push_back(1); // Major version
+ result.push_back(0); // Minor version
+ result.push_back(4); // Header size
+ result.push_back(4); // Offsets within CFF table are 4 bytes long
+
+ // Name INDEX
+ std::string fontName = "MylesFont";
+ append16(1); // INDEX contains 1 element
+ result.push_back(4); // Offsets in this INDEX are 4 bytes long
+ append32(1); // 1-index offset of name data
+ append32(static_cast<uint32_t>(fontName.length() + 1)); // 1-index offset just past end of name data
+ for (char c : fontName)
+ result.push_back(c);
+
+ const char operand32Bit = 29;
+ const char fullNameKey = 2;
+ const char familyNameKey = 3;
+ const char fontBBoxKey = 5;
+ const char charsetIndexKey = 15;
+ const char charstringsIndexKey = 17;
+ const char privateDictIndexKey = 18;
+ const uint32_t userDefinedStringStartIndex = 391;
+ const unsigned sizeOfTopIndex = 56;
+
+ // Top DICT INDEX.
+ append16(1); // INDEX contains 1 element
+ result.push_back(4); // Offsets in this INDEX are 4 bytes long
+ append32(1); // 1-index offset of DICT data
+ append32(1 + sizeOfTopIndex); // 1-index offset just past end of DICT data
+
+ // DICT information
+ size_t topDictStart = result.size();
+ result.push_back(operand32Bit);
+ append32(userDefinedStringStartIndex);
+ result.push_back(fullNameKey);
+ result.push_back(operand32Bit);
+ append32(userDefinedStringStartIndex);
+ result.push_back(familyNameKey);
+ result.push_back(operand32Bit);
+ append32(clampTo<int32_t>(0)); // Bounding box x
+ result.push_back(operand32Bit);
+ append32(clampTo<int32_t>(0)); // Bounding box y
+ result.push_back(operand32Bit);
+ append32(clampTo<int32_t>(unitsPerEm)); // Bounding box max x
+ result.push_back(operand32Bit);
+ append32(clampTo<int32_t>(unitsPerEm)); // Bounding box max y
+ result.push_back(fontBBoxKey);
+ result.push_back(operand32Bit);
+ size_t charsetOffsetLocation = result.size();
+ append32(0); // Offset of Charset info. Will be overwritten later.
+ result.push_back(charsetIndexKey);
+ result.push_back(operand32Bit);
+ size_t charstringsOffsetLocation = result.size();
+ append32(0); // Offset of CharStrings INDEX. Will be overwritten later.
+ result.push_back(charstringsIndexKey);
+ result.push_back(operand32Bit);
+ append32(0); // 0-sized private dict
+ result.push_back(operand32Bit);
+ append32(0); // no location for private dict
+ result.push_back(privateDictIndexKey); // Private dict size and offset
+ assert(result.size() == topDictStart + sizeOfTopIndex);
+
+ // String INDEX
+ append16(1); // Number of elements in INDEX
+ result.push_back(4); // Offsets in this INDEX are 4 bytes long
+ uint32_t offset = 1;
+ append32(offset);
+ offset += fontName.length();
+ append32(offset);
+ for (char c : fontName)
+ result.push_back(c);
+
+ append16(0); // Empty subroutine INDEX
+
+ // Charset info
+ overwrite32(charsetOffsetLocation, static_cast<uint32_t>(result.size() - startingOffset));
+ result.push_back(0);
+ for (int i = 1; i < numGlyphs; ++i)
+ append16(i);
+
+ // CharStrings INDEX
+ std::vector<uint8_t> boxCharString = generateBoxCharString();
+ std::vector<uint8_t> checkCharString = generateCheckCharString();
+ std::vector<uint8_t> xCharString = generateXCharString();
+ assert(numGlyphs > 26);
+ overwrite32(charstringsOffsetLocation, static_cast<uint32_t>(result.size() - startingOffset));
+ append16(numGlyphs);
+ result.push_back(4); // Offsets in this INDEX are 4 bytes long
+ offset = 1;
+ append32(offset);
+ for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) {
+ offset += charStringForGlyph(glyph, boxCharString, checkCharString, xCharString).size();
+ append32(offset);
+ }
+ for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) {
+ std::vector<uint8_t>& charString = charStringForGlyph(glyph, boxCharString, checkCharString, xCharString);
+ result.insert(result.end(), charString.begin(), charString.end());
+ }
+ }
+
+ void appendSubstitutionSubtable(size_t subtableRecordLocation, uint16_t iGetReplaced, uint16_t replacedWithMe)
+ {
+ overwrite16(subtableRecordLocation + 6, result.size() - subtableRecordLocation);
+ auto subtableLocation = result.size();
+ append16(2); // Format 2
+ append16(0); // Placeholder for offset to coverage table, relative to beginning of substitution table
+ append16(1); // GlyphCount
+ append16(replacedWithMe); // Substitute with this glyph.
+
+ // Coverage table
+ overwrite16(subtableLocation + 2, result.size() - subtableLocation);
+ append16(1); // CoverageFormat
+ append16(1); // GlyphCount
+ append16(iGetReplaced); // This glyph is covered in the coverage.
+ }
+
+ void appendScriptSubtable(uint16_t featureCount)
+ {
+ auto dfltScriptTableLocation = result.size();
+ append16(0); // Placeholder for offset of default language system table, relative to beginning of Script table
+ append16(0); // Number of following language system tables
+
+ // LangSys table
+ overwrite16(dfltScriptTableLocation, result.size() - dfltScriptTableLocation);
+ append16(0); // LookupOrder "= NULL ... reserved"
+ append16(0xFFFF); // No features are required
+ append16(featureCount); // Number of FeatureIndex values
+ for (uint16_t i = 0; i < featureCount; ++i)
+ append16(i); // Features indices
+ }
+
+ void appendGSUBTable()
+ {
+ std::vector<std::array<char, 5>> features {{"liga"}, {"clig"}, {"dlig"}, {"hlig"}, {"calt"}, {"subs"}, {"sups"}, {"smcp"}, {"c2sc"}, {"pcap"}, {"c2pc"}, {"unic"}, {"titl"}, {"onum"}, {"pnum"}, {"tnum"}, {"frac"}, {"afrc"}, {"ordn"}, {"zero"}, {"hist"}, {"jp78"}, {"jp83"}, {"jp90"}, {"jp04"}, {"smpl"}, {"trad"}, {"fwid"}, {"pwid"}, {"ruby"}};
+ auto tableLocation = result.size();
+ auto headerSize = 10;
+
+ append32(0x00010000); // Version
+ append16(headerSize); // Offset to ScriptList
+ Placeholder toFeatureList = placeholder(tableLocation);
+ Placeholder toLookupList = placeholder(tableLocation);
+ assert(tableLocation + headerSize == result.size());
+
+ // ScriptList
+ auto scriptListLocation = result.size();
+ append16(1); // Number of ScriptRecords
+ append32BitCode("DFLT");
+ append16(0); // Placeholder for offset of Script table, relative to beginning of ScriptList
+
+ overwrite16(scriptListLocation + 6, result.size() - scriptListLocation);
+ appendScriptSubtable(static_cast<uint16_t>(features.size()));
+
+ // FeatureList
+ toFeatureList.populate();
+ auto featureListLocation = result.size();
+ size_t featureListSize = 2 + 6 * features.size();
+ size_t featureTableSize = 6;
+ append16(features.size()); // FeatureCount
+ for (unsigned i = 0; i < features.size(); ++i) {
+ auto& code = features[i];
+ append32BitCode(code.data()); // Feature name
+ append16(featureListSize + featureTableSize * i); // Offset of feature table, relative to beginning of FeatureList table
+ }
+ assert(featureListLocation + featureListSize == result.size());
+
+ for (unsigned i = 0; i < features.size(); ++i) {
+ auto featureTableStart = result.size();
+ append16(0); // FeatureParams "= NULL ... reserved"
+ append16(1); // LookupCount
+ append16(i); // LookupListIndex
+ assert(featureTableStart + featureTableSize == result.size());
+ }
+
+ // LookupList
+ toLookupList.populate();
+ auto lookupListLocation = result.size();
+ append16(features.size()); // LookupCount
+ for (unsigned i = 0; i < features.size(); ++i)
+ append16(0); // Placeholder for offset to lookup table, relative to beginning of LookupList
+ size_t subtableRecordLocations[features.size()];
+ for (unsigned i = 0; i < features.size(); ++i) {
+ subtableRecordLocations[i] = result.size();
+ overwrite16(lookupListLocation + 2 + 2 * i, result.size() - lookupListLocation);
+ append16(1); // Type 1: "Replace one glyph with one glyph"
+ append16(0); // LookupFlag
+ append16(1); // SubTableCount
+ append16(0); // Placeholder for offset to subtable, relative to beginning of Lookup table
+ }
+
+ for (unsigned i = 0; i < features.size(); ++i)
+ appendSubstitutionSubtable(subtableRecordLocations[i], 3 + i, 1);
+ }
+
+ void appendOS2Table()
+ {
+ append16(2); // Version
+ append16(clampTo<int16_t>(unitsPerEm)); // Average advance
+ append16(clampTo<uint16_t>(500)); // Weight class
+ append16(5); // Width class
+ append16(0); // Protected font
+ // WebKit handles these superscripts and subscripts
+ append16(0); // Subscript X Size
+ append16(0); // Subscript Y Size
+ append16(0); // Subscript X Offset
+ append16(0); // Subscript Y Offset
+ append16(0); // Superscript X Size
+ append16(0); // Superscript Y Size
+ append16(0); // Superscript X Offset
+ append16(0); // Superscript Y Offset
+ append16(0); // Strikeout width
+ append16(0); // Strikeout Position
+ append16(0); // No classification
+
+ for (int i = 0; i < 10; ++i)
+ result.push_back(0);
+
+ for (int i = 0; i < 4; ++i)
+ append32(0); // "Bit assignments are pending. Set to 0"
+ append32(0x544B4257); // Font Vendor. "WBKT"
+ append16(0); // Font Patterns.
+ append16(0); // First unicode index
+ append16(0xFFFF); // Last unicode index
+ append16(clampTo<int16_t>(unitsPerEm)); // Typographical ascender
+ append16(clampTo<int16_t>(1)); // Typographical descender
+ append16(clampTo<int16_t>(unitsPerEm / 10)); // Typographical line gap
+ append16(clampTo<uint16_t>(unitsPerEm)); // Windows-specific ascent
+ append16(clampTo<uint16_t>(1)); // Windows-specific descent
+ append32(0xFF10FC07); // Bitmask for supported codepages (Part 1). Report all pages as supported.
+ append32(0x0000FFFF); // Bitmask for supported codepages (Part 2). Report all pages as supported.
+ append16(clampTo<int16_t>(unitsPerEm / 2)); // x-height
+ append16(clampTo<int16_t>(unitsPerEm)); // Cap-height
+ append16(0); // Default char
+ append16(' '); // Break character
+ append16(3); // Maximum context needed to perform font features
+ append16(3); // Smallest optical point size
+ append16(0xFFFF); // Largest optical point size
+ }
+
+ void appendFormat12CMAPTable()
+ {
+ // Braindead scheme: One segment for each character
+ auto subtableLocation = result.size();
+ append32(12 << 16); // Format 12
+ append32(0); // Placeholder for byte length
+ append32(0); // Language independent
+ append32(2); // nGroups
+ append32('A'); // startCharCode
+ append32('Z'); // endCharCode
+ append32(1); // startGlyphCode
+ append32('a'); // startCharCode
+ append32('z'); // endCharCode
+ append32(27); // startGlyphCode
+ overwrite32(subtableLocation + 4, static_cast<uint32_t>(result.size() - subtableLocation));
+ }
+
+ void appendFormat4CMAPTable()
+ {
+ auto subtableLocation = result.size();
+ append16(4); // Format 4
+ append16(0); // Placeholder for length in bytes
+ append16(0); // Language independent
+ uint16_t segCount = 3;
+ append16(clampTo<uint16_t>(2 * segCount)); // segCountX2: "2 x segCount"
+ uint16_t originalSearchRange = roundDownToPowerOfTwo(segCount);
+ uint16_t searchRange = clampTo<uint16_t>(2 * originalSearchRange); // searchRange: "2 x (2**floor(log2(segCount)))"
+ append16(searchRange);
+ append16(integralLog2(originalSearchRange)); // entrySelector: "log2(searchRange/2)"
+ append16(clampTo<uint16_t>((2 * segCount) - searchRange)); // rangeShift: "2 x segCount - searchRange"
+
+ // Ending character codes
+ append16('Z');
+ append16('z');
+ append16(0xFFFF);
+
+ append16(0); // reserved
+
+ // Starting character codes
+ append16('A');
+ append16('a');
+ append16(0xFFFF);
+
+ // idDelta
+ append16(static_cast<uint16_t>(27) - static_cast<uint16_t>('A'));
+ append16(static_cast<uint16_t>(1) - static_cast<uint16_t>('a'));
+ append16(0x0001);
+
+ // idRangeOffset
+ append16(0); // idRangeOffset
+ append16(0);
+
+ // Fonts strive to hold 2^16 glyphs, but with the current encoding scheme, we write 8 bytes per codepoint into this subtable.
+ // Because the size of this subtable must be represented as a 16-bit number, we are limiting the number of glyphs we support to 2^13.
+ // FIXME: If we hit this limit in the wild, use a more compact encoding scheme for this subtable.
+ overwrite16(subtableLocation + 2, clampTo<uint16_t>(result.size() - subtableLocation));
+ }
+
+ void appendCMAPTable()
+ {
+ auto startingOffset = result.size();
+ append16(0);
+ append16(3); // Number of subtables
+
+ append16(0); // Unicode
+ append16(3); // Unicode version 2.2+
+ append32(28); // Byte offset of subtable
+
+ append16(3); // Microsoft
+ append16(1); // Unicode BMP
+ auto format4OffsetLocation = result.size();
+ append32(0); // Byte offset of subtable
+
+ append16(3); // Microsoft
+ append16(10); // Unicode
+ append32(28); // Byte offset of subtable
+
+ appendFormat12CMAPTable();
+ overwrite32(format4OffsetLocation, static_cast<uint32_t>(result.size() - startingOffset));
+ appendFormat4CMAPTable();
+ }
+
+ void appendHEADTable()
+ {
+ append32(0x00010000); // Version
+ append32(0x00010000); // Revision
+ append32(0); // Checksum placeholder; to be overwritten by the caller.
+ append32(0x5F0F3CF5); // Magic number.
+ append16((1 << 9) | 1);
+
+ append16(unitsPerEm);
+ append32(0); // First half of creation date
+ append32(0); // Last half of creation date
+ append32(0); // First half of modification date
+ append32(0); // Last half of modification date
+ append16(clampTo<int16_t>(0)); // bounding box x
+ append16(clampTo<int16_t>(0)); // bounding box y
+ append16(clampTo<int16_t>(unitsPerEm)); // bounding box max x
+ append16(clampTo<int16_t>(unitsPerEm)); // bounding box max y
+ append16(0); // Traits
+ append16(3); // Smallest readable size in pixels
+ append16(0); // Might contain LTR or RTL glyphs
+ append16(0); // Short offsets in the 'loca' table. However, OTF fonts don't have a 'loca' table so this is irrelevant
+ append16(0); // Glyph data format
+ }
+
+ void appendHHEATable()
+ {
+ append32(0x00010000); // Version
+ append16(clampTo<int16_t>(unitsPerEm)); // ascent
+ append16(clampTo<int16_t>(1)); // descent
+ // WebKit SVG font rendering has hard coded the line gap to be 1/10th of the font size since 2008 (see r29719).
+ append16(clampTo<int16_t>(unitsPerEm / 10)); // line gap
+ append16(clampTo<uint16_t>(unitsPerEm)); // advance width max
+ append16(clampTo<int16_t>(0)); // Minimum left side bearing
+ append16(clampTo<int16_t>(0)); // Minimum right side bearing
+ append16(clampTo<int16_t>(unitsPerEm)); // X maximum extent
+ // Since WebKit draws the caret and ignores the following values, it doesn't matter what we set them to.
+ append16(1); // Vertical caret
+ append16(0); // Vertical caret
+ append16(0); // "Set value to 0 for non-slanted fonts"
+ append32(0); // Reserved
+ append32(0); // Reserved
+ append16(0); // Current format
+ append16(numGlyphs); // Number of advance widths in HMTX table
+ }
+
+ void appendHMTXTable()
+ {
+ for (unsigned i = 0; i < numGlyphs; ++i) {
+ append16(clampTo<uint16_t>(unitsPerEm)); // horizontal advance
+ append16(clampTo<int16_t>(0)); // left side bearing
+ }
+ }
+
+ void appendMAXPTable()
+ {
+ append32(0x00010000); // Version
+ append16(numGlyphs); // Number of glyphs
+ append16(0xFFFF); // Maximum number of points in non-compound glyph
+ append16(0xFFFF); // Maximum number of contours in non-compound glyph
+ append16(0xFFFF); // Maximum number of points in compound glyph
+ append16(0xFFFF); // Maximum number of contours in compound glyph
+ append16(2); // Maximum number of zones
+ append16(0); // Maximum number of points used in zone 0
+ append16(0); // Maximum number of storage area locations
+ append16(0); // Maximum number of function definitions
+ append16(0); // Maximum number of instruction definitions
+ append16(0); // Maximum stack depth
+ append16(0); // Maximum size of instructions
+ append16(numGlyphs); // Maximum number of glyphs referenced at top level
+ append16(0); // No compound glyphs
+ }
+
+ void appendNAMETable()
+ {
+ std::string fontName = "MylesFont";
+
+ append16(0); // Format selector
+ append16(1); // Number of name records in table
+ append16(18); // Offset in bytes to the beginning of name character strings
+
+ append16(0); // Unicode
+ append16(3); // Unicode version 2.0 or later
+ append16(0); // Language
+ append16(1); // Name identifier. 1 = Font family
+ append16(fontName.length());
+ append16(0); // Offset into name data
+
+ for (auto codeUnit : fontName)
+ append16(codeUnit);
+ }
+
+ void appendPOSTTable()
+ {
+ append32(0x00030000); // Format. Printing is undefined
+ append32(0); // Italic angle in degrees
+ append16(0); // Underline position
+ append16(0); // Underline thickness
+ append32(0); // Monospaced
+ append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 42 font"
+ append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 42 font"
+ append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 1 font"
+ append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 1 font"
+ }
+
+ uint32_t calculateChecksum(size_t startingOffset, size_t endingOffset) const
+ {
+ assert(isFourByteAligned(endingOffset - startingOffset));
+ uint32_t sum = 0;
+ for (size_t offset = startingOffset; offset < endingOffset; offset += 4) {
+ sum += static_cast<unsigned char>(result[offset + 3])
+ | (static_cast<unsigned char>(result[offset + 2]) << 8)
+ | (static_cast<unsigned char>(result[offset + 1]) << 16)
+ | (static_cast<unsigned char>(result[offset]) << 24);
+ }
+ return sum;
+ }
+
+ typedef void (Generator::*FontAppendingFunction)();
+ void appendTable(const char identifier[4], FontAppendingFunction appendingFunction)
+ {
+ size_t offset = result.size();
+ assert(isFourByteAligned(offset));
+ (this->*appendingFunction)();
+ size_t unpaddedSize = result.size() - offset;
+ while (!isFourByteAligned(result.size()))
+ result.push_back(0);
+ assert(isFourByteAligned(result.size()));
+ size_t directoryEntryOffset = headerSize + m_tablesAppendedCount * directoryEntrySize;
+ result[directoryEntryOffset] = identifier[0];
+ result[directoryEntryOffset + 1] = identifier[1];
+ result[directoryEntryOffset + 2] = identifier[2];
+ result[directoryEntryOffset + 3] = identifier[3];
+ overwrite32(directoryEntryOffset + 4, calculateChecksum(offset, result.size()));
+ overwrite32(directoryEntryOffset + 8, static_cast<uint32_t>(offset));
+ overwrite32(directoryEntryOffset + 12, static_cast<uint32_t>(unpaddedSize));
+ ++m_tablesAppendedCount;
+ }
+
+ unsigned m_tablesAppendedCount { 0 };
+ std::vector<uint8_t> result;
+};
+
+std::vector<uint8_t> generateFont()
+{
+ return Generator().generate();
+}
</ins></span></pre></div>
<a id="branchessafari601branchToolsFontWithFeaturesFontWithFeaturesFontCreatorh"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h         (rev 0)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+//
+// FontCreator.hpp
+// FontWithFeatures
+//
+// Created by Litherum on 9/15/15.
+// Copyright © 2015 Litherum. All rights reserved.
+//
+
+#ifndef FontCreator_h
+#define FontCreator_h
+
+#include <vector>
+
+std::vector<uint8_t> generateFont();
+
+#endif /* FontCreator_h */
</ins></span></pre></div>
<a id="branchessafari601branchToolsFontWithFeaturesFontWithFeaturesmaincpp"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp         (rev 0)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,114 @@
</span><ins>+//
+// main.cpp
+// FontWithFeatures
+//
+// Created by Litherum on 9/15/15.
+// Copyright © 2015 Litherum. All rights reserved.
+//
+
+#include "FontCreator.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreServices/CoreServices.h>
+#include <CoreText/CoreText.h>
+#include <ImageIO/ImageIO.h>
+#include <fstream>
+
+void drawTextWithFeature(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value, CGPoint location)
+{
+ CGFloat fontSize = 25;
+ CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
+ CGContextSetTextPosition(context, location.x, location.y);
+
+ CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
+ CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
+ CFTypeRef featureDictionaryValues[] = { feature, featureValue };
+ CFDictionaryRef featureDictionary = CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFRelease(featureValue);
+
+ CFTypeRef featureSettingsValues[] = { featureDictionary };
+ CFArrayRef fontFeatureSettings = CFArrayCreate(kCFAllocatorDefault, featureSettingsValues, 1, &kCFTypeArrayCallBacks);
+ CFRelease(featureDictionary);
+
+ CFTypeRef fontDescriptorKeys[] = { kCTFontFeatureSettingsAttribute };
+ CFTypeRef fontDescriptorValues[] = { fontFeatureSettings };
+ CFDictionaryRef fontDescriptorAttributes = CFDictionaryCreate(kCFAllocatorDefault, fontDescriptorKeys, fontDescriptorValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFRelease(fontFeatureSettings);
+
+ CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes);
+ CFRelease(fontDescriptorAttributes);
+
+ CTFontRef font = CTFontCreateWithFontDescriptor(modifiedFontDescriptor, fontSize, nullptr);
+ CFRelease(modifiedFontDescriptor);
+
+ CFMutableStringRef string = CFStringCreateMutable(kCFAllocatorDefault, 0);
+ CFStringAppend(string, feature);
+ CFStringAppend(string, value ? CFSTR(" (on)") : CFSTR(" (off)"));
+ CFStringAppend(string, CFSTR(": ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
+
+ CGColorRef red = CGColorCreateGenericRGB(1, 0, 0, 1);
+ CFTypeRef lineKeys[] = { kCTForegroundColorAttributeName };
+ CFTypeRef lineValues[] = { red };
+ CFDictionaryRef lineAttributes = CFDictionaryCreate(kCFAllocatorDefault, lineKeys, lineValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CGColorRelease(red);
+
+ CFAttributedStringRef attributedString = CFAttributedStringCreate(kCFAllocatorDefault, string, lineAttributes);
+ CFRelease(lineAttributes);
+ CFRelease(string);
+
+ CFMutableAttributedStringRef mutableAttributedString = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, attributedString);
+ CFRelease(attributedString);
+
+ CTFontRef monospaceFont = CTFontCreateWithName(CFSTR("Courier"), fontSize, nullptr);
+ CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, 12), kCTFontAttributeName, monospaceFont);
+ CFRelease(monospaceFont);
+
+ CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(12, 52), kCTFontAttributeName, font);
+ CFRelease(font);
+
+ CTLineRef line = CTLineCreateWithAttributedString(mutableAttributedString);
+ CFRelease(mutableAttributedString);
+
+ CTLineDraw(line, context);
+ CFRelease(line);
+}
+
+int main(int argc, const char * argv[])
+{
+ size_t width = 2000;
+ size_t height = 2000;
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGContextRef context = CGBitmapContextCreate(nullptr, width, height, 8, width * 4, colorSpace, kCGImageAlphaNoneSkipLast);
+ CGColorSpaceRelease(colorSpace);
+ const std::vector<uint8_t> fontVector = generateFont();
+ std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.otf", std::ios::out | std::ios::binary);
+ for (uint8_t b : fontVector)
+ outputFile << b;
+ outputFile.close();
+
+ CFDataRef fontData = CFDataCreate(kCFAllocatorDefault, fontVector.data(), fontVector.size());
+ CTFontDescriptorRef fontDescriptor = CTFontManagerCreateFontDescriptorFromData(fontData);
+ CFRelease(fontData);
+
+ CFTypeRef featureValues[] = { CFSTR("liga"), CFSTR("clig"), CFSTR("dlig"), CFSTR("hlig"), CFSTR("calt"), CFSTR("subs"), CFSTR("sups"), CFSTR("smcp"), CFSTR("c2sc"), CFSTR("pcap"), CFSTR("c2pc"), CFSTR("unic"), CFSTR("titl"), CFSTR("onum"), CFSTR("pnum"), CFSTR("tnum"), CFSTR("frac"), CFSTR("afrc"), CFSTR("ordn"), CFSTR("zero"), CFSTR("hist"), CFSTR("jp78"), CFSTR("jp83"), CFSTR("jp90"), CFSTR("jp04"), CFSTR("smpl"), CFSTR("trad"), CFSTR("fwid"), CFSTR("pwid"), CFSTR("ruby") };
+ CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValues, 30, &kCFTypeArrayCallBacks);
+
+ for (CFIndex i = 0; i < CFArrayGetCount(features); ++i) {
+ drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 1, CGPointMake(25, 1950 - 50 * i));
+ drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 0, CGPointMake(25, 1925 - 50 * i));
+ }
+
+ CFRelease(features);
+ CFRelease(fontDescriptor);
+ CGImageRef image = CGBitmapContextCreateImage(context);
+ CGContextRelease(context);
+ CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Volumes/Data/home/mmaxfield/tmp/output.png"), kCFURLPOSIXPathStyle, FALSE);
+ CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, nullptr);
+ CFRelease(url);
+ CGImageDestinationAddImage(imageDestination, image, nullptr);
+ CGImageRelease(image);
+ CGImageDestinationFinalize(imageDestination);
+ CFRelease(imageDestination);
+ return 0;
+}
</ins></span></pre></div>
<a id="branchessafari601branchToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj (0 => 193518)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj         (rev 0)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj        2015-12-05 18:30:14 UTC (rev 193518)
</span><span class="lines">@@ -0,0 +1,268 @@
</span><ins>+// !$*UTF8*$!
+{
+        archiveVersion = 1;
+        classes = {
+        };
+        objectVersion = 46;
+        objects = {
+
+/* Begin PBXBuildFile section */
+                C28626A61BA902B9001961D6 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28626A51BA902B9001961D6 /* main.cpp */; };
+                C28626AD1BA904F1001961D6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C28626AC1BA904F1001961D6 /* CoreGraphics.framework */; };
+                C28626AF1BA9062C001961D6 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C28626AE1BA9062C001961D6 /* ImageIO.framework */; };
+                C28626B11BA906C1001961D6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C28626B01BA906C1001961D6 /* CoreFoundation.framework */; };
+                C28626B31BA906D1001961D6 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C28626B21BA906D1001961D6 /* CoreServices.framework */; };
+                C28626B51BA907AE001961D6 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C28626B41BA907AE001961D6 /* CoreText.framework */; };
+                C28626B81BA91762001961D6 /* FontCreator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28626B61BA91762001961D6 /* FontCreator.cpp */; settings = {ASSET_TAGS = (); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+                C28626A01BA902B9001961D6 /* CopyFiles */ = {
+                        isa = PBXCopyFilesBuildPhase;
+                        buildActionMask = 2147483647;
+                        dstPath = /usr/share/man/man1/;
+                        dstSubfolderSpec = 0;
+                        files = (
+                        );
+                        runOnlyForDeploymentPostprocessing = 1;
+                };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+                C28626A21BA902B9001961D6 /* FontWithFeatures */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FontWithFeatures; sourceTree = BUILT_PRODUCTS_DIR; };
+                C28626A51BA902B9001961D6 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+                C28626AC1BA904F1001961D6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+                C28626AE1BA9062C001961D6 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
+                C28626B01BA906C1001961D6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+                C28626B21BA906D1001961D6 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+                C28626B41BA907AE001961D6 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
+                C28626B61BA91762001961D6 /* FontCreator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontCreator.cpp; sourceTree = "<group>"; };
+                C28626B71BA91762001961D6 /* FontCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontCreator.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+                C286269F1BA902B9001961D6 /* Frameworks */ = {
+                        isa = PBXFrameworksBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                C28626B51BA907AE001961D6 /* CoreText.framework in Frameworks */,
+                                C28626B31BA906D1001961D6 /* CoreServices.framework in Frameworks */,
+                                C28626B11BA906C1001961D6 /* CoreFoundation.framework in Frameworks */,
+                                C28626AF1BA9062C001961D6 /* ImageIO.framework in Frameworks */,
+                                C28626AD1BA904F1001961D6 /* CoreGraphics.framework in Frameworks */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+                C28626991BA902B9001961D6 = {
+                        isa = PBXGroup;
+                        children = (
+                                C28626B41BA907AE001961D6 /* CoreText.framework */,
+                                C28626B21BA906D1001961D6 /* CoreServices.framework */,
+                                C28626B01BA906C1001961D6 /* CoreFoundation.framework */,
+                                C28626AE1BA9062C001961D6 /* ImageIO.framework */,
+                                C28626AC1BA904F1001961D6 /* CoreGraphics.framework */,
+                                C28626A41BA902B9001961D6 /* FontWithFeatures */,
+                                C28626A31BA902B9001961D6 /* Products */,
+                        );
+                        sourceTree = "<group>";
+                };
+                C28626A31BA902B9001961D6 /* Products */ = {
+                        isa = PBXGroup;
+                        children = (
+                                C28626A21BA902B9001961D6 /* FontWithFeatures */,
+                        );
+                        name = Products;
+                        sourceTree = "<group>";
+                };
+                C28626A41BA902B9001961D6 /* FontWithFeatures */ = {
+                        isa = PBXGroup;
+                        children = (
+                                C28626A51BA902B9001961D6 /* main.cpp */,
+                                C28626B61BA91762001961D6 /* FontCreator.cpp */,
+                                C28626B71BA91762001961D6 /* FontCreator.h */,
+                        );
+                        path = FontWithFeatures;
+                        sourceTree = "<group>";
+                };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+                C28626A11BA902B9001961D6 /* FontWithFeatures */ = {
+                        isa = PBXNativeTarget;
+                        buildConfigurationList = C28626A91BA902B9001961D6 /* Build configuration list for PBXNativeTarget "FontWithFeatures" */;
+                        buildPhases = (
+                                C286269E1BA902B9001961D6 /* Sources */,
+                                C286269F1BA902B9001961D6 /* Frameworks */,
+                                C28626A01BA902B9001961D6 /* CopyFiles */,
+                        );
+                        buildRules = (
+                        );
+                        dependencies = (
+                        );
+                        name = FontWithFeatures;
+                        productName = FontWithFeatures;
+                        productReference = C28626A21BA902B9001961D6 /* FontWithFeatures */;
+                        productType = "com.apple.product-type.tool";
+                };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+                C286269A1BA902B9001961D6 /* Project object */ = {
+                        isa = PBXProject;
+                        attributes = {
+                                LastUpgradeCheck = 0700;
+                                ORGANIZATIONNAME = Litherum;
+                                TargetAttributes = {
+                                        C28626A11BA902B9001961D6 = {
+                                                CreatedOnToolsVersion = 7.0;
+                                        };
+                                };
+                        };
+                        buildConfigurationList = C286269D1BA902B9001961D6 /* Build configuration list for PBXProject "FontWithFeatures" */;
+                        compatibilityVersion = "Xcode 3.2";
+                        developmentRegion = English;
+                        hasScannedForEncodings = 0;
+                        knownRegions = (
+                                en,
+                        );
+                        mainGroup = C28626991BA902B9001961D6;
+                        productRefGroup = C28626A31BA902B9001961D6 /* Products */;
+                        projectDirPath = "";
+                        projectRoot = "";
+                        targets = (
+                                C28626A11BA902B9001961D6 /* FontWithFeatures */,
+                        );
+                };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+                C286269E1BA902B9001961D6 /* Sources */ = {
+                        isa = PBXSourcesBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                C28626A61BA902B9001961D6 /* main.cpp in Sources */,
+                                C28626B81BA91762001961D6 /* FontCreator.cpp in Sources */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+                C28626A71BA902B9001961D6 /* Debug */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                ALWAYS_SEARCH_USER_PATHS = NO;
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                                CLANG_CXX_LIBRARY = "libc++";
+                                CLANG_ENABLE_MODULES = YES;
+                                CLANG_ENABLE_OBJC_ARC = YES;
+                                CLANG_WARN_BOOL_CONVERSION = YES;
+                                CLANG_WARN_CONSTANT_CONVERSION = YES;
+                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                                CLANG_WARN_EMPTY_BODY = YES;
+                                CLANG_WARN_ENUM_CONVERSION = YES;
+                                CLANG_WARN_INT_CONVERSION = YES;
+                                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                                CLANG_WARN_UNREACHABLE_CODE = YES;
+                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                                COPY_PHASE_STRIP = NO;
+                                DEBUG_INFORMATION_FORMAT = dwarf;
+                                ENABLE_STRICT_OBJC_MSGSEND = YES;
+                                ENABLE_TESTABILITY = YES;
+                                GCC_C_LANGUAGE_STANDARD = gnu99;
+                                GCC_DYNAMIC_NO_PIC = NO;
+                                GCC_NO_COMMON_BLOCKS = YES;
+                                GCC_OPTIMIZATION_LEVEL = 0;
+                                GCC_PREPROCESSOR_DEFINITIONS = (
+                                        "DEBUG=1",
+                                        "$(inherited)",
+                                );
+                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                                GCC_WARN_UNDECLARED_SELECTOR = YES;
+                                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                                GCC_WARN_UNUSED_FUNCTION = YES;
+                                GCC_WARN_UNUSED_VARIABLE = YES;
+                                MACOSX_DEPLOYMENT_TARGET = 10.11;
+                                MTL_ENABLE_DEBUG_INFO = YES;
+                                ONLY_ACTIVE_ARCH = YES;
+                                SDKROOT = macosx;
+                        };
+                        name = Debug;
+                };
+                C28626A81BA902B9001961D6 /* Release */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                ALWAYS_SEARCH_USER_PATHS = NO;
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                                CLANG_CXX_LIBRARY = "libc++";
+                                CLANG_ENABLE_MODULES = YES;
+                                CLANG_ENABLE_OBJC_ARC = YES;
+                                CLANG_WARN_BOOL_CONVERSION = YES;
+                                CLANG_WARN_CONSTANT_CONVERSION = YES;
+                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                                CLANG_WARN_EMPTY_BODY = YES;
+                                CLANG_WARN_ENUM_CONVERSION = YES;
+                                CLANG_WARN_INT_CONVERSION = YES;
+                                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                                CLANG_WARN_UNREACHABLE_CODE = YES;
+                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                                COPY_PHASE_STRIP = NO;
+                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                                ENABLE_NS_ASSERTIONS = NO;
+                                ENABLE_STRICT_OBJC_MSGSEND = YES;
+                                GCC_C_LANGUAGE_STANDARD = gnu99;
+                                GCC_NO_COMMON_BLOCKS = YES;
+                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                                GCC_WARN_UNDECLARED_SELECTOR = YES;
+                                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                                GCC_WARN_UNUSED_FUNCTION = YES;
+                                GCC_WARN_UNUSED_VARIABLE = YES;
+                                MACOSX_DEPLOYMENT_TARGET = 10.11;
+                                MTL_ENABLE_DEBUG_INFO = NO;
+                                SDKROOT = macosx;
+                        };
+                        name = Release;
+                };
+                C28626AA1BA902B9001961D6 /* Debug */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                        };
+                        name = Debug;
+                };
+                C28626AB1BA902B9001961D6 /* Release */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                        };
+                        name = Release;
+                };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+                C286269D1BA902B9001961D6 /* Build configuration list for PBXProject "FontWithFeatures" */ = {
+                        isa = XCConfigurationList;
+                        buildConfigurations = (
+                                C28626A71BA902B9001961D6 /* Debug */,
+                                C28626A81BA902B9001961D6 /* Release */,
+                        );
+                        defaultConfigurationIsVisible = 0;
+                        defaultConfigurationName = Release;
+                };
+                C28626A91BA902B9001961D6 /* Build configuration list for PBXNativeTarget "FontWithFeatures" */ = {
+                        isa = XCConfigurationList;
+                        buildConfigurations = (
+                                C28626AA1BA902B9001961D6 /* Debug */,
+                                C28626AB1BA902B9001961D6 /* Release */,
+                        );
+                        defaultConfigurationIsVisible = 0;
+                };
+/* End XCConfigurationList section */
+        };
+        rootObject = C286269A1BA902B9001961D6 /* Project object */;
+}
</ins></span></pre>
</div>
</div>
</body>
</html>