Title: [193577] branches/safari-601-branch

Diff

Modified: branches/safari-601-branch/LayoutTests/ChangeLog (193576 => 193577)


--- branches/safari-601-branch/LayoutTests/ChangeLog	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/LayoutTests/ChangeLog	2015-12-06 10:37:09 UTC (rev 193577)
@@ -1,3 +1,18 @@
+2015-12-06  Matthew Hanson  <matthew_han...@apple.com>
+
+        Merge r190697. rdar://problem/23769789
+
+    2015-10-07  Myles C. Maxfield  <mmaxfi...@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.
+
 2015-09-23  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [Cocoa] [Font Features] Implement font-variant-*

Modified: branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html (193576 => 193577)


--- branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2-expected.html	2015-12-06 10:37:09 UTC (rev 193577)
@@ -6,6 +6,10 @@
     font-family: "FontFeaturesTest";
     src: url("resources/FontWithFeatures.otf") format("opentype");
 }
+@font-face {
+    font-family: "FontFeaturesTestTTF";
+    src: url("resources/FontWithFeatures.ttf") format("truetype");
+}
 </style>
 </head>
 <body>
@@ -43,5 +47,39 @@
 <span style="font-family: FontFeaturesTest;">BA</span>
 <span style="font-family: FontFeaturesTest;">BA</span>
 </div>
+<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>
 </body>
 </html>

Modified: branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html (193576 => 193577)


--- branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/LayoutTests/css3/font-feature-settings-rendering-2.html	2015-12-06 10:37:09 UTC (rev 193577)
@@ -6,56 +6,97 @@
     font-family: "FontFeaturesTest";
     src: url("resources/FontWithFeatures.otf") format("opentype");
 }
+@font-face {
+    font-family: "FontFeaturesTestTTF";
+    src: url("resources/FontWithFeatures.ttf") format("truetype");
+}
 </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>
+<div id="insertionPoint"></div>
+<div id="insertionPoint2"></div>
 <script>
-var insertionpoint = document.getElementById("insertionpoint");
-function addElement(feature, c) {
+var insertionPoint = document.getElementById("insertionPoint");
+var insertionPoint2 = document.getElementById("insertionPoint2");
+function addElement(placeToInsert, familyName, feature, c) {
     ["0", "1"].map(function(state) {
         var element = document.createElement("span");
         element.textContent = c;
-        element.style.fontFamily = "FontFeaturesTest";
+        element.style.fontFamily = familyName;
         element.style.fontFeatureSettings = '"' + feature + '" ' + state;
-        insertionpoint.appendChild(element);
+        placeToInsert.appendChild(element);
     });
-    insertionpoint.appendChild(document.createTextNode(" "));
+    placeToInsert.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("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");
+
+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");
 </script>
 </body>
 </html>

Added: branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.ttf (0 => 193577)


--- branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.ttf	                        (rev 0)
+++ branches/safari-601-branch/LayoutTests/css3/resources/FontWithFeatures.ttf	2015-12-06 10:37:09 UTC (rev 193577)
@@ -0,0 +1,24 @@
+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\xC3a\xB0\xFF+N+\x9D+\xEC;\x8A\xD9(w\xC65\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF5.D\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFFD\xFF\xFF\xFF\xFF	D\xFF\xFF\xFF\xFF
+D\xFF\xFF\xFF\xFFD$\xFF\xFF\xFF\xFFD$\xFF\xFF\xFF\xFF+D
+c\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD
+\xFF\xFF\xFF\xFFD%c\xFF\xFF\xFF\xFFD%\xFF\xFF\xFF\xFFD%\xFF\xFF\xFF\xFFD&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
\ No newline at end of file

Modified: branches/safari-601-branch/Tools/ChangeLog (193576 => 193577)


--- branches/safari-601-branch/Tools/ChangeLog	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/Tools/ChangeLog	2015-12-06 10:37:09 UTC (rev 193577)
@@ -1,3 +1,102 @@
+2015-12-06  Matthew Hanson  <matthew_han...@apple.com>
+
+        Merge r190697. rdar://problem/23769789
+
+    2015-10-07  Myles C. Maxfield  <mmaxfi...@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.
+
 2015-09-23  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [Cocoa] [Font Features] Implement font-variant-*

Modified: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp (193576 => 193577)


--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp	2015-12-06 10:37:09 UTC (rev 193577)
@@ -82,7 +82,6 @@
 }
 
 static const char rLineTo = 0x05;
-static const char rrCurveTo = 0x08;
 static const char endChar = 0x0e;
 static const char rMoveTo = 0x15;
 
@@ -102,14 +101,9 @@
         return std::move(result);
     }
 
-    void moveTo(std::pair<float, float> targetPoint, bool closed)
+    void moveTo(std::pair<float, float> targetPoint)
     {
-        if (closed && !result.empty())
-            closePath();
-
-        std::pair<float, float> destination = targetPoint;
-
-        writePoint(destination);
+        writePoint(targetPoint);
         result.push_back(rMoveTo);
 
         startingPoint = current;
@@ -117,24 +111,10 @@
 
     void lineTo(std::pair<float, float> targetPoint)
     {
-        std::pair<float, float> destination = targetPoint;
-
-        writePoint(destination);
+        writePoint(targetPoint);
         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)
@@ -156,10 +136,94 @@
     std::pair<float, float> current;
 };
 
+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>
 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);
