Changeset 190697 in webkit
- Timestamp:
- Oct 7, 2015, 5:33:55 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r190695 r190697 1 2015-10-07 Myles C. Maxfield <mmaxfield@apple.com> 2 3 Test font-variant-* and font-feature-settings with TrueType fonts 4 https://bugs.webkit.org/show_bug.cgi?id=149776 5 6 Reviewed by Simon Fraser. 7 8 * css3/font-feature-settings-rendering-2-expected.html: 9 * css3/font-feature-settings-rendering-2.html: 10 * css3/resources/FontWithFeatures.ttf: Added. 11 1 12 2015-10-07 Mark Lam <mark.lam@apple.com> 2 13 -
trunk/LayoutTests/css3/font-feature-settings-rendering-2-expected.html
r190192 r190697 6 6 font-family: "FontFeaturesTest"; 7 7 src: url("resources/FontWithFeatures.otf") format("opentype"); 8 } 9 @font-face { 10 font-family: "FontFeaturesTestTTF"; 11 src: url("resources/FontWithFeatures.ttf") format("truetype"); 8 12 } 9 13 </style> … … 44 48 <span style="font-family: FontFeaturesTest;">BA</span> 45 49 </div> 50 <div><span style="font-family: FontFeaturesTestTTF;">BA</span> 51 <span style="font-family: FontFeaturesTestTTF;">BA</span> 52 <span style="font-family: FontFeaturesTestTTF;">BA</span> 53 <span style="font-family: FontFeaturesTestTTF;">BA</span> 54 <span style="font-family: FontFeaturesTestTTF;">BA</span> 55 <span style="font-family: FontFeaturesTestTTF;">BA</span> 56 <span style="font-family: FontFeaturesTestTTF;">BA</span> 57 <span style="font-family: FontFeaturesTestTTF;">BA</span> 58 <span style="font-family: FontFeaturesTestTTF;">BA</span> 59 <span style="font-family: FontFeaturesTestTTF;">BA</span> 60 <span style="font-family: FontFeaturesTestTTF;">BA</span> 61 <span style="font-family: FontFeaturesTestTTF;">BA</span> 62 <span style="font-family: FontFeaturesTestTTF;">BA</span> 63 <span style="font-family: FontFeaturesTestTTF;">BA</span> 64 <span style="font-family: FontFeaturesTestTTF;">BA</span> 65 <span style="font-family: FontFeaturesTestTTF;">BA</span> 66 <span style="font-family: FontFeaturesTestTTF;">BA</span> 67 <span style="font-family: FontFeaturesTestTTF;">BA</span> 68 <span style="font-family: FontFeaturesTestTTF;">BA</span> 69 <span style="font-family: FontFeaturesTestTTF;">BA</span> 70 <span style="font-family: FontFeaturesTestTTF;">BA</span> 71 <span style="font-family: FontFeaturesTestTTF;">BA</span> 72 <span style="font-family: FontFeaturesTestTTF;">BA</span> 73 <span style="font-family: FontFeaturesTestTTF;">BA</span> 74 <span style="font-family: FontFeaturesTestTTF;">BA</span> 75 <span style="font-family: FontFeaturesTestTTF;">BA</span> 76 <span style="font-family: FontFeaturesTestTTF;">BA</span> 77 <span style="font-family: FontFeaturesTestTTF;">BA</span> 78 <span style="font-family: FontFeaturesTestTTF;">BA</span> 79 <span style="font-family: FontFeaturesTestTTF;">BA</span> 80 <span style="font-family: FontFeaturesTestTTF;">BA</span> 81 <span style="font-family: FontFeaturesTestTTF;">BA</span> 82 <span style="font-family: FontFeaturesTestTTF;">BA</span> 83 </div> 46 84 </body> 47 85 </html> -
trunk/LayoutTests/css3/font-feature-settings-rendering-2.html
r190564 r190697 7 7 src: url("resources/FontWithFeatures.otf") format("opentype"); 8 8 } 9 @font-face { 10 font-family: "FontFeaturesTestTTF"; 11 src: url("resources/FontWithFeatures.ttf") format("truetype"); 12 } 9 13 </style> 10 14 </head> … … 13 17 designed specifically for this purpose. The test passes if you see a sequence of alternating check 14 18 marks and X below. 15 <div id="insertionpoint"></div> 19 <div id="insertionPoint"></div> 20 <div id="insertionPoint2"></div> 16 21 <script> 17 var insertionpoint = document.getElementById("insertionpoint"); 18 function addElement(feature, c) { 22 var insertionPoint = document.getElementById("insertionPoint"); 23 var insertionPoint2 = document.getElementById("insertionPoint2"); 24 function addElement(placeToInsert, familyName, feature, c) { 19 25 ["0", "1"].map(function(state) { 20 26 var element = document.createElement("span"); 21 27 element.textContent = c; 22 element.style.fontFamily = "FontFeaturesTest";28 element.style.fontFamily = familyName; 23 29 element.style.fontFeatureSettings = '"' + feature + '" ' + state; 24 insertionpoint.appendChild(element);30 placeToInsert.appendChild(element); 25 31 }); 26 insertionpoint.appendChild(document.createTextNode(" "));32 placeToInsert.appendChild(document.createTextNode(" ")); 27 33 } 28 addElement("liga", "C"); 29 addElement("clig", "D"); 30 addElement("dlig", "E"); 31 addElement("hlig", "F"); 32 addElement("calt", "G"); 33 addElement("subs", "H"); 34 addElement("sups", "I"); 35 addElement("smcp", "J"); 36 addElement("c2sc", "K"); 37 addElement("pcap", "L"); 38 addElement("c2pc", "M"); 39 addElement("unic", "N"); 40 addElement("titl", "O"); 41 addElement("lnum", "P"); 42 addElement("onum", "Q"); 43 addElement("pnum", "R"); 44 addElement("tnum", "S"); 45 addElement("frac", "T"); 46 //addElement("afrc", "U"); 47 addElement("ordn", "V"); 48 addElement("zero", "W"); 49 addElement("hist", "X"); 50 addElement("jp78", "Y"); 51 addElement("jp83", "Z"); 52 addElement("jp90", "a"); 53 addElement("jp04", "b"); 54 addElement("smpl", "c"); 55 addElement("trad", "d"); 56 addElement("fwid", "e"); 57 addElement("pwid", "f"); 58 addElement("ruby", "g"); 34 35 addElement(insertionPoint, "FontFeaturesTest", "liga", "C"); 36 addElement(insertionPoint, "FontFeaturesTest", "clig", "D"); 37 addElement(insertionPoint, "FontFeaturesTest", "dlig", "E"); 38 addElement(insertionPoint, "FontFeaturesTest", "hlig", "F"); 39 addElement(insertionPoint, "FontFeaturesTest", "calt", "G"); 40 addElement(insertionPoint, "FontFeaturesTest", "subs", "H"); 41 addElement(insertionPoint, "FontFeaturesTest", "sups", "I"); 42 addElement(insertionPoint, "FontFeaturesTest", "smcp", "J"); 43 addElement(insertionPoint, "FontFeaturesTest", "c2sc", "K"); 44 addElement(insertionPoint, "FontFeaturesTest", "pcap", "L"); 45 addElement(insertionPoint, "FontFeaturesTest", "c2pc", "M"); 46 addElement(insertionPoint, "FontFeaturesTest", "unic", "N"); 47 addElement(insertionPoint, "FontFeaturesTest", "titl", "O"); 48 addElement(insertionPoint, "FontFeaturesTest", "lnum", "P"); 49 addElement(insertionPoint, "FontFeaturesTest", "onum", "Q"); 50 addElement(insertionPoint, "FontFeaturesTest", "pnum", "R"); 51 addElement(insertionPoint, "FontFeaturesTest", "tnum", "S"); 52 addElement(insertionPoint, "FontFeaturesTest", "frac", "T"); 53 //addElement(insertionPoint, "FontFeaturesTest", "afrc", "U"); 54 addElement(insertionPoint, "FontFeaturesTest", "ordn", "V"); 55 addElement(insertionPoint, "FontFeaturesTest", "zero", "W"); 56 addElement(insertionPoint, "FontFeaturesTest", "hist", "X"); 57 addElement(insertionPoint, "FontFeaturesTest", "jp78", "Y"); 58 addElement(insertionPoint, "FontFeaturesTest", "jp83", "Z"); 59 addElement(insertionPoint, "FontFeaturesTest", "jp90", "a"); 60 addElement(insertionPoint, "FontFeaturesTest", "jp04", "b"); 61 addElement(insertionPoint, "FontFeaturesTest", "smpl", "c"); 62 addElement(insertionPoint, "FontFeaturesTest", "trad", "d"); 63 addElement(insertionPoint, "FontFeaturesTest", "fwid", "e"); 64 addElement(insertionPoint, "FontFeaturesTest", "pwid", "f"); 65 addElement(insertionPoint, "FontFeaturesTest", "ruby", "g"); 66 67 addElement(insertionPoint2, "FontFeaturesTestTTF", "liga", "C"); 68 addElement(insertionPoint2, "FontFeaturesTestTTF", "liga", "D"); 69 addElement(insertionPoint2, "FontFeaturesTestTTF", "clig", "C"); 70 addElement(insertionPoint2, "FontFeaturesTestTTF", "clig", "D"); 71 addElement(insertionPoint2, "FontFeaturesTestTTF", "dlig", "G"); 72 addElement(insertionPoint2, "FontFeaturesTestTTF", "hlig", "I"); 73 addElement(insertionPoint2, "FontFeaturesTestTTF", "calt", "L"); 74 addElement(insertionPoint2, "FontFeaturesTestTTF", "subs", "O"); 75 addElement(insertionPoint2, "FontFeaturesTestTTF", "sups", "P"); 76 addElement(insertionPoint2, "FontFeaturesTestTTF", "smcp", "S"); 77 addElement(insertionPoint2, "FontFeaturesTestTTF", "c2sc", "V"); 78 addElement(insertionPoint2, "FontFeaturesTestTTF", "pcap", "T"); 79 addElement(insertionPoint2, "FontFeaturesTestTTF", "c2pc", "W"); 80 addElement(insertionPoint2, "FontFeaturesTestTTF", "unic", "Y"); 81 addElement(insertionPoint2, "FontFeaturesTestTTF", "titl", "a"); 82 addElement(insertionPoint2, "FontFeaturesTestTTF", "lnum", "c"); 83 addElement(insertionPoint2, "FontFeaturesTestTTF", "onum", "d"); 84 addElement(insertionPoint2, "FontFeaturesTestTTF", "pnum", "f"); 85 addElement(insertionPoint2, "FontFeaturesTestTTF", "tnum", "g"); 86 addElement(insertionPoint2, "FontFeaturesTestTTF", "frac", "i"); 87 addElement(insertionPoint2, "FontFeaturesTestTTF", "afrc", "j"); 88 addElement(insertionPoint2, "FontFeaturesTestTTF", "ordn", "Q"); 89 addElement(insertionPoint2, "FontFeaturesTestTTF", "zero", "k"); 90 addElement(insertionPoint2, "FontFeaturesTestTTF", "hist", "K"); 91 addElement(insertionPoint2, "FontFeaturesTestTTF", "jp78", "m"); 92 addElement(insertionPoint2, "FontFeaturesTestTTF", "jp83", "n"); 93 addElement(insertionPoint2, "FontFeaturesTestTTF", "jp90", "o"); 94 addElement(insertionPoint2, "FontFeaturesTestTTF", "jp04", "p"); 95 addElement(insertionPoint2, "FontFeaturesTestTTF", "smpl", "q"); 96 addElement(insertionPoint2, "FontFeaturesTestTTF", "trad", "r"); 97 addElement(insertionPoint2, "FontFeaturesTestTTF", "fwid", "t"); 98 addElement(insertionPoint2, "FontFeaturesTestTTF", "pwid", "u"); 99 addElement(insertionPoint2, "FontFeaturesTestTTF", "ruby", "v"); 59 100 </script> 60 101 </body> -
trunk/Tools/ChangeLog
r190689 r190697 1 2015-10-07 Myles C. Maxfield <mmaxfield@apple.com> 2 3 Test font-variant-* and font-feature-settings with TrueType fonts 4 https://bugs.webkit.org/show_bug.cgi?id=149776 5 6 Reviewed by Simon Fraser. 7 8 This test extends our existing FontWithFeatures project to be able to generate a 9 TrueType font. This font is conceptually similar as the existing OpenType font, 10 except the feature -> character mapping is different. 11 12 The font itself only supports the following characters: 13 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 14 However, the shape of these letters are either an X or a check mark. 15 The letter "A" always is a check mark. 16 The letter "B" always is an X. 17 Each font feature has an letter associated with it. When the font feature is enabled, 18 that letter is shown as a check mark. For example, when 19 "kLowerCaseType / kLowerCaseSmallCapsSelector" is enabled, "S" is shown as a check 20 mark. 21 22 Here are the mappings of font features to letters: 23 kLigaturesType / kCommonLigaturesOnSelector: C 24 kLigaturesType / kContextualLigaturesOnSelector: D 25 kLigaturesType / kRareLigaturesOnSelector: G 26 kLigaturesType / kHistoricalLigaturesOnSelector: I 27 kContextualAlternatesType / kContextualAlternatesOnSelector: L 28 kVerticalPositionType / kInferiorsSelector: O 29 kVerticalPositionType / kSuperiorsSelector: P 30 kLowerCaseType / kLowerCaseSmallCapsSelector: S 31 kUpperCaseType / kUpperCaseSmallCapsSelector: V 32 kLowerCaseType / kLowerCasePetiteCapsSelector: T 33 kUpperCaseType / kUpperCasePetiteCapsSelector: W 34 kLetterCaseType / 14: Y 35 kStyleOptionsType / kTitlingCapsSelector: a 36 kNumberCaseType / kUpperCaseNumbersSelector: c 37 kNumberCaseType / kLowerCaseNumbersSelector: d 38 kNumberSpacingType / kProportionalNumbersSelector: f 39 kNumberSpacingType / kMonospacedNumbersSelector: g 40 kFractionsType / kDiagonalFractionsSelector: i 41 kFractionsType / kVerticalFractionsSelector: j 42 kVerticalPositionType / kOrdinalsSelector: Q 43 kTypographicExtrasType / kSlashedZeroOnSelector: k 44 kLigaturesType / kHistoricalLigaturesOnSelector: K 45 kCharacterShapeType / kJIS1978CharactersSelector: m 46 kCharacterShapeType / kJIS1983CharactersSelector: n 47 kCharacterShapeType / kJIS1990CharactersSelector: o 48 kCharacterShapeType / kJIS2004CharactersSelector: p 49 kCharacterShapeType / kSimplifiedCharactersSelector: q 50 kCharacterShapeType / kTraditionalCharactersSelector: r 51 kTextSpacingType / kMonospacedTextSelector: t 52 kTextSpacingType / kProportionalTextSelector: u 53 kRubyKanaType / kRubyKanaOnSelector: v 54 55 * FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj: 56 * FontWithFeatures/FontWithFeatures/FontCreator.cpp: 57 (CFFBuilder::moveTo): 58 (CFFBuilder::lineTo): 59 (GLYFBuilder::GLYFBuilder): 60 (GLYFBuilder::takeResult): 61 (GLYFBuilder::moveTo): 62 (GLYFBuilder::lineTo): 63 (GLYFBuilder::closePath): 64 (GLYFBuilder::writePoint): 65 (GLYFBuilder::append16): 66 (generateBoxCharString): 67 (generateCheckCharString): 68 (generateXCharString): 69 (itemForGlyph): 70 (Generator::generate): 71 (Generator::insertSelector): 72 (Generator::insertFeature): 73 (Generator::generateFeatureDescription): 74 (Generator::appendCFFTable): 75 (Generator::appendGLYFTable): 76 (Generator::appendLOCATable): 77 (Generator::appendFEATTable): 78 (Generator::appendMetamorphosisChain): 79 (Generator::appendMORXTable): 80 (Generator::appendHEADTable): 81 (Generator::appendHMTXTable): 82 (Generator::appendNameSubtable): 83 (Generator::append2ByteASCIIString): 84 (Generator::appendNAMETable): 85 (generateFont): 86 (CFFBuilder::curveToCubic): Deleted. 87 (charStringForGlyph): Deleted. 88 * FontWithFeatures/FontWithFeatures/FontCreator.h: 89 * FontWithFeatures/FontWithFeatures/main.cpp: 90 (constructFontWithTrueTypeFeature): 91 (constructFontWithOpenTypeFeature): 92 (drawText): 93 (main): 94 (drawTextWithFeature): Deleted. 95 1 96 2015-10-07 Commit Queue <commit-queue@webkit.org> 2 97 -
trunk/Tools/FontWithFeatures/FontWithFeatures.xcodeproj/project.pbxproj
r189890 r190697 187 187 GCC_WARN_UNUSED_FUNCTION = YES; 188 188 GCC_WARN_UNUSED_VARIABLE = YES; 189 MACOSX_DEPLOYMENT_TARGET = 10.1 1;189 MACOSX_DEPLOYMENT_TARGET = 10.10; 190 190 MTL_ENABLE_DEBUG_INFO = YES; 191 191 ONLY_ACTIVE_ARCH = YES; … … 223 223 GCC_WARN_UNUSED_FUNCTION = YES; 224 224 GCC_WARN_UNUSED_VARIABLE = YES; 225 MACOSX_DEPLOYMENT_TARGET = 10.1 1;225 MACOSX_DEPLOYMENT_TARGET = 10.10; 226 226 MTL_ENABLE_DEBUG_INFO = NO; 227 227 SDKROOT = macosx; … … 262 262 ); 263 263 defaultConfigurationIsVisible = 0; 264 defaultConfigurationName = Release; 264 265 }; 265 266 /* End XCConfigurationList section */ -
trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.cpp
r190192 r190697 83 83 84 84 static const char rLineTo = 0x05; 85 static const char rrCurveTo = 0x08;86 85 static const char endChar = 0x0e; 87 86 static const char rMoveTo = 0x15; … … 103 102 } 104 103 105 void moveTo(std::pair<float, float> targetPoint, bool closed) 106 { 107 if (closed && !result.empty()) 108 closePath(); 109 110 std::pair<float, float> destination = targetPoint; 111 112 writePoint(destination); 104 void moveTo(std::pair<float, float> targetPoint) 105 { 106 writePoint(targetPoint); 113 107 result.push_back(rMoveTo); 114 108 … … 118 112 void lineTo(std::pair<float, float> targetPoint) 119 113 { 120 std::pair<float, float> destination = targetPoint; 121 122 writePoint(destination); 114 writePoint(targetPoint); 123 115 result.push_back(rLineTo); 124 }125 126 void curveToCubic(std::pair<float, float> point1, std::pair<float, float> point2, std::pair<float, float> targetPoint)127 {128 std::pair<float, float> destination1 = point1;129 std::pair<float, float> destination2 = point2;130 std::pair<float, float> destination3 = targetPoint;131 132 writePoint(destination1);133 writePoint(destination2);134 writePoint(destination3);135 result.push_back(rrCurveTo);136 116 } 137 117 … … 157 137 }; 158 138 139 class GLYFBuilder { 140 public: 141 GLYFBuilder(float, std::pair<float, float>) 142 { 143 } 144 145 std::vector<uint8_t> takeResult() 146 { 147 std::vector<uint8_t> result; 148 append16(result, endPtsOfContours.size()); 149 append16(result, clampTo<int16_t>(minX)); 150 append16(result, clampTo<int16_t>(minY)); 151 append16(result, clampTo<int16_t>(maxX)); 152 append16(result, clampTo<int16_t>(maxY)); 153 154 for (uint16_t p : endPtsOfContours) 155 append16(result, p); 156 append16(result, 0); 157 for (uint8_t f : flags) 158 result.push_back(f); 159 for (uint16_t c : xCoordinates) 160 append16(result, c); 161 for (uint16_t c : yCoordinates) 162 append16(result, c); 163 164 return result; 165 } 166 167 void moveTo(std::pair<float, float> targetPoint) 168 { 169 writePoint(targetPoint, true); 170 171 startingPoint = current; 172 } 173 174 void lineTo(std::pair<float, float> targetPoint) 175 { 176 writePoint(targetPoint, true); 177 } 178 179 void closePath() 180 { 181 if (current != startingPoint) 182 lineTo(startingPoint); 183 endPtsOfContours.push_back(pointCount - 1); 184 } 185 186 private: 187 void writePoint(std::pair<float, float> destination, bool onCurve) 188 { 189 flags.push_back(onCurve ? 1 : 0); // Flags 190 191 std::pair<float, float> delta = std::make_pair(destination.first - current.first, destination.second - current.second); 192 xCoordinates.push_back(delta.first); 193 yCoordinates.push_back(delta.second); 194 195 current = destination; 196 minX = std::min(minX, destination.first); 197 maxX = std::max(maxX, destination.first); 198 minY = std::min(minY, destination.second); 199 maxY = std::max(maxY, destination.second); 200 ++pointCount; 201 } 202 203 static void append16(std::vector<uint8_t>& destination, uint16_t value) 204 { 205 destination.push_back(value >> 8); 206 destination.push_back(value); 207 } 208 209 std::vector<uint16_t> endPtsOfContours; 210 std::vector<uint8_t> flags; 211 std::vector<int16_t> xCoordinates; 212 std::vector<int16_t> yCoordinates; 213 std::pair<float, float> startingPoint; 214 std::pair<float, float> current; 215 float minX { std::numeric_limits<float>::max() }; 216 float maxX { std::numeric_limits<float>::min() }; 217 float minY { std::numeric_limits<float>::max() }; 218 float maxY { std::numeric_limits<float>::min() }; 219 unsigned pointCount { 0 }; 220 }; 221 222 template <typename T> 159 223 std::vector<uint8_t> generateBoxCharString() 160 224 { 161 CFFBuilderbuilder(unitsPerEm, std::make_pair(0.f, 0.f));162 builder.moveTo(std::make_pair(200.f, 200.f) , false);225 T builder(unitsPerEm, std::make_pair(0.f, 0.f)); 226 builder.moveTo(std::make_pair(200.f, 200.f)); 163 227 builder.lineTo(std::make_pair(200.f, 800.f)); 164 228 builder.lineTo(std::make_pair(800.f, 800.f)); … … 168 232 } 169 233 234 template <typename T> 170 235 std::vector<uint8_t> generateCheckCharString() 171 236 { 172 CFFBuilderbuilder(unitsPerEm, std::make_pair(0.f, 0.f));173 builder.moveTo(std::make_pair(200.f, 500.f) , false);237 T builder(unitsPerEm, std::make_pair(0.f, 0.f)); 238 builder.moveTo(std::make_pair(200.f, 500.f)); 174 239 builder.lineTo(std::make_pair(250.f, 550.f)); 175 240 builder.lineTo(std::make_pair(500.f, 300.f)); … … 181 246 } 182 247 248 template <typename T> 183 249 std::vector<uint8_t> generateXCharString() 184 250 { 185 CFFBuilderbuilder(unitsPerEm, std::make_pair(0.f, 0.f));186 builder.moveTo(std::make_pair(500.0f, 550.0f) , false);251 T builder(unitsPerEm, std::make_pair(0.f, 0.f)); 252 builder.moveTo(std::make_pair(500.0f, 550.0f)); 187 253 builder.lineTo(std::make_pair(900.f, 950.f)); 188 254 builder.lineTo(std::make_pair(950.f, 900.f)); … … 200 266 } 201 267 202 std::vector<uint8_t>& charStringForGlyph(uint16_t glyph, std::vector<uint8_t>& boxCharString, std::vector<uint8_t>& checkCharString, std::vector<uint8_t>& xCharString) 268 template<typename T> 269 const T& itemForGlyph(uint16_t glyph, const T& boxCharString, const T& checkCharString, const T& xCharString) 203 270 { 204 271 if (!glyph) … … 209 276 } 210 277 278 struct FeatureSelector { 279 uint16_t selector; 280 std::string name; 281 uint16_t stringIndex; 282 bool defaultSelector; 283 }; 284 285 struct FeatureType { 286 uint16_t type; 287 std::string name; 288 uint16_t stringIndex; 289 size_t settingTableOffsetLocation; 290 std::vector<FeatureSelector> selectors; 291 bool exclusive; 292 }; 293 211 294 class Generator { 212 295 public: 213 std::vector<uint8_t> generate() 214 { 215 uint16_t numTables = 10; 296 std::vector<uint8_t> generate(Type type) 297 { 298 featureDescription = generateFeatureDescription(); 299 300 uint16_t numTables = type == Type::OpenType ? 10 : 12; 216 301 uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables); 217 302 uint16_t searchRange = roundedNumTables * 16; // searchRange: "(Maximum power of 2 <= numTables) x 16." 218 303 219 result.push_back('O'); 220 result.push_back('T'); 221 result.push_back('T'); 222 result.push_back('O'); 304 if (type == Type::OpenType) { 305 result.push_back('O'); 306 result.push_back('T'); 307 result.push_back('T'); 308 result.push_back('O'); 309 } else { 310 result.push_back('t'); 311 result.push_back('r'); 312 result.push_back('u'); 313 result.push_back('e'); 314 } 223 315 append16(numTables); 224 316 append16(searchRange); … … 232 324 result.push_back(0); 233 325 234 appendTable("CFF ", &Generator::appendCFFTable); 235 appendTable("GSUB", &Generator::appendGSUBTable); 326 if (type == Type::OpenType) { 327 appendTable("CFF ", &Generator::appendCFFTable); 328 appendTable("GSUB", &Generator::appendGSUBTable); 329 } 236 330 appendTable("OS/2", &Generator::appendOS2Table); 237 331 appendTable("cmap", &Generator::appendCMAPTable); 332 if (type == Type::TrueType) { 333 appendTable("feat", &Generator::appendFEATTable); 334 appendTable("glyf", &Generator::appendGLYFTable); 335 } 238 336 auto headTableOffset = result.size(); 239 337 appendTable("head", &Generator::appendHEADTable); 240 338 appendTable("hhea", &Generator::appendHHEATable); 241 339 appendTable("hmtx", &Generator::appendHMTXTable); 340 if (type == Type::TrueType) 341 appendTable("loca", &Generator::appendLOCATable); 242 342 appendTable("maxp", &Generator::appendMAXPTable); 343 if (type == Type::TrueType) 344 appendTable("morx", &Generator::appendMORXTable); 243 345 appendTable("name", &Generator::appendNAMETable); 244 346 appendTable("post", &Generator::appendPOSTTable); … … 249 351 // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK." 250 352 overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, result.size())); 353 251 354 return std::move(result); 252 355 } … … 331 434 result[location + 2] = value >> 8; 332 435 result[location + 3] = value; 436 } 437 438 void insertSelector(std::vector<FeatureSelector>& selectors, uint16_t selector, std::string selectorString, bool defaultSelector) 439 { 440 selectors.push_back({selector, selectorString, m_stringIndex++, defaultSelector}); 441 } 442 443 void insertFeature(std::vector<FeatureType>& result, uint16_t type, std::string typeString, uint16_t selector, std::string selectorString, bool exclusive) 444 { 445 // O(n) but performance is not an issue here 446 for (size_t i = 0; i < result.size(); ++i) { 447 if (result[i].type == type) { 448 insertSelector(result[i].selectors, selector, selectorString, false); 449 return; 450 } 451 } 452 result.push_back({type, typeString, m_stringIndex++, 0, std::vector<FeatureSelector>(), exclusive}); 453 insertSelector(result[result.size() - 1].selectors, selector, selectorString, true); 454 } 455 456 static const uint16_t kCharacterShapeType = 20; 457 static const uint16_t kContextualAlternatesType = 36; 458 static const uint16_t kFractionsType = 11; 459 static const uint16_t kLetterCaseType = 3; 460 static const uint16_t kLigaturesType = 1; 461 static const uint16_t kLowerCaseType = 37; 462 static const uint16_t kNumberCaseType = 21; 463 static const uint16_t kNumberSpacingType = 6; 464 static const uint16_t kRubyKanaType = 28; 465 static const uint16_t kStyleOptionsType = 19; 466 static const uint16_t kTextSpacingType = 22; 467 static const uint16_t kTypographicExtrasType = 14; 468 static const uint16_t kUpperCaseType = 38; 469 static const uint16_t kVerticalPositionType = 10; 470 471 static const uint16_t kCommonLigaturesOffSelector = 3; 472 static const uint16_t kCommonLigaturesOnSelector = 2; 473 static const uint16_t kContextualAlternatesOffSelector = 1; 474 static const uint16_t kContextualAlternatesOnSelector = 0; 475 static const uint16_t kContextualLigaturesOffSelector = 19; 476 static const uint16_t kContextualLigaturesOnSelector = 18; 477 static const uint16_t kDiagonalFractionsSelector = 2; 478 static const uint16_t kHistoricalLigaturesOffSelector = 21; 479 static const uint16_t kHistoricalLigaturesOnSelector = 20; 480 static const uint16_t kInferiorsSelector = 2; 481 static const uint16_t kJIS1978CharactersSelector = 2; 482 static const uint16_t kJIS1983CharactersSelector = 3; 483 static const uint16_t kJIS1990CharactersSelector = 4; 484 static const uint16_t kJIS2004CharactersSelector = 11; 485 static const uint16_t kLowerCaseNumbersSelector = 0; 486 static const uint16_t kLowerCasePetiteCapsSelector = 2; 487 static const uint16_t kLowerCaseSmallCapsSelector = 1; 488 static const uint16_t kMonospacedNumbersSelector = 0; 489 static const uint16_t kMonospacedTextSelector = 1; 490 static const uint16_t kOrdinalsSelector = 3; 491 static const uint16_t kProportionalNumbersSelector = 1; 492 static const uint16_t kProportionalTextSelector = 0; 493 static const uint16_t kRareLigaturesOffSelector = 5; 494 static const uint16_t kRareLigaturesOnSelector = 4; 495 static const uint16_t kRubyKanaOnSelector = 2; 496 static const uint16_t kRubyKanaSelector = 1; 497 static const uint16_t kSimplifiedCharactersSelector = 1; 498 static const uint16_t kSlashedZeroOnSelector = 4; 499 static const uint16_t kSuperiorsSelector = 1; 500 static const uint16_t kTitlingCapsSelector = 4; 501 static const uint16_t kTraditionalCharactersSelector = 0; 502 static const uint16_t kUpperCaseNumbersSelector = 1; 503 static const uint16_t kUpperCasePetiteCapsSelector = 2; 504 static const uint16_t kUpperCaseSmallCapsSelector = 1; 505 static const uint16_t kVerticalFractionsSelector = 1; 506 507 static const uint16_t defaultUnusedSelector = 99; 508 509 std::vector<FeatureType> generateFeatureDescription() 510 { 511 std::vector<FeatureType> result; 512 513 // For any given feature type, the first selector inside it is the default selector for that type. 514 insertFeature(result, kLigaturesType, "kLigaturesType", kCommonLigaturesOnSelector, "kCommonLigaturesOnSelector", false); 515 insertFeature(result, kLigaturesType, "kLigaturesType", kContextualLigaturesOnSelector, "kContextualLigaturesOnSelector", false); 516 insertFeature(result, kLigaturesType, "kLigaturesType", kCommonLigaturesOffSelector, "kCommonLigaturesOffSelector", false); 517 insertFeature(result, kLigaturesType, "kLigaturesType", kContextualLigaturesOffSelector, "kContextualLigaturesOffSelector", false); 518 insertFeature(result, kLigaturesType, "kLigaturesType", kRareLigaturesOnSelector, "kRareLigaturesOnSelector", false); 519 insertFeature(result, kLigaturesType, "kLigaturesType", kRareLigaturesOffSelector, "kRareLigaturesOffSelector", false); 520 insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOnSelector, "kHistoricalLigaturesOnSelector", false); 521 insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOffSelector, "kHistoricalLigaturesOffSelector", false); 522 insertFeature(result, kContextualAlternatesType, "kContextualAlternatesType", kContextualAlternatesOnSelector, "kContextualAlternatesOnSelector", false); 523 insertFeature(result, kContextualAlternatesType, "kContextualAlternatesType", kContextualAlternatesOffSelector, "kContextualAlternatesOffSelector", false); 524 insertFeature(result, kVerticalPositionType, "kVerticalPositionType", defaultUnusedSelector, "defaultUnusedSelector", true); 525 insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kInferiorsSelector, "kInferiorsSelector", true); 526 insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kSuperiorsSelector, "kSuperiorsSelector", true); 527 insertFeature(result, kLowerCaseType, "kLowerCaseType", defaultUnusedSelector, "defaultUnusedSelector", true); 528 insertFeature(result, kUpperCaseType, "kUpperCaseType", defaultUnusedSelector, "defaultUnusedSelector", true); 529 insertFeature(result, kLowerCaseType, "kLowerCaseType", kLowerCaseSmallCapsSelector, "kLowerCaseSmallCapsSelector", true); 530 insertFeature(result, kUpperCaseType, "kUpperCaseType", kUpperCaseSmallCapsSelector, "kUpperCaseSmallCapsSelector", true); 531 insertFeature(result, kLowerCaseType, "kLowerCaseType", kLowerCasePetiteCapsSelector, "kLowerCasePetiteCapsSelector", true); 532 insertFeature(result, kUpperCaseType, "kUpperCaseType", kUpperCasePetiteCapsSelector, "kUpperCasePetiteCapsSelector", true); 533 insertFeature(result, kLetterCaseType, "kLetterCaseType", defaultUnusedSelector, "defaultUnusedSelector", true); 534 insertFeature(result, kLetterCaseType, "kLetterCaseType", 14, "14", true); 535 insertFeature(result, kStyleOptionsType, "kStyleOptionsType", defaultUnusedSelector, "defaultUnusedSelector", true); 536 insertFeature(result, kStyleOptionsType, "kStyleOptionsType", kTitlingCapsSelector, "kTitlingCapsSelector", true); 537 insertFeature(result, kNumberCaseType, "kNumberCaseType", defaultUnusedSelector, "defaultUnusedSelector", true); 538 insertFeature(result, kNumberCaseType, "kNumberCaseType", kUpperCaseNumbersSelector, "kUpperCaseNumbersSelector", true); 539 insertFeature(result, kNumberCaseType, "kNumberCaseType", kLowerCaseNumbersSelector, "kLowerCaseNumbersSelector", true); 540 insertFeature(result, kNumberSpacingType, "kNumberSpacingType", defaultUnusedSelector, "defaultUnusedSelector", true); 541 insertFeature(result, kNumberSpacingType, "kNumberSpacingType", kProportionalNumbersSelector, "kProportionalNumbersSelector", true); 542 insertFeature(result, kNumberSpacingType, "kNumberSpacingType", kMonospacedNumbersSelector, "kMonospacedNumbersSelector", true); 543 insertFeature(result, kFractionsType, "kFractionsType", defaultUnusedSelector, "defaultUnusedSelector", true); 544 insertFeature(result, kFractionsType, "kFractionsType", kDiagonalFractionsSelector, "kDiagonalFractionsSelector", true); 545 insertFeature(result, kFractionsType, "kFractionsType", kVerticalFractionsSelector, "kVerticalFractionsSelector", true); 546 insertFeature(result, kVerticalPositionType, "kVerticalPositionType", kOrdinalsSelector, "kOrdinalsSelector", true); 547 insertFeature(result, kTypographicExtrasType, "kTypographicExtrasType", kSlashedZeroOnSelector, "kSlashedZeroOnSelector", false); 548 insertFeature(result, kLigaturesType, "kLigaturesType", kHistoricalLigaturesOnSelector, "kHistoricalLigaturesOnSelector", false); 549 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", defaultUnusedSelector, "defaultUnusedSelector", true); 550 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1978CharactersSelector, "kJIS1978CharactersSelector", true); 551 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1983CharactersSelector, "kJIS1983CharactersSelector", true); 552 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS1990CharactersSelector, "kJIS1990CharactersSelector", true); 553 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kJIS2004CharactersSelector, "kJIS2004CharactersSelector", true); 554 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kSimplifiedCharactersSelector, "kSimplifiedCharactersSelector", true); 555 insertFeature(result, kCharacterShapeType, "kCharacterShapeType", kTraditionalCharactersSelector, "kTraditionalCharactersSelector", true); 556 insertFeature(result, kTextSpacingType, "kTextSpacingType", defaultUnusedSelector, "defaultUnusedSelector", true); 557 insertFeature(result, kTextSpacingType, "kTextSpacingType", kMonospacedTextSelector, "kMonospacedTextSelector", true); 558 insertFeature(result, kTextSpacingType, "kTextSpacingType", kProportionalTextSelector, "kProportionalTextSelector", true); 559 insertFeature(result, kRubyKanaType, "kRubyKanaType", kRubyKanaOnSelector, "kRubyKanaOnSelector", false); 560 561 return result; 333 562 } 334 563 … … 419 648 420 649 // CharStrings INDEX 421 std::vector<uint8_t> boxCharString = generateBoxCharString ();422 std::vector<uint8_t> checkCharString = generateCheckCharString ();423 std::vector<uint8_t> xCharString = generateXCharString ();650 std::vector<uint8_t> boxCharString = generateBoxCharString<CFFBuilder>(); 651 std::vector<uint8_t> checkCharString = generateCheckCharString<CFFBuilder>(); 652 std::vector<uint8_t> xCharString = generateXCharString<CFFBuilder>(); 424 653 assert(numGlyphs > 26); 425 654 overwrite32(charstringsOffsetLocation, static_cast<uint32_t>(result.size() - startingOffset)); … … 429 658 append32(offset); 430 659 for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) { 431 offset += charStringForGlyph(glyph, boxCharString, checkCharString, xCharString).size();660 offset += itemForGlyph(glyph, boxCharString, checkCharString, xCharString).size(); 432 661 append32(offset); 433 662 } 434 663 for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) { 435 std::vector<uint8_t>& charString = charStringForGlyph(glyph, boxCharString, checkCharString, xCharString);664 const std::vector<uint8_t>& charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString); 436 665 result.insert(result.end(), charString.begin(), charString.end()); 437 666 } 667 } 668 669 // Keep in sync with loca 670 void appendGLYFTable() 671 { 672 std::vector<uint8_t> boxCharString = generateBoxCharString<GLYFBuilder>(); 673 std::vector<uint8_t> checkCharString = generateCheckCharString<GLYFBuilder>(); 674 std::vector<uint8_t> xCharString = generateXCharString<GLYFBuilder>(); 675 for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) { 676 const std::vector<uint8_t>& charString = itemForGlyph(glyph, boxCharString, checkCharString, xCharString); 677 result.insert(result.end(), charString.begin(), charString.end()); 678 } 679 } 680 681 // Keep in sync with glyf 682 void appendLOCATable() 683 { 684 std::vector<uint8_t> boxCharString = generateBoxCharString<GLYFBuilder>(); 685 std::vector<uint8_t> checkCharString = generateCheckCharString<GLYFBuilder>(); 686 std::vector<uint8_t> xCharString = generateXCharString<GLYFBuilder>(); 687 uint32_t index = 0; 688 for (uint16_t glyph = 0; glyph < numGlyphs; ++glyph) { 689 append32(index); 690 index += itemForGlyph(glyph, boxCharString, checkCharString, xCharString).size(); 691 } 692 append32(index); 693 } 694 695 void appendFEATTable() 696 { 697 size_t tableLocation = result.size(); 698 append32(0x00010000); // Version 699 append16(featureDescription.size()); // Number of entries in the feature name array 700 append16(0); // reserved 701 append32(0); // reserved 702 703 // Feature name array 704 for (FeatureType& type : featureDescription) { 705 append16(type.type); // Feature type 706 append16(type.selectors.size()); // Number of settings 707 type.settingTableOffsetLocation = result.size(); 708 append32(0); // Offset in bytes from beginning of this table to feature's setting name array 709 append16(type.exclusive ? 0x8000 : 0); // Flags. 0x8000 = Exclusive 710 append16(type.stringIndex + m_baseStringIndex); // Index in the name table for the name of this feature 711 } 712 713 // Setting name array 714 for (FeatureType& type : featureDescription) { 715 overwrite32(type.settingTableOffsetLocation, static_cast<uint32_t>(result.size() - tableLocation)); 716 for (FeatureSelector& selector : type.selectors) { 717 append16(selector.selector); // Setting: kNormalPositionSelector (initial setting is default) 718 append16(selector.stringIndex + m_baseStringIndex); // Index in the name table for the name of this setting 719 } 720 } 721 } 722 723 void appendMetamorphosisChain(const FeatureType& type, const FeatureSelector& selector, uint16_t glyphToReplace, uint16_t withMe) 724 { 725 size_t chainLocation = result.size(); 726 append32(type.exclusive && selector.defaultSelector ? 1 : 0); // Default flags 727 size_t chainSizeLocation = result.size(); 728 append32(0); // Placeholder for chain length in bytes (padded to multiple of 4) 729 append32(2); // Number of feature subtable entries 730 append32(1); // Number of subtables in the chain 731 732 // Feature table 733 append16(type.type); // Feature type 734 append16(selector.selector); // Feature selector 735 append32(1); // Enable flags 736 append32(0xFFFFFFFF); // disable flags 737 738 // Feature table 2 739 append16(0); // Feature type: kAllTypographicFeaturesType 740 append16(1); // Feature selector: kAllTypeFeaturesOffSelector 741 append32(0); // Enable flags 742 append32(0); // disable flags 743 744 // Metamorphosis subtable 745 size_t metamorphosisSubtableSizeLocation = result.size(); 746 append32(0); // Placeholder for chain length in bytes (padded to multiple of 4) 747 append32(4); // Coverage flags and subtable type. Subtable type 4: Noncontextual ("swash") subtable 748 append32(1); // subFeature flags 749 750 // Non-contextual glyph substitution subtable 751 append16(6); // Lookup format: sorted list of (glyph index, lookup value) pairs 752 753 // BinSrchHeader 754 append16(4); // Size of a lookup unit for this search in bytes 755 append16(1); // Number of units to be searched 756 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. 757 append16(0); // Entry selector: The log base 2 of the largest power of 2 less than or equal to the value of nUnits. 758 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. 759 // Entries 760 append16(glyphToReplace); 761 append16(withMe); 762 763 overwrite32(metamorphosisSubtableSizeLocation, static_cast<uint32_t>(result.size() - metamorphosisSubtableSizeLocation)); 764 765 while (result.size() % 4) 766 result.push_back(0); 767 overwrite32(chainSizeLocation, static_cast<uint32_t>(result.size() - chainLocation)); 768 } 769 770 void appendMORXTable() 771 { 772 append16(2); // Version 773 append16(0); // Unused 774 size_t numberOfChainsLocation = result.size(); 775 append32(0); // Number of metamorphosis chains placeholder 776 777 int count = 0; 778 for (FeatureType& type : featureDescription) { 779 for (FeatureSelector& selector : type.selectors) { 780 appendMetamorphosisChain(type, selector, count + 3, 1); 781 count++; 782 } 783 } 784 785 overwrite32(numberOfChainsLocation, count); 438 786 } 439 787 … … 678 1026 append16(3); // Smallest readable size in pixels 679 1027 append16(0); // Might contain LTR or RTL glyphs 680 append16( 0); // Short offsets in the 'loca' table. However, OTF fonts don't have a 'loca' table so this is irrelevant1028 append16(1); // Long offsets in the 'loca' table. 681 1029 append16(0); // Glyph data format 682 1030 } … … 706 1054 { 707 1055 for (unsigned i = 0; i < numGlyphs; ++i) { 708 append16(clampTo<uint16_t>( unitsPerEm)); // horizontal advance709 append16( clampTo<int16_t>(0)); // left side bearing1056 append16(clampTo<uint16_t>(static_cast<int32_t>(unitsPerEm))); // horizontal advance 1057 append16(itemForGlyph(i, 200, 200, 50)); // left side bearing 710 1058 } 711 1059 } … … 729 1077 append16(0); // No compound glyphs 730 1078 } 731 732 void appendNAMETable() 733 { 734 std::string fontName = "MylesFont"; 735 736 append16(0); // Format selector 737 append16(1); // Number of name records in table 738 append16(18); // Offset in bytes to the beginning of name character strings 739 1079 1080 void appendNameSubtable(const std::string& s, uint16_t nameIdentifier) 1081 { 740 1082 append16(0); // Unicode 741 1083 append16(3); // Unicode version 2.0 or later 742 1084 append16(0); // Language 743 append16(1); // Name identifier. 1 = Font family 744 append16(fontName.length()); 745 append16(0); // Offset into name data 746 747 for (auto codeUnit : fontName) 1085 append16(m_baseStringIndex + nameIdentifier); // Name identifier 1086 append16(s.length()); 1087 append16(m_nameOffset); // Offset into name data 1088 m_nameOffset += s.size() * 2; // Code units get 2 bytes each 1089 } 1090 1091 void append2ByteASCIIString(std::string& s) 1092 { 1093 for (auto codeUnit : s) 748 1094 append16(codeUnit); 1095 } 1096 1097 void appendNAMETable() 1098 { 1099 std::string familyName = "MylesFont"; // 1: Font Family 1100 1101 uint16_t numberOfRecords = m_stringIndex + 1; 1102 append16(0); // Format selector 1103 append16(numberOfRecords); // Number of name records in table 1104 append16(6 + 12 * numberOfRecords); // Offset in bytes to the beginning of name character strings 1105 1106 appendNameSubtable(familyName, 1); // 1: Font Family 1107 for (FeatureType& type : featureDescription) { 1108 appendNameSubtable(type.name, type.stringIndex); 1109 for (FeatureSelector& selector : type.selectors) 1110 appendNameSubtable(selector.name, selector.stringIndex); 1111 } 1112 1113 append2ByteASCIIString(familyName); 1114 for (FeatureType& type : featureDescription) { 1115 append2ByteASCIIString(type.name); 1116 for (FeatureSelector& selector : type.selectors) 1117 append2ByteASCIIString(selector.name); 1118 } 749 1119 } 750 1120 … … 797 1167 798 1168 unsigned m_tablesAppendedCount { 0 }; 1169 unsigned m_nameOffset { 0 }; 1170 static constexpr uint16_t m_baseStringIndex { 257 }; 1171 uint16_t m_stringIndex { 0 }; 1172 std::vector<FeatureType> featureDescription; 799 1173 std::vector<uint8_t> result; 800 1174 }; 801 1175 802 std::vector<uint8_t> generateFont( )1176 std::vector<uint8_t> generateFont(Type type) 803 1177 { 804 return Generator().generate( );1178 return Generator().generate(type); 805 1179 } -
trunk/Tools/FontWithFeatures/FontWithFeatures/FontCreator.h
r189943 r190697 29 29 #include <vector> 30 30 31 std::vector<uint8_t> generateFont(); 31 enum class Type { 32 OpenType, 33 TrueType 34 }; 35 36 std::vector<uint8_t> generateFont(Type); 32 37 33 38 #endif /* FontCreator_h */ -
trunk/Tools/FontWithFeatures/FontWithFeatures/main.cpp
r189943 r190697 33 33 #include <fstream> 34 34 35 void drawTextWithFeature(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value, CGPoint location) 36 { 37 CGFloat fontSize = 25; 38 CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1)); 39 CGContextSetTextPosition(context, location.x, location.y); 40 35 static CTFontDescriptorRef constructFontWithTrueTypeFeature(CTFontDescriptorRef fontDescriptor, int type, int selector) 36 { 37 CFNumberRef typeValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &type); 38 CFNumberRef selectorValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &selector); 39 CFTypeRef featureDictionaryKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey }; 40 CFTypeRef featureDictionaryValues[] = { typeValue, selectorValue }; 41 CFDictionaryRef featureDictionary = CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 42 CFRelease(typeValue); 43 CFRelease(selectorValue); 44 45 CFTypeRef featureSettingsValues[] = { featureDictionary }; 46 CFArrayRef fontFeatureSettings = CFArrayCreate(kCFAllocatorDefault, featureSettingsValues, 1, &kCFTypeArrayCallBacks); 47 CFRelease(featureDictionary); 48 49 CFTypeRef fontDescriptorKeys[] = { kCTFontFeatureSettingsAttribute }; 50 CFTypeRef fontDescriptorValues[] = { fontFeatureSettings }; 51 CFDictionaryRef fontDescriptorAttributes = CFDictionaryCreate(kCFAllocatorDefault, fontDescriptorKeys, fontDescriptorValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 52 CFRelease(fontFeatureSettings); 53 54 CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes); 55 CFRelease(fontDescriptorAttributes); 56 return modifiedFontDescriptor; 57 } 58 59 static CTFontDescriptorRef constructFontWithOpenTypeFeature(CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value) 60 { 41 61 CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); 42 62 CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue }; … … 56 76 CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes); 57 77 CFRelease(fontDescriptorAttributes); 58 59 CTFontRef font = CTFontCreateWithFontDescriptor(modifiedFontDescriptor, fontSize, nullptr); 60 CFRelease(modifiedFontDescriptor); 78 return modifiedFontDescriptor; 79 } 80 81 static void drawText(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef prefix, CGPoint location) 82 { 83 CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1)); 84 CGContextSetTextPosition(context, location.x, location.y); 85 86 CGFloat fontSize = 25; 87 CTFontRef font = CTFontCreateWithFontDescriptor(fontDescriptor, fontSize, nullptr); 61 88 62 89 CFMutableStringRef string = CFStringCreateMutable(kCFAllocatorDefault, 0); 63 CFStringAppend(string, feature); 64 CFStringAppend(string, value ? CFSTR(" (on)") : CFSTR(" (off)")); 65 CFStringAppend(string, CFSTR(": ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")); 90 CFStringAppend(string, prefix); 91 CFStringAppend(string, CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")); 66 92 67 93 CGColorRef red = CGColorCreateGenericRGB(1, 0, 0, 1); … … 73 99 CFAttributedStringRef attributedString = CFAttributedStringCreate(kCFAllocatorDefault, string, lineAttributes); 74 100 CFRelease(lineAttributes); 75 CFRelease(string);76 101 77 102 CFMutableAttributedStringRef mutableAttributedString = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, attributedString); … … 79 104 80 105 CTFontRef monospaceFont = CTFontCreateWithName(CFSTR("Courier"), fontSize, nullptr); 81 CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, 12), kCTFontAttributeName, monospaceFont);106 CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, CFStringGetLength(prefix)), kCTFontAttributeName, monospaceFont); 82 107 CFRelease(monospaceFont); 83 108 84 CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(12, 52), kCTFontAttributeName, font); 109 CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(CFStringGetLength(prefix), CFStringGetLength(string) - CFStringGetLength(prefix)), kCTFontAttributeName, font); 110 CFRelease(string); 85 111 CFRelease(font); 86 112 … … 94 120 int main(int argc, const char * argv[]) 95 121 { 96 size_t width = 2 000;122 size_t width = 2500; 97 123 size_t height = 2000; 98 124 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 99 125 CGContextRef context = CGBitmapContextCreate(nullptr, width, height, 8, width * 4, colorSpace, kCGImageAlphaNoneSkipLast); 100 126 CGColorSpaceRelease(colorSpace); 101 const std::vector<uint8_t> fontVector = generateFont(); 102 std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.otf", std::ios::out | std::ios::binary); 127 Type type = Type::TrueType; 128 const std::vector<uint8_t> fontVector = generateFont(type); 129 std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.ttf", std::ios::out | std::ios::binary); 103 130 for (uint8_t b : fontVector) 104 131 outputFile << b; … … 109 136 CFRelease(fontData); 110 137 111 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") }; 112 CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValues, 30, &kCFTypeArrayCallBacks); 113 114 for (CFIndex i = 0; i < CFArrayGetCount(features); ++i) { 115 drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 1, CGPointMake(25, 1950 - 50 * i)); 116 drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 0, CGPointMake(25, 1925 - 50 * i)); 138 if (type == Type::OpenType) { 139 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") }; 140 CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValuesOpenType, 30, &kCFTypeArrayCallBacks); 141 142 for (CFIndex i = 0; i < CFArrayGetCount(features); ++i) { 143 CFStringRef feature = static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)); 144 CTFontDescriptorRef modifiedFontDescriptor = constructFontWithOpenTypeFeature(fontDescriptor, feature, 1); 145 CFMutableStringRef prefix = CFStringCreateMutable(kCFAllocatorDefault, 0); 146 CFStringAppend(prefix, feature); 147 CFStringAppend(prefix, CFSTR(" (on): ")); 148 drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1950 - 50 * i)); 149 CFRelease(prefix); 150 CFRelease(modifiedFontDescriptor); 151 152 modifiedFontDescriptor = constructFontWithOpenTypeFeature(fontDescriptor, feature, 0); 153 prefix = CFStringCreateMutable(kCFAllocatorDefault, 0); 154 CFStringAppend(prefix, feature); 155 CFStringAppend(prefix, CFSTR(" (off): ")); 156 drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1925 - 50 * i)); 157 CFRelease(prefix); 158 CFRelease(modifiedFontDescriptor); 159 } 160 161 CFRelease(features); 162 } else { 163 __block int i = 0; 164 void (^handler)(uint16_t type, CFStringRef typeString, uint16_t selector, CFStringRef selectorString) = ^(uint16_t type, CFStringRef typeString, uint16_t selector, CFStringRef selectorString) 165 { 166 CTFontDescriptorRef modifiedFontDescriptor = constructFontWithTrueTypeFeature(fontDescriptor, type, selector); 167 CFMutableStringRef prefix = CFStringCreateMutable(kCFAllocatorDefault, 0); 168 CFStringAppend(prefix, typeString); 169 CFStringAppend(prefix, CFSTR(": ")); 170 CFStringAppend(prefix, selectorString); 171 CFStringAppend(prefix, CFSTR(": ")); 172 while (CFStringGetLength(prefix) < 65) 173 CFStringAppend(prefix, CFSTR(" ")); 174 drawText(context, modifiedFontDescriptor, prefix, CGPointMake(25, 1950 - 40 * i)); 175 CFRelease(prefix); 176 CFRelease(modifiedFontDescriptor); 177 ++i; 178 }; 179 handler(kLigaturesType, CFSTR("kLigaturesType"), kCommonLigaturesOnSelector, CFSTR("kCommonLigaturesOnSelector")); 180 handler(kLigaturesType, CFSTR("kLigaturesType"), kContextualLigaturesOnSelector, CFSTR("kContextualLigaturesOnSelector")); 181 handler(kLigaturesType, CFSTR("kLigaturesType"), kCommonLigaturesOffSelector, CFSTR("kCommonLigaturesOffSelector")); 182 handler(kLigaturesType, CFSTR("kLigaturesType"), kContextualLigaturesOffSelector, CFSTR("kContextualLigaturesOffSelector")); 183 handler(kLigaturesType, CFSTR("kLigaturesType"), kRareLigaturesOnSelector, CFSTR("kRareLigaturesOnSelector")); 184 handler(kLigaturesType, CFSTR("kLigaturesType"), kRareLigaturesOffSelector, CFSTR("kRareLigaturesOffSelector")); 185 handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOnSelector, CFSTR("kHistoricalLigaturesOnSelector")); 186 handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOffSelector, CFSTR("kHistoricalLigaturesOffSelector")); 187 handler(kContextualAlternatesType, CFSTR("kContextualAlternatesType"), kContextualAlternatesOnSelector, CFSTR("kContextualAlternatesOnSelector")); 188 handler(kContextualAlternatesType, CFSTR("kContextualAlternatesType"), kContextualAlternatesOffSelector, CFSTR("kContextualAlternatesOffSelector")); 189 handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kInferiorsSelector, CFSTR("kInferiorsSelector")); 190 handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kSuperiorsSelector, CFSTR("kSuperiorsSelector")); 191 handler(kLowerCaseType, CFSTR("kLowerCaseType"), kLowerCaseSmallCapsSelector, CFSTR("kLowerCaseSmallCapsSelector")); 192 handler(kUpperCaseType, CFSTR("kUpperCaseType"), kUpperCaseSmallCapsSelector, CFSTR("kUpperCaseSmallCapsSelector")); 193 handler(kLowerCaseType, CFSTR("kLowerCaseType"), kLowerCasePetiteCapsSelector, CFSTR("kLowerCasePetiteCapsSelector")); 194 handler(kUpperCaseType, CFSTR("kUpperCaseType"), kUpperCasePetiteCapsSelector, CFSTR("kUpperCasePetiteCapsSelector")); 195 handler(kLetterCaseType, CFSTR("kLetterCaseType"), 14, CFSTR("14")); 196 handler(kStyleOptionsType, CFSTR("kStyleOptionsType"), kTitlingCapsSelector, CFSTR("kTitlingCapsSelector")); 197 handler(kNumberCaseType, CFSTR("kNumberCaseType"), kUpperCaseNumbersSelector, CFSTR("kUpperCaseNumbersSelector")); 198 handler(kNumberCaseType, CFSTR("kNumberCaseType"), kLowerCaseNumbersSelector, CFSTR("kLowerCaseNumbersSelector")); 199 handler(kNumberSpacingType, CFSTR("kNumberSpacingType"), kProportionalNumbersSelector, CFSTR("kProportionalNumbersSelector")); 200 handler(kNumberSpacingType, CFSTR("kNumberSpacingType"), kMonospacedNumbersSelector, CFSTR("kMonospacedNumbersSelector")); 201 handler(kFractionsType, CFSTR("kFractionsType"), kDiagonalFractionsSelector, CFSTR("kDiagonalFractionsSelector")); 202 handler(kFractionsType, CFSTR("kFractionsType"), kVerticalFractionsSelector, CFSTR("kVerticalFractionsSelector")); 203 handler(kVerticalPositionType, CFSTR("kVerticalPositionType"), kOrdinalsSelector, CFSTR("kOrdinalsSelector")); 204 handler(kTypographicExtrasType, CFSTR("kTypographicExtrasType"), kSlashedZeroOnSelector, CFSTR("kSlashedZeroOnSelector")); 205 handler(kLigaturesType, CFSTR("kLigaturesType"), kHistoricalLigaturesOnSelector, CFSTR("kHistoricalLigaturesOnSelector")); 206 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1978CharactersSelector, CFSTR("kJIS1978CharactersSelector")); 207 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1983CharactersSelector, CFSTR("kJIS1983CharactersSelector")); 208 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS1990CharactersSelector, CFSTR("kJIS1990CharactersSelector")); 209 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kJIS2004CharactersSelector, CFSTR("kJIS2004CharactersSelector")); 210 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kSimplifiedCharactersSelector, CFSTR("kSimplifiedCharactersSelector")); 211 handler(kCharacterShapeType, CFSTR("kCharacterShapeType"), kTraditionalCharactersSelector, CFSTR("kTraditionalCharactersSelector")); 212 handler(kTextSpacingType, CFSTR("kTextSpacingType"), kMonospacedTextSelector, CFSTR("kMonospacedTextSelector")); 213 handler(kTextSpacingType, CFSTR("kTextSpacingType"), kProportionalTextSelector, CFSTR("kProportionalTextSelector")); 214 handler(kRubyKanaType, CFSTR("kRubyKanaType"), kRubyKanaOnSelector, CFSTR("kRubyKanaOnSelector")); 117 215 } 118 216 119 CFRelease(features);120 217 CFRelease(fontDescriptor); 121 218 CGImageRef image = CGBitmapContextCreateImage(context);
Note:
See TracChangeset
for help on using the changeset viewer.