<!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>[190697] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/190697">190697</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2015-10-07 17:33:55 -0700 (Wed, 07 Oct 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Test font-variant-* and font-feature-settings with TrueType fonts
https://bugs.webkit.org/show_bug.cgi?id=149776
Reviewed by Simon Fraser.
Tools:
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 -> 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 "A" always is a check mark.
The letter "B" 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
"kLowerCaseType / kLowerCaseSmallCapsSelector" is enabled, "S" 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.
LayoutTests:
* css3/font-feature-settings-rendering-2-expected.html:
* css3/font-feature-settings-rendering-2.html:
* css3/resources/FontWithFeatures.ttf: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestscss3fontfeaturesettingsrendering2expectedhtml">trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html</a></li>
<li><a href="#trunkLayoutTestscss3fontfeaturesettingsrendering2html">trunk/LayoutTests/css3/font-feature-settings-rendering-2.html</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp">trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp</a></li>
<li><a href="#trunkToolsFontWithFeaturesFontWithFeaturesFontCreatorh">trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h</a></li>
<li><a href="#trunkToolsFontWithFeaturesFontWithFeaturesmaincpp">trunk/Tools/FontWithFeatures/FontWithFeatures/main.cpp</a></li>
<li><a href="#trunkToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj">trunk/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestscss3resourcesFontWithFeaturesttf">trunk/LayoutTests/css3/resources/FontWithFeatures.ttf</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/LayoutTests/ChangeLog        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-10-07 Myles C. Maxfield <mmaxfield@apple.com>
+
+ 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.
+
</ins><span class="cx"> 2015-10-07 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Disable tail calls because it is breaking some sites.
</span></span></pre></div>
<a id="trunkLayoutTestscss3fontfeaturesettingsrendering2expectedhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -6,6 +6,10 @@
</span><span class="cx"> font-family: "FontFeaturesTest";
</span><span class="cx"> src: url("resources/FontWithFeatures.otf") format("opentype");
</span><span class="cx"> }
</span><ins>+@font-face {
+ font-family: "FontFeaturesTestTTF";
+ src: url("resources/FontWithFeatures.ttf") format("truetype");
+}
</ins><span class="cx"> </style>
</span><span class="cx"> </head>
</span><span class="cx"> <body>
</span><span class="lines">@@ -43,5 +47,39 @@
</span><span class="cx"> <span style="font-family: FontFeaturesTest;">BA</span>
</span><span class="cx"> <span style="font-family: FontFeaturesTest;">BA</span>
</span><span class="cx"> </div>
</span><ins>+<div><span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+<span style="font-family: FontFeaturesTestTTF;">BA</span>
+</div>
</ins><span class="cx"> </body>
</span><span class="cx"> </html>
</span></span></pre></div>
<a id="trunkLayoutTestscss3fontfeaturesettingsrendering2html"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/css3/font-feature-settings-rendering-2.html (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/css3/font-feature-settings-rendering-2.html        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/LayoutTests/css3/font-feature-settings-rendering-2.html        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -6,56 +6,97 @@
</span><span class="cx"> font-family: "FontFeaturesTest";
</span><span class="cx"> src: url("resources/FontWithFeatures.otf") format("opentype");
</span><span class="cx"> }
</span><ins>+@font-face {
+ font-family: "FontFeaturesTestTTF";
+ src: url("resources/FontWithFeatures.ttf") format("truetype");
+}
</ins><span class="cx"> </style>
</span><span class="cx"> </head>
</span><span class="cx"> <body>
</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>-<div id="insertionpoint"></div>
</del><ins>+<div id="insertionPoint"></div>
+<div id="insertionPoint2"></div>
</ins><span class="cx"> <script>
</span><del>-var insertionpoint = document.getElementById("insertionpoint");
-function addElement(feature, c) {
</del><ins>+var insertionPoint = document.getElementById("insertionPoint");
+var insertionPoint2 = document.getElementById("insertionPoint2");
+function addElement(placeToInsert, familyName, feature, c) {
</ins><span class="cx"> ["0", "1"].map(function(state) {
</span><span class="cx"> var element = document.createElement("span");
</span><span class="cx"> element.textContent = c;
</span><del>- element.style.fontFamily = "FontFeaturesTest";
</del><ins>+ element.style.fontFamily = familyName;
</ins><span class="cx"> element.style.fontFeatureSettings = '"' + feature + '" ' + state;
</span><del>- insertionpoint.appendChild(element);
</del><ins>+ placeToInsert.appendChild(element);
</ins><span class="cx"> });
</span><del>- insertionpoint.appendChild(document.createTextNode(" "));
</del><ins>+ placeToInsert.appendChild(document.createTextNode(" "));
</ins><span class="cx"> }
</span><del>-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("lnum", "P");
-addElement("onum", "Q");
-addElement("pnum", "R");
-addElement("tnum", "S");
-addElement("frac", "T");
-//addElement("afrc", "U");
-addElement("ordn", "V");
-addElement("zero", "W");
-addElement("hist", "X");
-addElement("jp78", "Y");
-addElement("jp83", "Z");
-addElement("jp90", "a");
-addElement("jp04", "b");
-addElement("smpl", "c");
-addElement("trad", "d");
-addElement("fwid", "e");
-addElement("pwid", "f");
-addElement("ruby", "g");
</del><ins>+
+addElement(insertionPoint, "FontFeaturesTest", "liga", "C");
+addElement(insertionPoint, "FontFeaturesTest", "clig", "D");
+addElement(insertionPoint, "FontFeaturesTest", "dlig", "E");
+addElement(insertionPoint, "FontFeaturesTest", "hlig", "F");
+addElement(insertionPoint, "FontFeaturesTest", "calt", "G");
+addElement(insertionPoint, "FontFeaturesTest", "subs", "H");
+addElement(insertionPoint, "FontFeaturesTest", "sups", "I");
+addElement(insertionPoint, "FontFeaturesTest", "smcp", "J");
+addElement(insertionPoint, "FontFeaturesTest", "c2sc", "K");
+addElement(insertionPoint, "FontFeaturesTest", "pcap", "L");
+addElement(insertionPoint, "FontFeaturesTest", "c2pc", "M");
+addElement(insertionPoint, "FontFeaturesTest", "unic", "N");
+addElement(insertionPoint, "FontFeaturesTest", "titl", "O");
+addElement(insertionPoint, "FontFeaturesTest", "lnum", "P");
+addElement(insertionPoint, "FontFeaturesTest", "onum", "Q");
+addElement(insertionPoint, "FontFeaturesTest", "pnum", "R");
+addElement(insertionPoint, "FontFeaturesTest", "tnum", "S");
+addElement(insertionPoint, "FontFeaturesTest", "frac", "T");
+//addElement(insertionPoint, "FontFeaturesTest", "afrc", "U");
+addElement(insertionPoint, "FontFeaturesTest", "ordn", "V");
+addElement(insertionPoint, "FontFeaturesTest", "zero", "W");
+addElement(insertionPoint, "FontFeaturesTest", "hist", "X");
+addElement(insertionPoint, "FontFeaturesTest", "jp78", "Y");
+addElement(insertionPoint, "FontFeaturesTest", "jp83", "Z");
+addElement(insertionPoint, "FontFeaturesTest", "jp90", "a");
+addElement(insertionPoint, "FontFeaturesTest", "jp04", "b");
+addElement(insertionPoint, "FontFeaturesTest", "smpl", "c");
+addElement(insertionPoint, "FontFeaturesTest", "trad", "d");
+addElement(insertionPoint, "FontFeaturesTest", "fwid", "e");
+addElement(insertionPoint, "FontFeaturesTest", "pwid", "f");
+addElement(insertionPoint, "FontFeaturesTest", "ruby", "g");
+
+addElement(insertionPoint2, "FontFeaturesTestTTF", "liga", "C");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "liga", "D");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "clig", "C");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "clig", "D");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "dlig", "G");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "hlig", "I");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "calt", "L");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "subs", "O");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "sups", "P");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "smcp", "S");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "c2sc", "V");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "pcap", "T");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "c2pc", "W");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "unic", "Y");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "titl", "a");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "lnum", "c");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "onum", "d");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "pnum", "f");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "tnum", "g");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "frac", "i");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "afrc", "j");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "ordn", "Q");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "zero", "k");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "hist", "K");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "jp78", "m");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "jp83", "n");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "jp90", "o");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "jp04", "p");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "smpl", "q");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "trad", "r");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "fwid", "t");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "pwid", "u");
+addElement(insertionPoint2, "FontFeaturesTestTTF", "ruby", "v");
</ins><span class="cx"> </script>
</span><span class="cx"> </body>
</span><span class="cx"> </html>
</span></span></pre></div>
<a id="trunkLayoutTestscss3resourcesFontWithFeaturesttf"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/css3/resources/FontWithFeatures.ttf (0 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/css3/resources/FontWithFeatures.ttf         (rev 0)
+++ trunk/LayoutTests/css3/resources/FontWithFeatures.ttf        2015-10-08 00:33:55 UTC (rev 190697)
</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&Zz\xFF\xFFAa\xFF\xFF\xFF\xDA\xFF\xA0        \xB4$\xD8
+
+\xE0\x80+%\xF0\x80&\xFC\x80\x80\x80\x80$\x80#0\x80'<,@\x80/\\x807h;        .c+ccccc !"c$%&c()*-c0123456c89:<\xC8\xC8 \xC8X\xFD\xA8\xC8X\xFD\xA8\xC8\xC8\xB6\xBC\xC82\xFA\x902\xFE>\xFE\xD4\xF42\xFF\x90\xFF\xCE\xFE>,22\xB6\xB6\xF4\x902\xFEp\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x90&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\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&\x90\xFF\xCE\xFEp\xFEp\xFF\xCE\x90\xFEp2\x
90\x902\xFEpZ2M_<\xF5f5\xC8\xC8222222222222222222222222222222222222222222222222222'X\xA7\xF6E\x94\xE32\x81\xD0n\xBD[\xAA\xF9H\x97\xE65\x84\xD3"q\xC0^\xAD\xFC        K        \x9A        \xE9
+8
+\x87
+\xD6%t\xC3a\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\xFFD$\xFF\xFF\xFF\xFFD$\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&c\xFF\xFF\xFF\xFFD&\xFF\xFF\xFF\xFFD&\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!Dc\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\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!":#l$\x90%\xBA&\xF2'&(B)l*\xA0,\xD4-/,0R1|2\xB03\xE44        5        L6        \x867        \xC28        \xE29
+:
+:;
+l<
+\x86MylesFontkLigaturesTypekCommonLigaturesOnSelectorkContextualLigaturesOnSelectorkCommonLigaturesOffSelectorkContextualLigaturesOffSelectorkRareLigaturesOnSelectorkRareLigaturesOffSelectorkHistoricalLigaturesOnSelectorkHistoricalLigaturesOffSelectorkHistoricalLigaturesOnSelectorkContextualAlternatesTypekContextualAlternatesOnSelectorkContextualAlternatesOffSelectorkVerticalPositionTypedefaultUnusedSelectorkInferiorsSelectorkSuperiorsSelectorkOrdinalsSelectorkLowerCaseTypedefaultUnusedSelec
torkLowerCaseSmallCapsSelectorkLowerCasePetiteCapsSelectorkUpperCaseTypedefaultUnusedSelectorkUpperCaseSmallCapsSelectorkUpperCasePetiteCapsSelectorkLetterCaseTypedefaultUnusedSelector14kStyleOptionsTypedefaultUnusedSelectorkTitlingCapsSelectorkNumberCaseTypedefaultUnusedSelectorkUpperCaseNumbersSelectorkLowerCaseNumbersSelectorkNumberSpacingTypedefaultUnusedSelectorkProportionalNumbersSelectorkMonospacedNumbersSelectorkFractionsTypedefaultUnusedSelectorkDiagonalFractionsSelectorkVerticalFr
actionsSelectorkTypographicExtrasTypekSlashedZeroOnSelectorkCharacterShapeTypedefaultUnusedSelectorkJIS1978CharactersSelectorkJIS1983CharactersSelectorkJIS1990CharactersSelectorkJIS2004CharactersSelectorkSimplifiedCharactersSelectorkTraditionalCharactersSelectorkTextSpacingTypedefaultUnusedSelectorkMonospacedTextSelectorkProportionalTextSelectorkRubyKanaTypekRubyKanaOnSelector
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/Tools/ChangeLog        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -1,3 +1,98 @@
</span><ins>+2015-10-07 Myles C. Maxfield <mmaxfield@apple.com>
+
+ 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 -> 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 "A" always is a check mark.
+ The letter "B" 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
+ "kLowerCaseType / kLowerCaseSmallCapsSelector" is enabled, "S" 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.
+
</ins><span class="cx"> 2015-10-07 Commit Queue <commit-queue@webkit.org>
</span><span class="cx">
</span><span class="cx"> Unreviewed, rolling out r190572, r190593, r190594, and
</span></span></pre></div>
<a id="trunkToolsFontWithFeaturesFontWithFeaturesFontCreatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp        2015-10-08 00:33:55 UTC (rev 190697)
</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<float, float> targetPoint, bool closed)
</del><ins>+ void moveTo(std::pair<float, float> targetPoint)
</ins><span class="cx"> {
</span><del>- if (closed && !result.empty())
- closePath();
-
- std::pair<float, float> 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<float, float> targetPoint)
</span><span class="cx"> {
</span><del>- std::pair<float, float> 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<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);
- }
-
</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<float, float> current;
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+class GLYFBuilder {
+public:
+ GLYFBuilder(float, std::pair<float, float>)
+ {
+ }
+
+ std::vector<uint8_t> takeResult()
+ {
+ std::vector<uint8_t> result;
+ append16(result, endPtsOfContours.size());
+ append16(result, clampTo<int16_t>(minX));
+ append16(result, clampTo<int16_t>(minY));
+ append16(result, clampTo<int16_t>(maxX));
+ append16(result, clampTo<int16_t>(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<float, float> targetPoint)
+ {
+ writePoint(targetPoint, true);
+
+ startingPoint = current;
+ }
+
+ void lineTo(std::pair<float, float> targetPoint)
+ {
+ writePoint(targetPoint, true);
+ }
+
+ void closePath()
+ {
+ if (current != startingPoint)
+ lineTo(startingPoint);
+ endPtsOfContours.push_back(pointCount - 1);
+ }
+
+private:
+ void writePoint(std::pair<float, float> destination, bool onCurve)
+ {
+ flags.push_back(onCurve ? 1 : 0); // Flags
+
+ std::pair<float, float> 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<uint8_t>& destination, uint16_t value)
+ {
+ destination.push_back(value >> 8);
+ destination.push_back(value);
+ }
+
+ std::vector<uint16_t> endPtsOfContours;
+ std::vector<uint8_t> flags;
+ std::vector<int16_t> xCoordinates;
+ std::vector<int16_t> yCoordinates;
+ std::pair<float, float> startingPoint;
+ std::pair<float, float> current;
+ float minX { std::numeric_limits<float>::max() };
+ float maxX { std::numeric_limits<float>::min() };
+ float minY { std::numeric_limits<float>::max() };
+ float maxY { std::numeric_limits<float>::min() };
+ unsigned pointCount { 0 };
+};
+
+template <typename T>
</ins><span class="cx"> std::vector<uint8_t> 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 <typename T>
</ins><span class="cx"> std::vector<uint8_t> 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 <typename T>
</ins><span class="cx"> std::vector<uint8_t> 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<uint8_t>& charStringForGlyph(uint16_t glyph, std::vector<uint8_t>& boxCharString, std::vector<uint8_t>& checkCharString, std::vector<uint8_t>& xCharString)
</del><ins>+template<typename T>
+const T& itemForGlyph(uint16_t glyph, const T& boxCharString, const T& checkCharString, const T& 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<FeatureSelector> selectors;
+ bool exclusive;
+};
+
</ins><span class="cx"> class Generator {
</span><span class="cx"> public:
</span><del>- std::vector<uint8_t> generate()
</del><ins>+ std::vector<uint8_t> 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: "(Maximum power of 2 <= numTables) x 16."
</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: "Log2(maximum power of 2 <= numTables)."
</span><span class="lines">@@ -231,15 +323,25 @@
</span><span class="cx"> for (size_t i = 0; i < directoryEntrySize * numTables; ++i)
</span><span class="cx"> result.push_back(0);
</span><span class="cx">
</span><del>- appendTable("CFF ", &Generator::appendCFFTable);
- appendTable("GSUB", &Generator::appendGSUBTable);
</del><ins>+ if (type == Type::OpenType) {
+ appendTable("CFF ", &Generator::appendCFFTable);
+ appendTable("GSUB", &Generator::appendGSUBTable);
+ }
</ins><span class="cx"> appendTable("OS/2", &Generator::appendOS2Table);
</span><span class="cx"> appendTable("cmap", &Generator::appendCMAPTable);
</span><ins>+ if (type == Type::TrueType) {
+ appendTable("feat", &Generator::appendFEATTable);
+ appendTable("glyf", &Generator::appendGLYFTable);
+ }
</ins><span class="cx"> auto headTableOffset = result.size();
</span><span class="cx"> appendTable("head", &Generator::appendHEADTable);
</span><span class="cx"> appendTable("hhea", &Generator::appendHHEATable);
</span><span class="cx"> appendTable("hmtx", &Generator::appendHMTXTable);
</span><ins>+ if (type == Type::TrueType)
+ appendTable("loca", &Generator::appendLOCATable);
</ins><span class="cx"> appendTable("maxp", &Generator::appendMAXPTable);
</span><ins>+ if (type == Type::TrueType)
+ appendTable("morx", &Generator::appendMORXTable);
</ins><span class="cx"> appendTable("name", &Generator::appendNAMETable);
</span><span class="cx"> appendTable("post", &Generator::appendPOSTTable);
</span><span class="cx">
</span><span class="lines">@@ -248,6 +350,7 @@
</span><span class="cx"> // checksumAdjustment: "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."
</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 >> 8;
</span><span class="cx"> result[location + 3] = value;
</span><span class="cx"> }
</span><ins>+
+ void insertSelector(std::vector<FeatureSelector>& selectors, uint16_t selector, std::string selectorString, bool defaultSelector)
+ {
+ selectors.push_back({selector, selectorString, m_stringIndex++, defaultSelector});
+ }
+
+ void insertFeature(std::vector<FeatureType>& 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 < 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<FeatureSelector>(), 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<FeatureType> generateFeatureDescription()
+ {
+ std::vector<FeatureType> result;
+
+ // For any given feature type, the first selector inside it is the default selector for that type.
+ insertFeature(result, kLigaturesType, "kLigaturesType", kCommonLigaturesOnSelector, "kCommonLigaturesOnSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kContextualLigaturesOnSelector, "kContextualLigaturesOnSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kCommonLigaturesOffSelector, "kCommonLigaturesOffSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kContextualLigaturesOffSelector, "kContextualLigaturesOffSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kRareLigaturesOnSelector, "kRareLigaturesOnSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kRareLigaturesOffSelector, "kRareLigaturesOffSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOnSelector, "kHistoricalLigaturesOnSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOffSelector, "kHistoricalLigaturesOffSelector", false);
+ insertFeature(result, kContextualAlternatesType, "kContextualAlternatesType", kContextualAlternatesOnSelector, "kContextualAlternatesOnSelector", false);
+ insertFeature(result, kContextualAlternatesType, "kContextualAlternatesType", kContextualAlternatesOffSelector, "kContextualAlternatesOffSelector", false);
+ insertFeature(result, kVerticalPositionType, "kVerticalPositionType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kInferiorsSelector, "kInferiorsSelector", true);
+ insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kSuperiorsSelector, "kSuperiorsSelector", true);
+ insertFeature(result, kLowerCaseType, "kLowerCaseType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kUpperCaseType, "kUpperCaseType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kLowerCaseType, "kLowerCaseType", kLowerCaseSmallCapsSelector, "kLowerCaseSmallCapsSelector", true);
+ insertFeature(result, kUpperCaseType, "kUpperCaseType", kUpperCaseSmallCapsSelector, "kUpperCaseSmallCapsSelector", true);
+ insertFeature(result, kLowerCaseType, "kLowerCaseType", kLowerCasePetiteCapsSelector, "kLowerCasePetiteCapsSelector", true);
+ insertFeature(result, kUpperCaseType, "kUpperCaseType", kUpperCasePetiteCapsSelector, "kUpperCasePetiteCapsSelector", true);
+ insertFeature(result, kLetterCaseType, "kLetterCaseType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kLetterCaseType, "kLetterCaseType", 14, "14", true);
+ insertFeature(result, kStyleOptionsType, "kStyleOptionsType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kStyleOptionsType, "kStyleOptionsType", kTitlingCapsSelector, "kTitlingCapsSelector", true);
+ insertFeature(result, kNumberCaseType, "kNumberCaseType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kNumberCaseType, "kNumberCaseType", kUpperCaseNumbersSelector, "kUpperCaseNumbersSelector", true);
+ insertFeature(result, kNumberCaseType, "kNumberCaseType", kLowerCaseNumbersSelector, "kLowerCaseNumbersSelector", true);
+ insertFeature(result, kNumberSpacingType, "kNumberSpacingType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kNumberSpacingType, "kNumberSpacingType", kProportionalNumbersSelector, "kProportionalNumbersSelector", true);
+ insertFeature(result, kNumberSpacingType, "kNumberSpacingType", kMonospacedNumbersSelector, "kMonospacedNumbersSelector", true);
+ insertFeature(result, kFractionsType, "kFractionsType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kFractionsType, "kFractionsType", kDiagonalFractionsSelector, "kDiagonalFractionsSelector", true);
+ insertFeature(result, kFractionsType, "kFractionsType", kVerticalFractionsSelector, "kVerticalFractionsSelector", true);
+ insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kOrdinalsSelector, "kOrdinalsSelector", true);
+ insertFeature(result, kTypographicExtrasType, "kTypographicExtrasType", kSlashedZeroOnSelector, "kSlashedZeroOnSelector", false);
+ insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOnSelector, "kHistoricalLigaturesOnSelector", false);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1978CharactersSelector, "kJIS1978CharactersSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1983CharactersSelector, "kJIS1983CharactersSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1990CharactersSelector, "kJIS1990CharactersSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS2004CharactersSelector, "kJIS2004CharactersSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kSimplifiedCharactersSelector, "kSimplifiedCharactersSelector", true);
+ insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kTraditionalCharactersSelector, "kTraditionalCharactersSelector", true);
+ insertFeature(result, kTextSpacingType, "kTextSpacingType", defaultUnusedSelector, "defaultUnusedSelector", true);
+ insertFeature(result, kTextSpacingType, "kTextSpacingType", kMonospacedTextSelector, "kMonospacedTextSelector", true);
+ insertFeature(result, kTextSpacingType, "kTextSpacingType", kProportionalTextSelector, "kProportionalTextSelector", true);
+ insertFeature(result, kRubyKanaType, "kRubyKanaType", kRubyKanaOnSelector, "kRubyKanaOnSelector", 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<uint8_t> boxCharString = generateBoxCharString();
- std::vector<uint8_t> checkCharString = generateCheckCharString();
- std::vector<uint8_t> xCharString = generateXCharString();
</del><ins>+ std::vector<uint8_t> boxCharString = generateBoxCharString<CFFBuilder>();
+ std::vector<uint8_t> checkCharString = generateCheckCharString<CFFBuilder>();
+ std::vector<uint8_t> xCharString = generateXCharString<CFFBuilder>();
</ins><span class="cx"> assert(numGlyphs > 26);
</span><span class="cx"> overwrite32(charstringsOffsetLocation, static_cast<uint32_t>(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 < 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 < numGlyphs; ++glyph) {
</span><del>- std::vector<uint8_t>& charString = charStringForGlyph(glyph, boxCharString, checkCharString, xCharString);
</del><ins>+ const std::vector<uint8_t>& 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<uint8_t> boxCharString = generateBoxCharString<GLYFBuilder>();
+ std::vector<uint8_t> checkCharString = generateCheckCharString<GLYFBuilder>();
+ std::vector<uint8_t> xCharString = generateXCharString<GLYFBuilder>();
+ for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) {
+ const std::vector<uint8_t>& charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString);
+ result.insert(result.end(), charString.begin(), charString.end());
+ }
+ }
+
+ // Keep in sync with glyf
+ void appendLOCATable()
+ {
+ std::vector<uint8_t> boxCharString = generateBoxCharString<GLYFBuilder>();
+ std::vector<uint8_t> checkCharString = generateCheckCharString<GLYFBuilder>();
+ std::vector<uint8_t> xCharString = generateXCharString<GLYFBuilder>();
+ uint32_t index = 0;
+ for (uint16_t glyph = 0; glyph < 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& 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& type : featureDescription) {
+ overwrite32(type.settingTableOffsetLocation, static_cast<uint32_t>(result.size() - tableLocation));
+ for (FeatureSelector& 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& type, const FeatureSelector& selector, uint16_t glyphToReplace, uint16_t withMe)
+ {
+ size_t chainLocation = result.size();
+ append32(type.exclusive && 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 ("swash") 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<uint32_t>(result.size() - metamorphosisSubtableSizeLocation));
+
+ while (result.size() % 4)
+ result.push_back(0);
+ overwrite32(chainSizeLocation, static_cast<uint32_t>(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& type : featureDescription) {
+ for (FeatureSelector& 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 < numGlyphs; ++i) {
</span><del>- append16(clampTo<uint16_t>(unitsPerEm)); // horizontal advance
- append16(clampTo<int16_t>(0)); // left side bearing
</del><ins>+ append16(clampTo<uint16_t>(static_cast<int32_t>(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& s, uint16_t nameIdentifier)
</ins><span class="cx"> {
</span><del>- 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
-
</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& s)
+ {
+ for (auto codeUnit : s)
</ins><span class="cx"> append16(codeUnit);
</span><span class="cx"> }
</span><ins>+
+ void appendNAMETable()
+ {
+ std::string familyName = "MylesFont"; // 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& type : featureDescription) {
+ appendNameSubtable(type.name, type.stringIndex);
+ for (FeatureSelector& selector : type.selectors)
+ appendNameSubtable(selector.name, selector.stringIndex);
+ }
+
+ append2ByteASCIIString(familyName);
+ for (FeatureType& type : featureDescription) {
+ append2ByteASCIIString(type.name);
+ for (FeatureSelector& 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<FeatureType> featureDescription;
</ins><span class="cx"> std::vector<uint8_t> result;
</span><span class="cx"> };
</span><span class="cx">
</span><del>-std::vector<uint8_t> generateFont()
</del><ins>+std::vector<uint8_t> 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="trunkToolsFontWithFeaturesFontWithFeaturesFontCreatorh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -28,6 +28,11 @@
</span><span class="cx">
</span><span class="cx"> #include <vector>
</span><span class="cx">
</span><del>-std::vector<uint8_t> generateFont();
</del><ins>+enum class Type {
+ OpenType,
+ TrueType
+};
</ins><span class="cx">
</span><ins>+std::vector<uint8_t> generateFont(Type);
+
</ins><span class="cx"> #endif /* FontCreator_h */
</span></span></pre></div>
<a id="trunkToolsFontWithFeaturesFontWithFeaturesmaincpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/FontWithFeatures/FontWithFeatures/main.cpp (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/FontWithFeatures/FontWithFeatures/main.cpp        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/Tools/FontWithFeatures/FontWithFeatures/main.cpp        2015-10-08 00:33:55 UTC (rev 190697)
</span><span class="lines">@@ -32,12 +32,32 @@
</span><span class="cx"> #include <ImageIO/ImageIO.h>
</span><span class="cx"> #include <fstream>
</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, &type);
+ CFNumberRef selectorValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &selector);
+ CFTypeRef featureDictionaryKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey };
+ CFTypeRef featureDictionaryValues[] = { typeValue, selectorValue };
+ CFDictionaryRef featureDictionary = CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFRelease(typeValue);
+ CFRelease(selectorValue);
</ins><span class="cx">
</span><ins>+ 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);
+ return modifiedFontDescriptor;
+}
+
+static CTFontDescriptorRef constructFontWithOpenTypeFeature(CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value)
+{
</ins><span class="cx"> CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &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(" (on)") : CFSTR(" (off)"));
- CFStringAppend(string, CFSTR(": ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
</del><ins>+ CFStringAppend(string, prefix);
+ CFStringAppend(string, CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
</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("Courier"), 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<uint8_t> fontVector = generateFont();
- std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.otf", std::ios::out | std::ios::binary);
</del><ins>+ Type type = Type::TrueType;
+ const std::vector<uint8_t> fontVector = generateFont(type);
+ std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.ttf", std::ios::out | std::ios::binary);
</ins><span class="cx"> for (uint8_t b : fontVector)
</span><span class="cx"> outputFile << 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("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);
</del><ins>+ if (type == Type::OpenType) {
+ CFTypeRef featureValuesOpenType[] = { 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, featureValuesOpenType, 30, &kCFTypeArrayCallBacks);
</ins><span class="cx">
</span><del>- 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));
</del><ins>+ for (CFIndex i = 0; i < CFArrayGetCount(features); ++i) {
+ CFStringRef feature = static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i));
+ CTFontDescriptorRef modifiedFontDescriptor = constructFontWithOpenTypeFeature(fontDescriptor, feature, 1);
+ CFMutableStringRef prefix = CFStringCreateMutable(kCFAllocatorDefault, 0);
+ CFStringAppend(prefix, feature);
+ CFStringAppend(prefix, CFSTR(" (on): "));
+ 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(" (off): "));
+ 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(": "));
+ CFStringAppend(prefix, selectorString);
+ CFStringAppend(prefix, CFSTR(": "));
+ while (CFStringGetLength(prefix) < 65)
+ CFStringAppend(prefix, CFSTR(" "));
+ drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1950 - 40 * i));
+ CFRelease(prefix);
+ CFRelease(modifiedFontDescriptor);
+ ++i;
+ };
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kCommonLigaturesOnSelector, CFSTR("kCommonLigaturesOnSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kContextualLigaturesOnSelector, CFSTR("kContextualLigaturesOnSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kCommonLigaturesOffSelector, CFSTR("kCommonLigaturesOffSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kContextualLigaturesOffSelector, CFSTR("kContextualLigaturesOffSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kRareLigaturesOnSelector, CFSTR("kRareLigaturesOnSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kRareLigaturesOffSelector, CFSTR("kRareLigaturesOffSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOnSelector, CFSTR("kHistoricalLigaturesOnSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOffSelector, CFSTR("kHistoricalLigaturesOffSelector"));
+ handler(kContextualAlternatesType, CFSTR("kContextualAlternatesType"), kContextualAlternatesOnSelector, CFSTR("kContextualAlternatesOnSelector"));
+ handler(kContextualAlternatesType, CFSTR("kContextualAlternatesType"), kContextualAlternatesOffSelector, CFSTR("kContextualAlternatesOffSelector"));
+ handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kInferiorsSelector, CFSTR("kInferiorsSelector"));
+ handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kSuperiorsSelector, CFSTR("kSuperiorsSelector"));
+ handler(kLowerCaseType, CFSTR("kLowerCaseType"), kLowerCaseSmallCapsSelector, CFSTR("kLowerCaseSmallCapsSelector"));
+ handler(kUpperCaseType, CFSTR("kUpperCaseType"), kUpperCaseSmallCapsSelector, CFSTR("kUpperCaseSmallCapsSelector"));
+ handler(kLowerCaseType, CFSTR("kLowerCaseType"), kLowerCasePetiteCapsSelector, CFSTR("kLowerCasePetiteCapsSelector"));
+ handler(kUpperCaseType, CFSTR("kUpperCaseType"), kUpperCasePetiteCapsSelector, CFSTR("kUpperCasePetiteCapsSelector"));
+ handler(kLetterCaseType, CFSTR("kLetterCaseType"), 14, CFSTR("14"));
+ handler(kStyleOptionsType, CFSTR("kStyleOptionsType"), kTitlingCapsSelector, CFSTR("kTitlingCapsSelector"));
+ handler(kNumberCaseType, CFSTR("kNumberCaseType"), kUpperCaseNumbersSelector, CFSTR("kUpperCaseNumbersSelector"));
+ handler(kNumberCaseType, CFSTR("kNumberCaseType"), kLowerCaseNumbersSelector, CFSTR("kLowerCaseNumbersSelector"));
+ handler(kNumberSpacingType, CFSTR("kNumberSpacingType"), kProportionalNumbersSelector, CFSTR("kProportionalNumbersSelector"));
+ handler(kNumberSpacingType, CFSTR("kNumberSpacingType"), kMonospacedNumbersSelector, CFSTR("kMonospacedNumbersSelector"));
+ handler(kFractionsType, CFSTR("kFractionsType"), kDiagonalFractionsSelector, CFSTR("kDiagonalFractionsSelector"));
+ handler(kFractionsType, CFSTR("kFractionsType"), kVerticalFractionsSelector, CFSTR("kVerticalFractionsSelector"));
+ handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kOrdinalsSelector, CFSTR("kOrdinalsSelector"));
+ handler(kTypographicExtrasType, CFSTR("kTypographicExtrasType"), kSlashedZeroOnSelector, CFSTR("kSlashedZeroOnSelector"));
+ handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOnSelector, CFSTR("kHistoricalLigaturesOnSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1978CharactersSelector, CFSTR("kJIS1978CharactersSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1983CharactersSelector, CFSTR("kJIS1983CharactersSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1990CharactersSelector, CFSTR("kJIS1990CharactersSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS2004CharactersSelector, CFSTR("kJIS2004CharactersSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kSimplifiedCharactersSelector, CFSTR("kSimplifiedCharactersSelector"));
+ handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kTraditionalCharactersSelector, CFSTR("kTraditionalCharactersSelector"));
+ handler(kTextSpacingType, CFSTR("kTextSpacingType"), kMonospacedTextSelector, CFSTR("kMonospacedTextSelector"));
+ handler(kTextSpacingType, CFSTR("kTextSpacingType"), kProportionalTextSelector, CFSTR("kProportionalTextSelector"));
+ handler(kRubyKanaType, CFSTR("kRubyKanaType"), kRubyKanaOnSelector, CFSTR("kRubyKanaOnSelector"));
</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="trunkToolsFontWithFeaturesFontWithFeaturesxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj (190696 => 190697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj        2015-10-08 00:17:21 UTC (rev 190696)
+++ trunk/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj        2015-10-08 00:33:55 UTC (rev 190697)
</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>