+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(200.f, 200.f));
     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));
@@ -167,10 +231,11 @@
     return builder.takeResult();
 }
 
+template <typename T>
 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);
+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(200.f, 500.f));
     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));
@@ -180,10 +245,11 @@
     return builder.takeResult();
 }
 
+template <typename T>
 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);
+    T builder(unitsPerEm, std::make_pair(0.f, 0.f));
+    builder.moveTo(std::make_pair(500.0f, 550.0f));
     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));
@@ -199,7 +265,8 @@
     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)
+template<typename T>
+const T& itemForGlyph(uint16_t glyph, const T& boxCharString, const T& checkCharString, const T& xCharString)
 {
     if (!glyph)
         return boxCharString;
@@ -208,18 +275,43 @@
     return xCharString;
 }
 
+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;
+};
+
 class Generator {
 public:
-    std::vector<uint8_t> generate()
+    std::vector<uint8_t> generate(Type type)
     {
-        uint16_t numTables = 10;
+        featureDescription = generateFeatureDescription();
+
+        uint16_t numTables = type == Type::OpenType ? 10 : 12;
         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');
+        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');
+        }
         append16(numTables);
         append16(searchRange);
         append16(integralLog2(roundedNumTables)); // entrySelector: "Log2(maximum power of 2 <= numTables)."
@@ -231,15 +323,25 @@
         for (size_t i = 0; i < directoryEntrySize * numTables; ++i)
             result.push_back(0);
 
-        appendTable("CFF ", &Generator::appendCFFTable);
-        appendTable("GSUB", &Generator::appendGSUBTable);
+        if (type == Type::OpenType) {
+            appendTable("CFF ", &Generator::appendCFFTable);
+            appendTable("GSUB", &Generator::appendGSUBTable);
+        }
         appendTable("OS/2", &Generator::appendOS2Table);
         appendTable("cmap", &Generator::appendCMAPTable);
+        if (type == Type::TrueType) {
+            appendTable("feat", &Generator::appendFEATTable);
+            appendTable("glyf", &Generator::appendGLYFTable);
+        }
         auto headTableOffset = result.size();
         appendTable("head", &Generator::appendHEADTable);
         appendTable("hhea", &Generator::appendHHEATable);
         appendTable("hmtx", &Generator::appendHMTXTable);
+        if (type == Type::TrueType)
+            appendTable("loca", &Generator::appendLOCATable);
         appendTable("maxp", &Generator::appendMAXPTable);
+        if (type == Type::TrueType)
+            appendTable("morx", &Generator::appendMORXTable);
         appendTable("name", &Generator::appendNAMETable);
         appendTable("post", &Generator::appendPOSTTable);
 
@@ -248,6 +350,7 @@
         // 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);
     }
 
@@ -331,6 +434,132 @@
         result[location + 2] = value >> 8;
         result[location + 3] = value;
     }
+
+    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;
+    }
     
     void appendCFFTable()
     {
@@ -418,9 +647,9 @@
             append16(i);
 
         // CharStrings INDEX
-        std::vector<uint8_t> boxCharString = generateBoxCharString();
-        std::vector<uint8_t> checkCharString = generateCheckCharString();
-        std::vector<uint8_t> xCharString = generateXCharString();
+        std::vector<uint8_t> boxCharString = generateBoxCharString<CFFBuilder>();
+        std::vector<uint8_t> checkCharString = generateCheckCharString<CFFBuilder>();
+        std::vector<uint8_t> xCharString = generateXCharString<CFFBuilder>();
         assert(numGlyphs > 26);
         overwrite32(charstringsOffsetLocation, static_cast<uint32_t>(result.size() - startingOffset));
         append16(numGlyphs);
@@ -428,15 +657,134 @@
         offset = 1;
         append32(offset);
         for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) {
-            offset += charStringForGlyph(glyph, boxCharString, checkCharString, xCharString).size();
+            offset += itemForGlyph(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);
+            const std::vector<uint8_t>& charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString);
             result.insert(result.end(), charString.begin(), charString.end());
         }
     }
 
+    // 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);
+    }
+
     void appendSubstitutionSubtable(size_t subtableRecordLocation, uint16_t iGetReplaced, uint16_t replacedWithMe)
     {
         overwrite16(subtableRecordLocation + 6, result.size() - subtableRecordLocation);
@@ -677,7 +1025,7 @@
         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(1); // Long offsets in the 'loca' table.
         append16(0); // Glyph data format
     }
     
@@ -705,8 +1053,8 @@
     void appendHMTXTable()
     {
         for (unsigned i = 0; i < numGlyphs; ++i) {
-            append16(clampTo<uint16_t>(unitsPerEm)); // horizontal advance
-            append16(clampTo<int16_t>(0)); // left side bearing
+            append16(clampTo<uint16_t>(static_cast<int32_t>(unitsPerEm))); // horizontal advance
+            append16(itemForGlyph(i, 200, 200, 50)); // left side bearing
         }
     }
     
