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\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
\ 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 */
};