@@ -728,25 +1076,47 @@
         append16(numGlyphs); // Maximum number of glyphs referenced at top level
         append16(0); // No compound glyphs
     }
-    
-    void appendNAMETable()
+
+    void appendNameSubtable(const std::string& s, uint16_t nameIdentifier)
     {
-        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
+        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
+    }
 
-        for (auto codeUnit : fontName)
+    void append2ByteASCIIString(std::string& s)
+    {
+        for (auto codeUnit : s)
             append16(codeUnit);
     }
+
+    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);
+        }
+    }
     
     void appendPOSTTable()
     {
@@ -796,10 +1166,14 @@
     }
 
     unsigned m_tablesAppendedCount { 0 };
+    unsigned m_nameOffset { 0 };
+    static constexpr uint16_t m_baseStringIndex { 257 };
+    uint16_t m_stringIndex { 0 };
+    std::vector<FeatureType> featureDescription;
     std::vector<uint8_t> result;
 };
 
-std::vector<uint8_t> generateFont()
+std::vector<uint8_t> generateFont(Type type)
 {
-    return Generator().generate();
+    return Generator().generate(type);
 }

Modified: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h (193576 => 193577)


--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h	2015-12-06 10:37:09 UTC (rev 193577)
@@ -28,6 +28,11 @@
 
 #include <vector>
 
-std::vector<uint8_t> generateFont();
+enum class Type {
+    OpenType,
+    TrueType
+};
 
+std::vector<uint8_t> generateFont(Type);
+
 #endif /* FontCreator_h */

Modified: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp (193576 => 193577)


--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures/main.cpp	2015-12-06 10:37:09 UTC (rev 193577)
@@ -32,12 +32,32 @@
 #include <ImageIO/ImageIO.h>
 #include <fstream>
 
-void drawTextWithFeature(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value, CGPoint location)
+static CTFontDescriptorRef constructFontWithTrueTypeFeature(CTFontDescriptorRef fontDescriptor, int type, int selector)
 {
-    CGFloat fontSize = 25;
-    CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
-    CGContextSetTextPosition(context, location.x, location.y);
+    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);
 
+    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)
+{
     CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
     CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
     CFTypeRef featureDictionaryValues[] = { feature, featureValue };
@@ -55,14 +75,20 @@
 
     CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes);
     CFRelease(fontDescriptorAttributes);
+    return modifiedFontDescriptor;
+}
 
-    CTFontRef font = CTFontCreateWithFontDescriptor(modifiedFontDescriptor, fontSize, nullptr);
-    CFRelease(modifiedFontDescriptor);
+static void drawText(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef prefix, CGPoint location)
+{
+    CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
+    CGContextSetTextPosition(context, location.x, location.y);
 
+    CGFloat fontSize = 25;
+    CTFontRef font = CTFontCreateWithFontDescriptor(fontDescriptor, fontSize, nullptr);
+
     CFMutableStringRef string = CFStringCreateMutable(kCFAllocatorDefault, 0);
-    CFStringAppend(string, feature);
-    CFStringAppend(string, value ? CFSTR("  (on)") : CFSTR(" (off)"));
-    CFStringAppend(string, CFSTR(": ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
+    CFStringAppend(string, prefix);
+    CFStringAppend(string, CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
 
     CGColorRef red = CGColorCreateGenericRGB(1, 0, 0, 1);
     CFTypeRef lineKeys[] = { kCTForegroundColorAttributeName };
@@ -72,16 +98,16 @@
 
     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);
+    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, CFStringGetLength(prefix)), kCTFontAttributeName, monospaceFont);
     CFRelease(monospaceFont);
 
-    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(12, 52), kCTFontAttributeName, font);
+    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(CFStringGetLength(prefix), CFStringGetLength(string) - CFStringGetLength(prefix)), kCTFontAttributeName, font);
+    CFRelease(string);
     CFRelease(font);
 
     CTLineRef line = CTLineCreateWithAttributedString(mutableAttributedString);
@@ -93,13 +119,14 @@
 
 int main(int argc, const char * argv[])
 {
-    size_t width = 2000;
+    size_t width = 2500;
     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);
+    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);
     for (uint8_t b : fontVector)
         outputFile << b;
     outputFile.close();
@@ -108,15 +135,85 @@
     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);
+    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);
 
-    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));
+        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"));
     }
 
-    CFRelease(features);
     CFRelease(fontDescriptor);
     CGImageRef image = CGBitmapContextCreateImage(context);
     CGContextRelease(context);

Modified: branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj (193576 => 193577)


--- branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj	2015-12-06 10:37:05 UTC (rev 193576)
+++ branches/safari-601-branch/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj	2015-12-06 10:37:09 UTC (rev 193577)
@@ -186,7 +186,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				_ONLY_ACTIVE_ARCH_ = YES;
 				SDKROOT = macosx;
@@ -222,7 +222,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = macosx;
 			};
@@ -261,6 +261,7 @@
 				C28626AB1BA902B9001961D6 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
 	};
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to