/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany * * Sccsid @(#)otf.c 1.68 (gritter) 3/17/10 */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dev.h" #include "afm.h" #ifndef __unused #define __unused __attribute__((unused)) #endif extern struct dev dev; extern char *chname; extern short *chtab; extern int nchtab; extern void errprint(const char *, ...); extern void verrprint(const char *, va_list); static jmp_buf breakpoint; static char *contents; static size_t size; static unsigned short numTables; static int ttf; static const char *filename; unsigned short unitsPerEm; static short xMin, yMin, xMax, yMax; static short indexToLocFormat; static struct afmtab *a; static unsigned long nc; static int fsType; static int WeightClass; static int isFixedPitch; static int minMemType42; static int maxMemType42; static int numGlyphs; static char *PostScript_name; static char *Copyright; static char *Notice; static struct table_directory { char tag[4]; unsigned long checkSum; unsigned long offset; unsigned long length; } *table_directories; static int pos_CFF; static int pos_head; static int pos_hhea; static int pos_loca; static int pos_prep; static int pos_fpgm; static int pos_vhea; static int pos_glyf; static int pos_cvt; static int pos_maxp; static int pos_vmtx; static int pos_hmtx; static int pos_OS_2; static int pos_GSUB; static int pos_GPOS; static int pos_post; static int pos_kern; static int pos_name; static int pos_cmap; static struct table { const char *name; int *pos; int in_sfnts; uint32_t checksum; } tables[] = { { "CFF ", &pos_CFF, 0, 0 }, { "cmap", &pos_cmap, 0, 0 }, { "cvt ", &pos_cvt, 1, 0 }, { "fpgm", &pos_fpgm, 1, 0 }, { "GPOS", &pos_GPOS, 0, 0 }, { "GSUB", &pos_GSUB, 0, 0 }, { "head", &pos_head, 2, 0 }, { "hhea", &pos_hhea, 1, 0 }, { "hmtx", &pos_hmtx, 1, 0 }, { "kern", &pos_kern, 0, 0 }, { "loca", &pos_loca, 1, 0 }, { "maxp", &pos_maxp, 1, 0 }, { "name", &pos_name, 0, 0 }, { "OS/2", &pos_OS_2, 0, 0 }, { "post", &pos_post, 0, 0 }, { "prep", &pos_prep, 1, 0 }, { "vhea", &pos_vhea, 1, 0 }, { "vmtx", &pos_vmtx, 1, 0 }, { "glyf", &pos_glyf, 3, 0 }, /* holds glyph data */ { NULL, NULL, 0, 0 } }; static unsigned short *gid2sid; struct INDEX { unsigned short count; int offSize; int *offset; char *data; }; static struct CFF { struct INDEX *Name; struct INDEX *Top_DICT; struct INDEX *String; struct INDEX *Global_Subr; struct INDEX *CharStrings; int Charset; int baseoffset; } CFF; static const int ExpertCharset[] = { 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378 }; static const int ExpertSubsetCharset[] = { 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346 }; static const char *const StandardStrings[] = { ".notdef", /* 0 */ "space", /* 1 */ "exclam", /* 2 */ "quotedbl", /* 3 */ "numbersign", /* 4 */ "dollar", /* 5 */ "percent", /* 6 */ "ampersand", /* 7 */ "quoteright", /* 8 */ "parenleft", /* 9 */ "parenright", /* 10 */ "asterisk", /* 11 */ "plus", /* 12 */ "comma", /* 13 */ "hyphen", /* 14 */ "period", /* 15 */ "slash", /* 16 */ "zero", /* 17 */ "one", /* 18 */ "two", /* 19 */ "three", /* 20 */ "four", /* 21 */ "five", /* 22 */ "six", /* 23 */ "seven", /* 24 */ "eight", /* 25 */ "nine", /* 26 */ "colon", /* 27 */ "semicolon", /* 28 */ "less", /* 29 */ "equal", /* 30 */ "greater", /* 31 */ "question", /* 32 */ "at", /* 33 */ "A", /* 34 */ "B", /* 35 */ "C", /* 36 */ "D", /* 37 */ "E", /* 38 */ "F", /* 39 */ "G", /* 40 */ "H", /* 41 */ "I", /* 42 */ "J", /* 43 */ "K", /* 44 */ "L", /* 45 */ "M", /* 46 */ "N", /* 47 */ "O", /* 48 */ "P", /* 49 */ "Q", /* 50 */ "R", /* 51 */ "S", /* 52 */ "T", /* 53 */ "U", /* 54 */ "V", /* 55 */ "W", /* 56 */ "X", /* 57 */ "Y", /* 58 */ "Z", /* 59 */ "bracketleft", /* 60 */ "backslash", /* 61 */ "bracketright", /* 62 */ "asciicircum", /* 63 */ "underscore", /* 64 */ "quoteleft", /* 65 */ "a", /* 66 */ "b", /* 67 */ "c", /* 68 */ "d", /* 69 */ "e", /* 70 */ "f", /* 71 */ "g", /* 72 */ "h", /* 73 */ "i", /* 74 */ "j", /* 75 */ "k", /* 76 */ "l", /* 77 */ "m", /* 78 */ "n", /* 79 */ "o", /* 80 */ "p", /* 81 */ "q", /* 82 */ "r", /* 83 */ "s", /* 84 */ "t", /* 85 */ "u", /* 86 */ "v", /* 87 */ "w", /* 88 */ "x", /* 89 */ "y", /* 90 */ "z", /* 91 */ "braceleft", /* 92 */ "bar", /* 93 */ "braceright", /* 94 */ "asciitilde", /* 95 */ "exclamdown", /* 96 */ "cent", /* 97 */ "sterling", /* 98 */ "fraction", /* 99 */ "yen", /* 100 */ "florin", /* 101 */ "section", /* 102 */ "currency", /* 103 */ "quotesingle", /* 104 */ "quotedblleft", /* 105 */ "guillemotleft", /* 106 */ "guilsinglleft", /* 107 */ "guilsinglright", /* 108 */ "fi", /* 109 */ "fl", /* 110 */ "endash", /* 111 */ "dagger", /* 112 */ "daggerdbl", /* 113 */ "periodcentered", /* 114 */ "paragraph", /* 115 */ "bullet", /* 116 */ "quotesinglbase", /* 117 */ "quotedblbase", /* 118 */ "quotedblright", /* 119 */ "guillemotright", /* 120 */ "ellipsis", /* 121 */ "perthousand", /* 122 */ "questiondown", /* 123 */ "grave", /* 124 */ "acute", /* 125 */ "circumflex", /* 126 */ "tilde", /* 127 */ "macron", /* 128 */ "breve", /* 129 */ "dotaccent", /* 130 */ "dieresis", /* 131 */ "ring", /* 132 */ "cedilla", /* 133 */ "hungarumlaut", /* 134 */ "ogonek", /* 135 */ "caron", /* 136 */ "emdash", /* 137 */ "AE", /* 138 */ "ordfeminine", /* 139 */ "Lslash", /* 140 */ "Oslash", /* 141 */ "OE", /* 142 */ "ordmasculine", /* 143 */ "ae", /* 144 */ "dotlessi", /* 145 */ "lslash", /* 146 */ "oslash", /* 147 */ "oe", /* 148 */ "germandbls", /* 149 */ "onesuperior", /* 150 */ "logicalnot", /* 151 */ "mu", /* 152 */ "trademark", /* 153 */ "Eth", /* 154 */ "onehalf", /* 155 */ "plusminus", /* 156 */ "Thorn", /* 157 */ "onequarter", /* 158 */ "divide", /* 159 */ "brokenbar", /* 160 */ "degree", /* 161 */ "thorn", /* 162 */ "threequarters", /* 163 */ "twosuperior", /* 164 */ "registered", /* 165 */ "minus", /* 166 */ "eth", /* 167 */ "multiply", /* 168 */ "threesuperior", /* 169 */ "copyright", /* 170 */ "Aacute", /* 171 */ "Acircumflex", /* 172 */ "Adieresis", /* 173 */ "Agrave", /* 174 */ "Aring", /* 175 */ "Atilde", /* 176 */ "Ccedilla", /* 177 */ "Eacute", /* 178 */ "Ecircumflex", /* 179 */ "Edieresis", /* 180 */ "Egrave", /* 181 */ "Iacute", /* 182 */ "Icircumflex", /* 183 */ "Idieresis", /* 184 */ "Igrave", /* 185 */ "Ntilde", /* 186 */ "Oacute", /* 187 */ "Ocircumflex", /* 188 */ "Odieresis", /* 189 */ "Ograve", /* 190 */ "Otilde", /* 191 */ "Scaron", /* 192 */ "Uacute", /* 193 */ "Ucircumflex", /* 194 */ "Udieresis", /* 195 */ "Ugrave", /* 196 */ "Yacute", /* 197 */ "Ydieresis", /* 198 */ "Zcaron", /* 199 */ "aacute", /* 200 */ "acircumflex", /* 201 */ "adieresis", /* 202 */ "agrave", /* 203 */ "aring", /* 204 */ "atilde", /* 205 */ "ccedilla", /* 206 */ "eacute", /* 207 */ "ecircumflex", /* 208 */ "edieresis", /* 209 */ "egrave", /* 210 */ "iacute", /* 211 */ "icircumflex", /* 212 */ "idieresis", /* 213 */ "igrave", /* 214 */ "ntilde", /* 215 */ "oacute", /* 216 */ "ocircumflex", /* 217 */ "odieresis", /* 218 */ "ograve", /* 219 */ "otilde", /* 220 */ "scaron", /* 221 */ "uacute", /* 222 */ "ucircumflex", /* 223 */ "udieresis", /* 224 */ "ugrave", /* 225 */ "yacute", /* 226 */ "ydieresis", /* 227 */ "zcaron", /* 228 */ "exclamsmall", /* 229 */ "Hungarumlautsmall", /* 230 */ "dollaroldstyle", /* 231 */ "dollarsuperior", /* 232 */ "ampersandsmall", /* 233 */ "Acutesmall", /* 234 */ "parenleftsuperior", /* 235 */ "parenrightsuperior", /* 236 */ "twodotenleader", /* 237 */ "onedotenleader", /* 238 */ "zerooldstyle", /* 239 */ "oneoldstyle", /* 240 */ "twooldstyle", /* 241 */ "threeoldstyle", /* 242 */ "fouroldstyle", /* 243 */ "fiveoldstyle", /* 244 */ "sixoldstyle", /* 245 */ "sevenoldstyle", /* 246 */ "eightoldstyle", /* 247 */ "nineoldstyle", /* 248 */ "commasuperior", /* 249 */ "threequartersemdash", /* 250 */ "periodsuperior", /* 251 */ "questionsmall", /* 252 */ "asuperior", /* 253 */ "bsuperior", /* 254 */ "centsuperior", /* 255 */ "dsuperior", /* 256 */ "esuperior", /* 257 */ "isuperior", /* 258 */ "lsuperior", /* 259 */ "msuperior", /* 260 */ "nsuperior", /* 261 */ "osuperior", /* 262 */ "rsuperior", /* 263 */ "ssuperior", /* 264 */ "tsuperior", /* 265 */ "ff", /* 266 */ "ffi", /* 267 */ "ffl", /* 268 */ "parenleftinferior", /* 269 */ "parenrightinferior", /* 270 */ "Circumflexsmall", /* 271 */ "hyphensuperior", /* 272 */ "Gravesmall", /* 273 */ "Asmall", /* 274 */ "Bsmall", /* 275 */ "Csmall", /* 276 */ "Dsmall", /* 277 */ "Esmall", /* 278 */ "Fsmall", /* 279 */ "Gsmall", /* 280 */ "Hsmall", /* 281 */ "Ismall", /* 282 */ "Jsmall", /* 283 */ "Ksmall", /* 284 */ "Lsmall", /* 285 */ "Msmall", /* 286 */ "Nsmall", /* 287 */ "Osmall", /* 288 */ "Psmall", /* 289 */ "Qsmall", /* 290 */ "Rsmall", /* 291 */ "Ssmall", /* 292 */ "Tsmall", /* 293 */ "Usmall", /* 294 */ "Vsmall", /* 295 */ "Wsmall", /* 296 */ "Xsmall", /* 297 */ "Ysmall", /* 298 */ "Zsmall", /* 299 */ "colonmonetary", /* 300 */ "onefitted", /* 301 */ "rupiah", /* 302 */ "Tildesmall", /* 303 */ "exclamdownsmall", /* 304 */ "centoldstyle", /* 305 */ "Lslashsmall", /* 306 */ "Scaronsmall", /* 307 */ "Zcaronsmall", /* 308 */ "Dieresissmall", /* 309 */ "Brevesmall", /* 310 */ "Caronsmall", /* 311 */ "Dotaccentsmall", /* 312 */ "Macronsmall", /* 313 */ "figuredash", /* 314 */ "hypheninferior", /* 315 */ "Ogoneksmall", /* 316 */ "Ringsmall", /* 317 */ "Cedillasmall", /* 318 */ "questiondownsmall", /* 319 */ "oneeighth", /* 320 */ "threeeighths", /* 321 */ "fiveeighths", /* 322 */ "seveneighths", /* 323 */ "onethird", /* 324 */ "twothirds", /* 325 */ "zerosuperior", /* 326 */ "foursuperior", /* 327 */ "fivesuperior", /* 328 */ "sixsuperior", /* 329 */ "sevensuperior", /* 330 */ "eightsuperior", /* 331 */ "ninesuperior", /* 332 */ "zeroinferior", /* 333 */ "oneinferior", /* 334 */ "twoinferior", /* 335 */ "threeinferior", /* 336 */ "fourinferior", /* 337 */ "fiveinferior", /* 338 */ "sixinferior", /* 339 */ "seveninferior", /* 340 */ "eightinferior", /* 341 */ "nineinferior", /* 342 */ "centinferior", /* 343 */ "dollarinferior", /* 344 */ "periodinferior", /* 345 */ "commainferior", /* 346 */ "Agravesmall", /* 347 */ "Aacutesmall", /* 348 */ "Acircumflexsmall", /* 349 */ "Atildesmall", /* 350 */ "Adieresissmall", /* 351 */ "Aringsmall", /* 352 */ "AEsmall", /* 353 */ "Ccedillasmall", /* 354 */ "Egravesmall", /* 355 */ "Eacutesmall", /* 356 */ "Ecircumflexsmall", /* 357 */ "Edieresissmall", /* 358 */ "Igravesmall", /* 359 */ "Iacutesmall", /* 360 */ "Icircumflexsmall", /* 361 */ "Idieresissmall", /* 362 */ "Ethsmall", /* 363 */ "Ntildesmall", /* 364 */ "Ogravesmall", /* 365 */ "Oacutesmall", /* 366 */ "Ocircumflexsmall", /* 367 */ "Otildesmall", /* 368 */ "Odieresissmall", /* 369 */ "OEsmall", /* 370 */ "Oslashsmall", /* 371 */ "Ugravesmall", /* 372 */ "Uacutesmall", /* 373 */ "Ucircumflexsmall", /* 374 */ "Udieresissmall", /* 375 */ "Yacutesmall", /* 376 */ "Thornsmall", /* 377 */ "Ydieresissmall", /* 378 */ "001.000", /* 379 */ "001.001", /* 380 */ "001.002", /* 381 */ "001.003", /* 382 */ "Black", /* 383 */ "Bold", /* 384 */ "Book", /* 385 */ "Light", /* 386 */ "Medium", /* 387 */ "Regular", /* 388 */ "Roman", /* 389 */ "Semibold" /* 390 */ }; static const int nStdStrings = 391; static const char *const MacintoshStrings[] = { ".notdef", /* 0 */ ".null", /* 1 */ "nonmarkingreturn", /* 2 */ "space", /* 3 */ "exclam", /* 4 */ "quotedbl", /* 5 */ "numbersign", /* 6 */ "dollar", /* 7 */ "percent", /* 8 */ "ampersand", /* 9 */ "quotesingle", /* 10 */ "parenleft", /* 11 */ "parenright", /* 12 */ "asterisk", /* 13 */ "plus", /* 14 */ "comma", /* 15 */ "hyphen", /* 16 */ "period", /* 17 */ "slash", /* 18 */ "zero", /* 19 */ "one", /* 20 */ "two", /* 21 */ "three", /* 22 */ "four", /* 23 */ "five", /* 24 */ "six", /* 25 */ "seven", /* 26 */ "eight", /* 27 */ "nine", /* 28 */ "colon", /* 29 */ "semicolon", /* 30 */ "less", /* 31 */ "equal", /* 32 */ "greater", /* 33 */ "question", /* 34 */ "at", /* 35 */ "A", /* 36 */ "B", /* 37 */ "C", /* 38 */ "D", /* 39 */ "E", /* 40 */ "F", /* 41 */ "G", /* 42 */ "H", /* 43 */ "I", /* 44 */ "J", /* 45 */ "K", /* 46 */ "L", /* 47 */ "M", /* 48 */ "N", /* 49 */ "O", /* 50 */ "P", /* 51 */ "Q", /* 52 */ "R", /* 53 */ "S", /* 54 */ "T", /* 55 */ "U", /* 56 */ "V", /* 57 */ "W", /* 58 */ "X", /* 59 */ "Y", /* 60 */ "Z", /* 61 */ "bracketleft", /* 62 */ "backslash", /* 63 */ "bracketright", /* 64 */ "asciicircum", /* 65 */ "underscore", /* 66 */ "grave", /* 67 */ "a", /* 68 */ "b", /* 69 */ "c", /* 70 */ "d", /* 71 */ "e", /* 72 */ "f", /* 73 */ "g", /* 74 */ "h", /* 75 */ "i", /* 76 */ "j", /* 77 */ "k", /* 78 */ "l", /* 79 */ "m", /* 80 */ "n", /* 81 */ "o", /* 82 */ "p", /* 83 */ "q", /* 84 */ "r", /* 85 */ "s", /* 86 */ "t", /* 87 */ "u", /* 88 */ "v", /* 89 */ "w", /* 90 */ "x", /* 91 */ "y", /* 92 */ "z", /* 93 */ "braceleft", /* 94 */ "bar", /* 95 */ "braceright", /* 96 */ "asciitilde", /* 97 */ "Adieresis", /* 98 */ "Aring", /* 99 */ "Ccedilla", /* 100 */ "Eacute", /* 101 */ "Ntilde", /* 102 */ "Odieresis", /* 103 */ "Udieresis", /* 104 */ "aacute", /* 105 */ "agrave", /* 106 */ "acircumflex", /* 107 */ "adieresis", /* 108 */ "atilde", /* 109 */ "aring", /* 110 */ "ccedilla", /* 111 */ "eacute", /* 112 */ "egrave", /* 113 */ "ecircumflex", /* 114 */ "edieresis", /* 115 */ "iacute", /* 116 */ "igrave", /* 117 */ "icircumflex", /* 118 */ "idieresis", /* 119 */ "ntilde", /* 120 */ "oacute", /* 121 */ "ograve", /* 122 */ "ocircumflex", /* 123 */ "odieresis", /* 124 */ "otilde", /* 125 */ "uacute", /* 126 */ "ugrave", /* 127 */ "ucircumflex", /* 128 */ "udieresis", /* 129 */ "dagger", /* 130 */ "degree", /* 131 */ "cent", /* 132 */ "sterling", /* 133 */ "section", /* 134 */ "bullet", /* 135 */ "paragraph", /* 136 */ "germandbls", /* 137 */ "registered", /* 138 */ "copyright", /* 139 */ "trademark", /* 140 */ "acute", /* 141 */ "dieresis", /* 142 */ "notequal", /* 143 */ "AE", /* 144 */ "Oslash", /* 145 */ "infinity", /* 146 */ "plusminus", /* 147 */ "lessequal", /* 148 */ "greaterequal", /* 149 */ "yen", /* 150 */ "mu", /* 151 */ "partialdiff", /* 152 */ "summation", /* 153 */ "product", /* 154 */ "pi", /* 155 */ "integral", /* 156 */ "ordfeminine", /* 157 */ "ordmasculine", /* 158 */ "Omega", /* 159 */ "ae", /* 160 */ "oslash", /* 161 */ "questiondown", /* 162 */ "exclamdown", /* 163 */ "logicalnot", /* 164 */ "radical", /* 165 */ "florin", /* 166 */ "approxequal", /* 167 */ "Delta", /* 168 */ "guillemotleft", /* 169 */ "guillemotright", /* 170 */ "ellipsis", /* 171 */ "nonbreakingspace", /* 172 */ "Agrave", /* 173 */ "Atilde", /* 174 */ "Otilde", /* 175 */ "OE", /* 176 */ "oe", /* 177 */ "endash", /* 178 */ "emdash", /* 179 */ "quotedblleft", /* 180 */ "quotedblright", /* 181 */ "quoteleft", /* 182 */ "quoteright", /* 183 */ "divide", /* 184 */ "lozenge", /* 185 */ "ydieresis", /* 186 */ "Ydieresis", /* 187 */ "fraction", /* 188 */ "currency", /* 189 */ "guilsinglleft", /* 190 */ "guilsinglright", /* 191 */ "fi", /* 192 */ "fl", /* 193 */ "daggerdbl", /* 194 */ "periodcentered", /* 195 */ "quotesinglbase", /* 196 */ "quotedblbase", /* 197 */ "perthousand", /* 198 */ "Acircumflex", /* 199 */ "Ecircumflex", /* 200 */ "Aacute", /* 201 */ "Edieresis", /* 202 */ "Egrave", /* 203 */ "Iacute", /* 204 */ "Icircumflex", /* 205 */ "Idieresis", /* 206 */ "Igrave", /* 207 */ "Oacute", /* 208 */ "Ocircumflex", /* 209 */ "apple", /* 210 */ "Ograve", /* 211 */ "Uacute", /* 212 */ "Ucircumflex", /* 213 */ "Ugrave", /* 214 */ "dotlessi", /* 215 */ "circumflex", /* 216 */ "tilde", /* 217 */ "macron", /* 218 */ "breve", /* 219 */ "dotaccent", /* 220 */ "ring", /* 221 */ "cedilla", /* 222 */ "hungarumlaut", /* 223 */ "ogonek", /* 224 */ "caron", /* 225 */ "Lslash", /* 226 */ "lslash", /* 227 */ "Scaron", /* 228 */ "scaron", /* 229 */ "Zcaron", /* 230 */ "zcaron", /* 231 */ "brokenbar", /* 232 */ "Eth", /* 233 */ "eth", /* 234 */ "Yacute", /* 235 */ "yacute", /* 236 */ "Thorn", /* 237 */ "thorn", /* 238 */ "minus", /* 239 */ "multiply", /* 240 */ "onesuperior", /* 241 */ "twosuperior", /* 242 */ "threesuperior", /* 243 */ "onehalf", /* 244 */ "onequarter", /* 245 */ "threequarters", /* 246 */ "franc", /* 247 */ "Gbreve", /* 248 */ "gbreve", /* 249 */ "Idotaccent", /* 250 */ "Scedilla", /* 251 */ "scedilla", /* 252 */ "Cacute", /* 253 */ "cacute", /* 254 */ "Ccaron", /* 255 */ "ccaron", /* 256 */ "dcroat" /* 257 */ }; static const int nMacintoshStrings = 258; static const struct WGL { int u; const char *s; } WGL[] = { /* WGL4 */ { 0x0000, ".notdef" }, { 0x0020, "space" }, { 0x0021, "exclam" }, { 0x0022, "quotedbl" }, { 0x0023, "numbersign" }, { 0x0024, "dollar" }, { 0x0025, "percent" }, { 0x0026, "ampersand" }, { 0x0027, "quotesingle" }, { 0x0028, "parenleft" }, { 0x0029, "parenright" }, { 0x002a, "asterisk" }, { 0x002b, "plus" }, { 0x002c, "comma" }, { 0x002d, "hyphen" }, { 0x002e, "period" }, { 0x002f, "slash" }, { 0x0030, "zero" }, { 0x0031, "one" }, { 0x0032, "two" }, { 0x0033, "three" }, { 0x0034, "four" }, { 0x0035, "five" }, { 0x0036, "six" }, { 0x0037, "seven" }, { 0x0038, "eight" }, { 0x0039, "nine" }, { 0x003a, "colon" }, { 0x003b, "semicolon" }, { 0x003c, "less" }, { 0x003d, "equal" }, { 0x003e, "greater" }, { 0x003f, "question" }, { 0x0040, "at" }, { 0x0041, "A" }, { 0x0042, "B" }, { 0x0043, "C" }, { 0x0044, "D" }, { 0x0045, "E" }, { 0x0046, "F" }, { 0x0047, "G" }, { 0x0048, "H" }, { 0x0049, "I" }, { 0x004a, "J" }, { 0x004b, "K" }, { 0x004c, "L" }, { 0x004d, "M" }, { 0x004e, "N" }, { 0x004f, "O" }, { 0x0050, "P" }, { 0x0051, "Q" }, { 0x0052, "R" }, { 0x0053, "S" }, { 0x0054, "T" }, { 0x0055, "U" }, { 0x0056, "V" }, { 0x0057, "W" }, { 0x0058, "X" }, { 0x0059, "Y" }, { 0x005a, "Z" }, { 0x005b, "bracketleft" }, { 0x005c, "backslash" }, { 0x005d, "bracketright" }, { 0x005e, "asciicircum" }, { 0x005f, "underscore" }, { 0x0060, "grave" }, { 0x0061, "a" }, { 0x0062, "b" }, { 0x0063, "c" }, { 0x0064, "d" }, { 0x0065, "e" }, { 0x0066, "f" }, { 0x0067, "g" }, { 0x0068, "h" }, { 0x0069, "i" }, { 0x006a, "j" }, { 0x006b, "k" }, { 0x006c, "l" }, { 0x006d, "m" }, { 0x006e, "n" }, { 0x006f, "o" }, { 0x0070, "p" }, { 0x0071, "q" }, { 0x0072, "r" }, { 0x0073, "s" }, { 0x0074, "t" }, { 0x0075, "u" }, { 0x0076, "v" }, { 0x0077, "w" }, { 0x0078, "x" }, { 0x0079, "y" }, { 0x007a, "z" }, { 0x007b, "braceleft" }, { 0x007c, "bar" }, { 0x007d, "braceright" }, { 0x007e, "asciitilde" }, { 0x00a1, "exclamdown" }, { 0x00a2, "cent" }, { 0x00a3, "sterling" }, { 0x00a4, "currency" }, { 0x00a5, "yen" }, { 0x00a6, "brokenbar" }, { 0x00a7, "section" }, { 0x00a8, "dieresis" }, { 0x00a9, "copyright" }, { 0x00aa, "ordfeminine" }, { 0x00ab, "guillemotleft" }, { 0x00ac, "logicalnot" }, { 0x00ae, "registered" }, { 0x00af, "macron" }, { 0x00b0, "degree" }, { 0x00b1, "plusminus" }, { 0x00b2, "twosuperior" }, { 0x00b3, "threesuperior" }, { 0x00b4, "acute" }, { 0x00b5, "mu" }, { 0x00b6, "paragraph" }, { 0x00b7, "periodcentered" }, { 0x00b8, "cedilla" }, { 0x00b9, "onesuperior" }, { 0x00ba, "ordmasculine" }, { 0x00bb, "guillemotright" }, { 0x00bc, "onequarter" }, { 0x00bd, "onehalf" }, { 0x00be, "threequarters" }, { 0x00bf, "questiondown" }, { 0x00c0, "Agrave" }, { 0x00c1, "Aacute" }, { 0x00c2, "Acircumflex" }, { 0x00c3, "Atilde" }, { 0x00c4, "Adieresis" }, { 0x00c5, "Aring" }, { 0x00c6, "AE" }, { 0x00c7, "Ccedilla" }, { 0x00c8, "Egrave" }, { 0x00c9, "Eacute" }, { 0x00ca, "Ecircumflex" }, { 0x00cb, "Edieresis" }, { 0x00cc, "Igrave" }, { 0x00cd, "Iacute" }, { 0x00ce, "Icircumflex" }, { 0x00cf, "Idieresis" }, { 0x00d0, "Eth" }, { 0x00d1, "Ntilde" }, { 0x00d2, "Ograve" }, { 0x00d3, "Oacute" }, { 0x00d4, "Ocircumflex" }, { 0x00d5, "Otilde" }, { 0x00d6, "Odieresis" }, { 0x00d7, "multiply" }, { 0x00d8, "Oslash" }, { 0x00d9, "Ugrave" }, { 0x00da, "Uacute" }, { 0x00db, "Ucircumflex" }, { 0x00dc, "Udieresis" }, { 0x00dd, "Yacute" }, { 0x00de, "Thorn" }, { 0x00df, "germandbls" }, { 0x00e0, "agrave" }, { 0x00e1, "aacute" }, { 0x00e2, "acircumflex" }, { 0x00e3, "atilde" }, { 0x00e4, "adieresis" }, { 0x00e5, "aring" }, { 0x00e6, "ae" }, { 0x00e7, "ccedilla" }, { 0x00e8, "egrave" }, { 0x00e9, "eacute" }, { 0x00ea, "ecircumflex" }, { 0x00eb, "edieresis" }, { 0x00ec, "igrave" }, { 0x00ed, "iacute" }, { 0x00ee, "icircumflex" }, { 0x00ef, "idieresis" }, { 0x00f0, "eth" }, { 0x00f1, "ntilde" }, { 0x00f2, "ograve" }, { 0x00f3, "oacute" }, { 0x00f4, "ocircumflex" }, { 0x00f5, "otilde" }, { 0x00f6, "odieresis" }, { 0x00f7, "divide" }, { 0x00f8, "oslash" }, { 0x00f9, "ugrave" }, { 0x00fa, "uacute" }, { 0x00fb, "ucircumflex" }, { 0x00fc, "udieresis" }, { 0x00fd, "yacute" }, { 0x00fe, "thorn" }, { 0x00ff, "ydieresis" }, { 0x0100, "Amacron" }, { 0x0101, "amacron" }, { 0x0102, "Abreve" }, { 0x0103, "abreve" }, { 0x0104, "Aogonek" }, { 0x0105, "aogonek" }, { 0x0106, "Cacute" }, { 0x0107, "cacute" }, { 0x0108, "Ccircumflex" }, { 0x0109, "ccircumflex" }, { 0x010a, "Cdotaccent" }, { 0x010b, "cdotaccent" }, { 0x010c, "Ccaron" }, { 0x010d, "ccaron" }, { 0x010e, "Dcaron" }, { 0x010f, "dcaron" }, { 0x0110, "Dcroat" }, { 0x0111, "dcroat" }, { 0x0112, "Emacron" }, { 0x0113, "emacron" }, { 0x0114, "Ebreve" }, { 0x0115, "ebreve" }, { 0x0116, "Edotaccent" }, { 0x0117, "edotaccent" }, { 0x0118, "Eogonek" }, { 0x0119, "eogonek" }, { 0x011a, "Ecaron" }, { 0x011b, "ecaron" }, { 0x011c, "Gcircumflex" }, { 0x011d, "gcircumflex" }, { 0x011e, "Gbreve" }, { 0x011f, "gbreve" }, { 0x0120, "Gdotaccent" }, { 0x0121, "gdotaccent" }, { 0x0122, "Gcommaaccent" }, { 0x0123, "gcommaaccent" }, { 0x0124, "Hcircumflex" }, { 0x0125, "hcircumflex" }, { 0x0126, "Hbar" }, { 0x0127, "hbar" }, { 0x0128, "Itilde" }, { 0x0129, "itilde" }, { 0x012a, "Imacron" }, { 0x012b, "imacron" }, { 0x012c, "Ibreve" }, { 0x012d, "ibreve" }, { 0x012e, "Iogonek" }, { 0x012f, "iogonek" }, { 0x0130, "Idotaccent" }, { 0x0131, "dotlessi" }, { 0x0132, "IJ" }, { 0x0133, "ij" }, { 0x0134, "Jcircumflex" }, { 0x0135, "jcircumflex" }, { 0x0136, "Kcommaaccent" }, { 0x0137, "kcommaaccent" }, { 0x0138, "kgreenlandic" }, { 0x0139, "Lacute" }, { 0x013a, "lacute" }, { 0x013b, "Lcommaaccent" }, { 0x013c, "lcommaaccent" }, { 0x013d, "Lcaron" }, { 0x013e, "lcaron" }, { 0x013f, "Ldot" }, { 0x0140, "ldot" }, { 0x0141, "Lslash" }, { 0x0142, "lslash" }, { 0x0143, "Nacute" }, { 0x0144, "nacute" }, { 0x0145, "Ncommaaccent" }, { 0x0146, "ncommaaccent" }, { 0x0147, "Ncaron" }, { 0x0148, "ncaron" }, { 0x0149, "napostrophe" }, { 0x014a, "Eng" }, { 0x014b, "eng" }, { 0x014c, "Omacron" }, { 0x014d, "omacron" }, { 0x014e, "Obreve" }, { 0x014f, "obreve" }, { 0x0150, "Ohungarumlaut" }, { 0x0151, "ohungarumlaut" }, { 0x0152, "OE" }, { 0x0153, "oe" }, { 0x0154, "Racute" }, { 0x0155, "racute" }, { 0x0156, "Rcommaaccent" }, { 0x0157, "rcommaaccent" }, { 0x0158, "Rcaron" }, { 0x0159, "rcaron" }, { 0x015a, "Sacute" }, { 0x015b, "sacute" }, { 0x015c, "Scircumflex" }, { 0x015d, "scircumflex" }, { 0x015e, "Scedilla" }, { 0x015f, "scedilla" }, { 0x0160, "Scaron" }, { 0x0161, "scaron" }, { 0x0164, "Tcaron" }, { 0x0165, "tcaron" }, { 0x0166, "Tbar" }, { 0x0167, "tbar" }, { 0x0168, "Utilde" }, { 0x0169, "utilde" }, { 0x016a, "Umacron" }, { 0x016b, "umacron" }, { 0x016c, "Ubreve" }, { 0x016d, "ubreve" }, { 0x016e, "Uring" }, { 0x016f, "uring" }, { 0x0170, "Uhungarumlaut" }, { 0x0171, "uhungarumlaut" }, { 0x0172, "Uogonek" }, { 0x0173, "uogonek" }, { 0x0174, "Wcircumflex" }, { 0x0175, "wcircumflex" }, { 0x0176, "Ycircumflex" }, { 0x0177, "ycircumflex" }, { 0x0178, "Ydieresis" }, { 0x0179, "Zacute" }, { 0x017a, "zacute" }, { 0x017b, "Zdotaccent" }, { 0x017c, "zdotaccent" }, { 0x017d, "Zcaron" }, { 0x017e, "zcaron" }, { 0x017f, "longs" }, { 0x0192, "florin" }, { 0x01fa, "Aringacute" }, { 0x01fb, "aringacute" }, { 0x01fc, "AEacute" }, { 0x01fd, "aeacute" }, { 0x01fe, "Oslashacute" }, { 0x01ff, "oslashacute" }, { 0x02c6, "circumflex" }, { 0x02c7, "caron" }, { 0x02d8, "breve" }, { 0x02d9, "dotaccent" }, { 0x02da, "ring" }, { 0x02db, "ogonek" }, { 0x02dc, "tilde" }, { 0x02dd, "hungarumlaut" }, { 0x0384, "tonos" }, { 0x0385, "dieresistonos" }, { 0x0386, "Alphatonos" }, { 0x0387, "anoteleia" }, { 0x0388, "Epsilontonos" }, { 0x0389, "Etatonos" }, { 0x038a, "Iotatonos" }, { 0x038c, "Omicrontonos" }, { 0x038e, "Upsilontonos" }, { 0x038f, "Omegatonos" }, { 0x0390, "iotadieresistonos" }, { 0x0391, "Alpha" }, { 0x0392, "Beta" }, { 0x0393, "Gamma" }, { 0x0395, "Epsilon" }, { 0x0396, "Zeta" }, { 0x0397, "Eta" }, { 0x0398, "Theta" }, { 0x0399, "Iota" }, { 0x039a, "Kappa" }, { 0x039b, "Lambda" }, { 0x039c, "Mu" }, { 0x039d, "Nu" }, { 0x039e, "Xi" }, { 0x039f, "Omicron" }, { 0x03a0, "Pi" }, { 0x03a1, "Rho" }, { 0x03a3, "Sigma" }, { 0x03a4, "Tau" }, { 0x03a5, "Upsilon" }, { 0x03a6, "Phi" }, { 0x03a7, "Chi" }, { 0x03a8, "Psi" }, { 0x03aa, "Iotadieresis" }, { 0x03ab, "Upsilondieresis" }, { 0x03ac, "alphatonos" }, { 0x03ad, "epsilontonos" }, { 0x03ae, "etatonos" }, { 0x03af, "iotatonos" }, { 0x03b0, "upsilondieresistonos" }, { 0x03b1, "alpha" }, { 0x03b2, "beta" }, { 0x03b3, "gamma" }, { 0x03b4, "delta" }, { 0x03b5, "epsilon" }, { 0x03b6, "zeta" }, { 0x03b7, "eta" }, { 0x03b8, "theta" }, { 0x03b9, "iota" }, { 0x03ba, "kappa" }, { 0x03bb, "lambda" }, { 0x03bd, "nu" }, { 0x03be, "xi" }, { 0x03bf, "omicron" }, { 0x03c0, "pi" }, { 0x03c1, "rho" }, { 0x03c2, "sigma1" }, { 0x03c3, "sigma" }, { 0x03c4, "tau" }, { 0x03c5, "upsilon" }, { 0x03c6, "phi" }, { 0x03c7, "chi" }, { 0x03c8, "psi" }, { 0x03c9, "omega" }, { 0x03ca, "iotadieresis" }, { 0x03cb, "upsilondieresis" }, { 0x03cc, "omicrontonos" }, { 0x03cd, "upsilontonos" }, { 0x03ce, "omegatonos" }, { 0x0401, "afii10023" }, { 0x0402, "afii10051" }, { 0x0403, "afii10052" }, { 0x0404, "afii10053" }, { 0x0405, "afii10054" }, { 0x0406, "afii10055" }, { 0x0407, "afii10056" }, { 0x0408, "afii10057" }, { 0x0409, "afii10058" }, { 0x040a, "afii10059" }, { 0x040b, "afii10060" }, { 0x040c, "afii10061" }, { 0x040e, "afii10062" }, { 0x040f, "afii10145" }, { 0x0410, "afii10017" }, { 0x0411, "afii10018" }, { 0x0412, "afii10019" }, { 0x0413, "afii10020" }, { 0x0414, "afii10021" }, { 0x0415, "afii10022" }, { 0x0416, "afii10024" }, { 0x0417, "afii10025" }, { 0x0418, "afii10026" }, { 0x0419, "afii10027" }, { 0x041a, "afii10028" }, { 0x041b, "afii10029" }, { 0x041c, "afii10030" }, { 0x041d, "afii10031" }, { 0x041e, "afii10032" }, { 0x041f, "afii10033" }, { 0x0420, "afii10034" }, { 0x0421, "afii10035" }, { 0x0422, "afii10036" }, { 0x0423, "afii10037" }, { 0x0424, "afii10038" }, { 0x0425, "afii10039" }, { 0x0426, "afii10040" }, { 0x0427, "afii10041" }, { 0x0428, "afii10042" }, { 0x0429, "afii10043" }, { 0x042a, "afii10044" }, { 0x042b, "afii10045" }, { 0x042c, "afii10046" }, { 0x042d, "afii10047" }, { 0x042e, "afii10048" }, { 0x042f, "afii10049" }, { 0x0430, "afii10065" }, { 0x0431, "afii10066" }, { 0x0432, "afii10067" }, { 0x0433, "afii10068" }, { 0x0434, "afii10069" }, { 0x0435, "afii10070" }, { 0x0436, "afii10072" }, { 0x0437, "afii10073" }, { 0x0438, "afii10074" }, { 0x0439, "afii10075" }, { 0x043a, "afii10076" }, { 0x043b, "afii10077" }, { 0x043c, "afii10078" }, { 0x043d, "afii10079" }, { 0x043e, "afii10080" }, { 0x043f, "afii10081" }, { 0x0440, "afii10082" }, { 0x0441, "afii10083" }, { 0x0442, "afii10084" }, { 0x0443, "afii10085" }, { 0x0444, "afii10086" }, { 0x0445, "afii10087" }, { 0x0446, "afii10088" }, { 0x0447, "afii10089" }, { 0x0448, "afii10090" }, { 0x0449, "afii10091" }, { 0x044a, "afii10092" }, { 0x044b, "afii10093" }, { 0x044c, "afii10094" }, { 0x044d, "afii10095" }, { 0x044e, "afii10096" }, { 0x044f, "afii10097" }, { 0x0451, "afii10071" }, { 0x0452, "afii10099" }, { 0x0453, "afii10100" }, { 0x0454, "afii10101" }, { 0x0455, "afii10102" }, { 0x0456, "afii10103" }, { 0x0457, "afii10104" }, { 0x0458, "afii10105" }, { 0x0459, "afii10106" }, { 0x045a, "afii10107" }, { 0x045b, "afii10108" }, { 0x045c, "afii10109" }, { 0x045e, "afii10110" }, { 0x045f, "afii10193" }, { 0x0490, "afii10050" }, { 0x0491, "afii10098" }, { 0x1e80, "Wgrave" }, { 0x1e81, "wgrave" }, { 0x1e82, "Wacute" }, { 0x1e83, "wacute" }, { 0x1e84, "Wdieresis" }, { 0x1e85, "wdieresis" }, { 0x1ef2, "Ygrave" }, { 0x1ef3, "ygrave" }, { 0x2013, "endash" }, { 0x2014, "emdash" }, { 0x2015, "afii00208" }, { 0x2017, "underscoredbl" }, { 0x2018, "quoteleft" }, { 0x2019, "quoteright" }, { 0x201a, "quotesinglbase" }, { 0x201b, "quotereversed" }, { 0x201c, "quotedblleft" }, { 0x201d, "quotedblright" }, { 0x201e, "quotedblbase" }, { 0x2020, "dagger" }, { 0x2021, "daggerdbl" }, { 0x2022, "bullet" }, { 0x2026, "ellipsis" }, { 0x2030, "perthousand" }, { 0x2032, "minute" }, { 0x2033, "second" }, { 0x2039, "guilsinglleft" }, { 0x203a, "guilsinglright" }, { 0x203c, "exclamdbl" }, { 0x203e, "uni203E" }, { 0x2044, "fraction" }, { 0x207f, "nsuperior" }, { 0x20a3, "franc" }, { 0x20a4, "lira" }, { 0x20a7, "peseta" }, { 0x20ac, "Euro" }, { 0x2105, "afii61248" }, { 0x2113, "afii61289" }, { 0x2116, "afii61352" }, { 0x2122, "trademark" }, { 0x2126, "Omega" }, { 0x212e, "estimated" }, { 0x215b, "oneeighth" }, { 0x215c, "threeeighths" }, { 0x215d, "fiveeighths" }, { 0x215e, "seveneighths" }, { 0x2190, "arrowleft" }, { 0x2191, "arrowup" }, { 0x2192, "arrowright" }, { 0x2193, "arrowdown" }, { 0x2194, "arrowboth" }, { 0x2195, "arrowupdn" }, { 0x21a8, "arrowupdnbse" }, { 0x2202, "partialdiff" }, { 0x2206, "Delta" }, { 0x220f, "product" }, { 0x2211, "summation" }, { 0x2212, "minus" }, { 0x221a, "radical" }, { 0x221e, "infinity" }, { 0x221f, "orthogonal" }, { 0x2229, "intersection" }, { 0x222b, "integral" }, { 0x2248, "approxequal" }, { 0x2260, "notequal" }, { 0x2261, "equivalence" }, { 0x2264, "lessequal" }, { 0x2265, "greaterequal" }, { 0x2302, "house" }, { 0x2310, "revlogicalnot" }, { 0x2320, "integraltp" }, { 0x2321, "integralbt" }, { 0x2500, "SF100000" }, { 0x2502, "SF110000" }, { 0x250c, "SF010000" }, { 0x2510, "SF030000" }, { 0x2514, "SF020000" }, { 0x2518, "SF040000" }, { 0x251c, "SF080000" }, { 0x2524, "SF090000" }, { 0x252c, "SF060000" }, { 0x2534, "SF070000" }, { 0x253c, "SF050000" }, { 0x2550, "SF430000" }, { 0x2551, "SF240000" }, { 0x2552, "SF510000" }, { 0x2553, "SF520000" }, { 0x2554, "SF390000" }, { 0x2555, "SF220000" }, { 0x2556, "SF210000" }, { 0x2557, "SF250000" }, { 0x2558, "SF500000" }, { 0x2559, "SF490000" }, { 0x255a, "SF380000" }, { 0x255b, "SF280000" }, { 0x255c, "SF270000" }, { 0x255d, "SF260000" }, { 0x255e, "SF360000" }, { 0x255f, "SF370000" }, { 0x2560, "SF420000" }, { 0x2561, "SF190000" }, { 0x2562, "SF200000" }, { 0x2563, "SF230000" }, { 0x2564, "SF470000" }, { 0x2565, "SF480000" }, { 0x2566, "SF410000" }, { 0x2567, "SF450000" }, { 0x2568, "SF460000" }, { 0x2569, "SF400000" }, { 0x256a, "SF540000" }, { 0x256b, "SF530000" }, { 0x256c, "SF440000" }, { 0x2580, "upblock" }, { 0x2584, "dnblock" }, { 0x2588, "block" }, { 0x258c, "lfblock" }, { 0x2590, "rtblock" }, { 0x2591, "ltshade" }, { 0x2592, "shade" }, { 0x2593, "dkshade" }, { 0x25a0, "filledbox" }, { 0x25a1, "H22073" }, { 0x25aa, "H18543" }, { 0x25ab, "H18551" }, { 0x25ac, "filledrect" }, { 0x25b2, "triagup" }, { 0x25ba, "triagrt" }, { 0x25bc, "triagdn" }, { 0x25c4, "triaglf" }, { 0x25ca, "lozenge" }, { 0x25cb, "circle" }, { 0x25cf, "H18533" }, { 0x25d8, "invbullet" }, { 0x25d9, "invcircle" }, { 0x25e6, "openbullet" }, { 0x263a, "smileface" }, { 0x263b, "invsmileface" }, { 0x263c, "sun" }, { 0x2640, "female" }, { 0x2642, "male" }, { 0x2660, "spade" }, { 0x2663, "club" }, { 0x2665, "heart" }, { 0x2666, "diamond" }, { 0x266a, "musicalnote" }, { 0x266b, "musicalnotedbl" }, { 0xfb01, "fi" }, { 0xfb02, "fl" }, { -1, NULL } }; static int nWGL = 642; static char **ExtraStrings; static char *ExtraStringSpace; static int ExtraStringSpacePos; static int nExtraStrings; static char * getSID(int n) { if (ttf == 3) { /*EMPTY*/; } else if (ttf == 2) { if (n >= 0 && n < nWGL) return (char *)WGL[n].s; n -= nWGL; } else if (ttf == 1) { if (n >= 0 && n < nMacintoshStrings) return (char *)MacintoshStrings[n]; n -= nMacintoshStrings; } else { if (n >= 0 && n < nStdStrings) return (char *)StandardStrings[n]; n -= nStdStrings; } if (n < nExtraStrings) return ExtraStrings[n]; return NULL; } static void error(const char *fmt, ...) { char buf[4096]; va_list ap; int n; n = snprintf(buf, sizeof buf, "%s: ", filename); va_start(ap, fmt); vsnprintf(&buf[n], sizeof buf - n, fmt, ap); errprint("%s", buf); va_end(ap); longjmp(breakpoint, 1); } #define _pbe16(cp) ((uint16_t)((cp)[1]&0377) + ((uint16_t)((cp)[0]&0377) << 8)) static uint32_t pbe16(const char *cp) { return (uint16_t)(cp[1]&0377) + ((uint16_t)(cp[0]&0377) << 8); } static uint32_t pbe24(const char *cp) { return (uint32_t)(cp[3]&0377) + ((uint32_t)(cp[2]&0377) << 8) + ((uint32_t)(cp[1]&0377) << 16); } static uint32_t pbe32(const char *cp) { return (uint32_t)(cp[3]&0377) + ((uint32_t)(cp[2]&0377) << 8) + ((uint32_t)(cp[1]&0377) << 16) + ((uint32_t)(cp[0]&0377) << 24); } static uint32_t pbeXX(const char *cp, int n) { switch (n) { default: error("invalid number size %d", n); case 1: return *cp&0377; case 2: return _pbe16(cp); case 3: return pbe24(cp); case 4: return pbe32(cp); } } static double cffoper(long *op) { int b0; int n = 0; double v = 0; b0 = contents[*op]&0377; if (b0 >= 32 && b0 <= 246) { n = 1; v = b0 - 139; } else if (b0 >= 247 && b0 <= 250) { n = 2; v = (b0 - 247) * 256 + (contents[*op+1]&0377) + 108; } else if (b0 >= 251 && b0 <= 254) { n = 2; v = -(b0 - 251) * 256 - (contents[*op+1]&0377) - 108; } else if (b0 == 28) { n = 3; v = (int16_t)((contents[*op+1]&0377)<<8 | (contents[*op+2]&0377)); } else if (b0 == 29) { n = 5; v = (int32_t)pbe32(&contents[*op+1]); } else if (b0 == 30) { char buf[100], *xp; int c, i = 0, s = 0; n = 1; for (;;) { if (i == sizeof buf - 2) error("floating point operand too long"); c = (contents[*op+n]&0377) >> (s ? 8 : 0) & 0xf; if (c >= 0 && c <= 9) buf[i++] = c + '0'; else if (c == 0xa) buf[i++] = '.'; else if (c == 0xb) buf[i++] = 'E'; else if (c == 0xc) { buf[i++] = 'E'; buf[i++] = '-'; } else if (c == 0xd) error("reserved nibble d in floating point " "operand"); else if (c == 0xe) buf[i++] = '-'; else if (c == 0xf) { buf[i++] = 0; if (s == 0) n++; break; } if ((s = !s) == 0) n++; } v = strtod(buf, &xp); if (*xp != 0) error("invalid floating point operand <%s>", buf); } else error("invalid operand b0 range %d", b0); *op += n; return v; } static void get_offset_table(void) { char buf[12]; if (size < 12) error("no offset table"); memcpy(buf, contents, 12); if (pbe32(buf) == 0x00010000 || memcmp(buf, "true", 4) == 0) { ttf = 1; } else if (memcmp(buf, "OTTO", 4) == 0) { ttf = 0; } else error("unknown font type"); numTables = pbe16(&buf[4]); } static void get_table_directories(void) { int i, j; size_t o; char buf[16]; free(table_directories); table_directories = calloc(numTables, sizeof *table_directories); o = 12; for (i = 0; tables[i].pos; i++) *tables[i].pos = -1; for (i = 0; i < numTables; i++) { if (o + 16 >= size) error("cannot get %dth table directory", i); memcpy(buf, &contents[o], 16); for (j = 0; tables[j].name; j++) if (memcmp(buf, tables[j].name, 4) == 0) { *tables[j].pos = i; break; } o += 16; memcpy(table_directories[i].tag, buf, 4); table_directories[i].checkSum = pbe32(&buf[4]); table_directories[i].offset = pbe32(&buf[8]); table_directories[i].length = pbe32(&buf[12]); if (table_directories[i].offset + table_directories[i].length > size) error("invalid table directory, " "size for entry %4.4s too large", table_directories[i].tag); } } static void free_INDEX(struct INDEX *ip) { if (ip) { free(ip->offset); free(ip); } } static struct INDEX * get_INDEX(unsigned long *op) { struct INDEX *ip; int i; if (*op + 3 >= size) error("no index at position %ld", *op); ip = calloc(1, sizeof *ip); ip->count = pbe16(&contents[*op]); *op += 2; if (ip->count != 0) { ip->offSize = contents[(*op)++] & 0377; ip->offset = calloc(ip->count+1, sizeof *ip->offset); for (i = 0; i < ip->count+1; i++) { if (*op + ip->offSize >= size) { free_INDEX(ip); error("no index offset at position %ld", *op); } ip->offset[i] = pbeXX(&contents[*op], ip->offSize); *op += ip->offSize; } ip->data = &contents[*op]; for (i = 0; i < ip->count+1; i++) ip->offset[i] += *op - 1; *op = ip->offset[ip->count]; } return ip; } static void get_bb(int gid, int B[4]) { int k, o; if (pos_loca < 0 || pos_glyf < 0) return; o = table_directories[pos_loca].offset; k = indexToLocFormat ? pbe32(&contents[o+4*gid]) : pbe16(&contents[o+2*gid]) * 2; o = table_directories[pos_glyf].offset; B[0] = (int16_t)pbe16(&contents[o+k+2]); B[1] = (int16_t)pbe16(&contents[o+k+4]); B[2] = (int16_t)pbe16(&contents[o+k+6]); B[3] = (int16_t)pbe16(&contents[o+k+8]); } static void onechar(unsigned long gid, int sid) { long o; int w, tp; char *N; int *b = NULL, B[4] = { 0, 0, 0, 0}; if ((gid == 0 && sid != 0) || (sid == 0 && gid != 0)) return; /* require .notdef to be GID 0 */ if (gid >= nc) return; if (pos_hmtx < 0) error("no hmtx table"); if (table_directories[pos_hmtx].length < 4) error("empty hmtx table"); o = table_directories[pos_hmtx].offset; if (isFixedPitch) w = pbe16(&contents[o]); else { if (table_directories[pos_hmtx].length < 4 * (gid+1)) return; /* just ignore this glyph */ w = pbe16(&contents[o + 4 * gid]); } if (sid != 0 && gid2sid[gid] != 0) return; if (a) { if ((N = getSID(sid)) != NULL) { a->nspace += strlen(N) + 1; tp = afmmapname(N, a->spec); } else tp = 0; if (ttf) get_bb(gid, b = B); afmaddchar(a, gid, tp, 0, w, b, N, a->spec, gid); } gid2sid[gid] = sid; } static int get_CFF_Top_DICT_Entry(int e) { long o; int d = 0; if (CFF.Top_DICT == NULL || CFF.Top_DICT->offset == NULL) error("no Top DICT INDEX"); o = CFF.Top_DICT->offset[0]; while (o < CFF.Top_DICT->offset[1] && contents[o] != e) { if (contents[o] < 0 || contents[o] > 27) d = cffoper(&o); else { d = 0; if (contents[o] == 12) o++; o++; } } return d; } static void get_CFF_Charset(void) { int d = 0; unsigned long gid, i, j, first, nLeft; d = get_CFF_Top_DICT_Entry(15); if (d == 0) { for (i = 0; i < nc && i <= 228; i++) onechar(i, i); } else if (d == 1) { for (i = 0; i < nc && i <= 166; i++) onechar(i, ExpertCharset[i]); } else if (d == 2) { for (i = 0; i < nc && i <= 87; i++) onechar(i, ExpertSubsetCharset[i]); } else if (d > 2) { d = CFF.Charset = d + CFF.baseoffset; onechar(0, 0); gid = 1; switch (contents[d++]) { case 0: for (i = 1; i < nc; i++) { j = pbe16(&contents[d]); d += 2; onechar(gid++, j); } break; case 1: i = nc - 1; while (i > 0) { first = pbe16(&contents[d]); d += 2; nLeft = contents[d++] & 0377; for (j = 0; j <= nLeft && gid < nc; j++) onechar(gid++, first + j); i -= nLeft + 1; } break; default: error("unknown Charset table format %d", contents[d-1]); case 2: i = nc - 1; while (i > 0) { first = pbe16(&contents[d]); d += 2; nLeft = pbe16(&contents[d]); d += 2; for (j = 0; j <= nLeft && gid < nc; j++) onechar(gid++, first + j); i -= nLeft + 1; } } } else error("invalid Charset offset"); } static void build_ExtraStrings(void) { int c, i; char *sp; if (CFF.String == NULL || CFF.String->count == 0) return; ExtraStrings = calloc(CFF.String->count, sizeof *ExtraStrings); sp = ExtraStringSpace = malloc(CFF.String->count + CFF.String->offset[CFF.String->count]); for (c = 0; c < CFF.String->count; c++) { ExtraStrings[c] = sp; for (i = CFF.String->offset[c]; i < CFF.String->offset[c+1]; i++) *sp++ = contents[i]; *sp++ = 0; } nExtraStrings = c; } static void otfalloc(int _nc) { nc = _nc; gid2sid = calloc(nc, sizeof *gid2sid); if (a) { afmalloc(a, nc); a->gid2tr = calloc(nc, sizeof *a->gid2tr); } } static void get_CFF(void) { size_t o; char buf[4]; if (pos_CFF < 0) error("no CFF table"); CFF.baseoffset = o = table_directories[pos_CFF].offset; if (o + 4 >= size) error("no CFF header"); memcpy(buf, &contents[o], 4); o += 4; if (buf[0] != 1) error("can only handle CFF major version 1"); CFF.Name = get_INDEX(&o); CFF.Top_DICT = get_INDEX(&o); CFF.String = get_INDEX(&o); build_ExtraStrings(); CFF.Global_Subr = get_INDEX(&o); o = get_CFF_Top_DICT_Entry(17); o += CFF.baseoffset; CFF.CharStrings = get_INDEX(&o); if (CFF.Name->count != 1) error("cannot handle CFF data with more than one font"); a->fontname = malloc(CFF.Name->offset[1] - CFF.Name->offset[0] + 1); memcpy(a->fontname, &contents[CFF.Name->offset[0]], CFF.Name->offset[1] - CFF.Name->offset[0]); a->fontname[CFF.Name->offset[1] - CFF.Name->offset[0]] = 0; #ifdef DUMP print(SHOW_NAME, "name %s", a->fontname); #endif if (CFF.CharStrings == NULL || CFF.CharStrings->count == 0) error("no characters in font"); otfalloc(CFF.CharStrings->count); get_CFF_Charset(); afmremap(a); } /*ARGSUSED*/ static void get_ttf_post_1_0(int o __unused) { int i; otfalloc(numGlyphs); for (i = 0; i < numGlyphs; i++) onechar(i, i); } static void get_ttf_post_2_0(int o) { size_t numberOfGlyphs; size_t numberNewGlyphs; size_t i, j, n; char *cp, *sp; numberOfGlyphs = pbe16(&contents[o+32]); if (34+2*numberOfGlyphs > table_directories[pos_post].length) error("numberOfGlyphs value in post table too large"); otfalloc(numberOfGlyphs); numberNewGlyphs = 0; for (i = 0; i < numberOfGlyphs; i++) { n = pbe16(&contents[o+34+2*i]); if (n >= 258) { n -= 258; if (n >= numberNewGlyphs) numberNewGlyphs = n + 1; } } ExtraStrings = calloc(numberNewGlyphs, sizeof *ExtraStrings); sp = ExtraStringSpace = malloc(table_directories[pos_post].length - 34 - 2*numberOfGlyphs); cp = &contents[o+34+2*numberOfGlyphs]; for (i = 0; i < numberNewGlyphs; i++) { if (cp >= &contents[o + table_directories[pos_post].length]) break; ExtraStrings[i] = sp; n = *cp++ & 0377; if (&cp[n] > &contents[o + table_directories[pos_post].length]) break; for (j = 0; j < n; j++) *sp++ = *cp++; *sp++ = 0; } nExtraStrings = i; for (i = 0; i < numberOfGlyphs; i++) { n = pbe16(&contents[o+34+2*i]); onechar(i, n); } } static void get_ttf_post_2_5(int o) { size_t numberOfGlyphs, i; int offset; numberOfGlyphs = pbe16(&contents[o+32]); if (34+numberOfGlyphs > table_directories[pos_post].length) error("numberOfGlyphs value in post table too large"); otfalloc(numberOfGlyphs); for (i = 0; i < numberOfGlyphs; i++) { offset = ((signed char *)contents)[o+34+i]; onechar(i, i + offset); } } static void unichar(int gid, int c) { int i; char *sp; for (i = 0; WGL[i].s; i++) if (WGL[i].u == c) { onechar(gid, i); return; } if (ExtraStrings == NULL) ExtraStrings = calloc(nc, sizeof *ExtraStrings); if (ExtraStringSpace == NULL) ExtraStringSpace = malloc(nc * 12); sp = &ExtraStringSpace[ExtraStringSpacePos]; ExtraStrings[nExtraStrings] = sp; ExtraStringSpacePos += snprintf(sp, 10, "uni%04X", c) + 1; onechar(gid, nWGL + nExtraStrings++); } #if !defined (DPOST) && !defined (DUMP) #include "unimap.h" static void addunimap(int gid, int c) { struct unimap ***up, *u, *ut; int x, y; if (c != 0 && (c&~0xffff) == 0) { if (a->unimap == NULL) a->unimap = calloc(256, sizeof *up); up = a->unimap; x = c >> 8; y = c & 0377; if (up[x] == NULL) up[x] = calloc(256, sizeof **up); u = calloc(1, sizeof *u); u->u.code = gid; if (up[x][y] != NULL) { for (ut = up[x][y]; ut->next; ut = ut->next); ut->next = u; } else up[x][y] = u; } } #endif /* !DPOST && !DUMP */ #if defined(DPOST) || defined(DUMP) #define __actual_use __unused #else #define __actual_use #endif static void addunitab(int c __actual_use, int u __actual_use) { #if !defined (DPOST) && !defined (DUMP) if (c >= a->nunitab) { a->unitab = realloc(a->unitab, (c+1) * sizeof *a->unitab); memset(&a->unitab[a->nunitab], 0, (c+1-a->nunitab) * sizeof *a->unitab); a->nunitab = c+1; } a->unitab[c] = u; addunimap(c, u); #endif } static char *got_gid; static void got_mapping(int c, unsigned long gid, int addchar) { if (gid < nc) { if (addchar) { if (!got_gid[gid]) { unichar(gid, c); got_gid[gid] = 1; } } else { addunitab(a->gid2tr[gid].ch1, c); addunitab(a->gid2tr[gid].ch2, c); } } } static int get_ms_unicode_cmap4(int o, int addchar) { /* int length; */ int segCount; int endCount; int startCount; int idDelta; int idRangeOffset; /* int glyphIdArray; */ int c, e, i, d, r, s, gid; size_t x; /* length = */ pbe16(&contents[o+2]); segCount = pbe16(&contents[o+6]) / 2; endCount = o + 14; startCount = endCount + 2*segCount + 2; idDelta = startCount + 2*segCount; idRangeOffset = idDelta + 2*segCount; /* glyphIdArray = idRangeOffset + 2*segCount; */ for (i = 0; i < segCount; i++) { s = pbe16(&contents[startCount+2*i]); e = pbe16(&contents[endCount+2*i]); d = pbe16(&contents[idDelta+2*i]); r = pbe16(&contents[idRangeOffset+2*i]); for (c = s; c <= e; c++) { if (r) { x = r + 2*(c - s) + idRangeOffset+2*i; if (x+1 >= table_directories[pos_cmap].offset + table_directories[pos_cmap].length) continue; gid = pbe16(&contents[x]); if (gid != 0) gid += d; } else gid = c + d; gid &= 0xffff; if (gid != 0) got_mapping(c, gid, addchar); } } return 1; } static int get_ms_unicode_cmap12(int o, int addchar) { /* int length; */ int nGroups; int startCharCode; int endCharCode; int startGlyphID; int c, i, gid; /* length = */ pbe32(&contents[o+4]); nGroups = pbe32(&contents[o+12]); o += 16; for (i = 0; i < nGroups; i++) { startCharCode = pbe32(&contents[o]); endCharCode = pbe32(&contents[o+4]); startGlyphID = pbe32(&contents[o+8]); for (c = startCharCode, gid = startGlyphID; c <= endCharCode; c++, gid++) got_mapping(c, gid, addchar); o += 12; } return 1; } static int get_ms_unicode_cmap(int o, int addchar) { int format; format = pbe16(&contents[o]); switch (format) { case 4: return get_ms_unicode_cmap4(o, addchar); case 12: return get_ms_unicode_cmap12(o, addchar); default: return 0; } } static int get_cmap(int addchar) { size_t nTables, i; int platformID; int encodingID; int offset; int o; int want_tbl; int gotit = 0; if (pos_cmap < 0) { if (addchar) error("no cmap table"); return gotit; } o = table_directories[pos_cmap].offset; if (pbe16(&contents[o]) != 0) { if (addchar) error("can only handle version 0 cmap tables"); return gotit; } nTables = pbe16(&contents[o+2]); if (4 + 8*nTables > table_directories[pos_cmap].length) { if (addchar) error("cmap table too small for values inside"); return gotit; } if (addchar) otfalloc(numGlyphs); want_tbl = -1; for (i = 0; i < nTables; i++) { platformID = pbe16(&contents[o+4+8*i]); encodingID = pbe16(&contents[o+4+8*i+2]); if ((platformID == 3 && encodingID == 10) || (want_tbl < 0 && ((platformID == 3 && (encodingID == 0 || encodingID == 1)) || platformID == 0))) want_tbl = i; } if (want_tbl >= 0) { offset = pbe32(&contents[o+4+8*want_tbl+4]); gotit |= get_ms_unicode_cmap(o + offset, addchar); } return gotit; } static void get_ttf_post_3_0(int o __unused) { int i, n; int gotit; char *sp; size_t l; ttf = 2; got_gid = calloc(numGlyphs, sizeof *got_gid); gotit = get_cmap(1); if (gotit <= 0) { ttf = 3; ExtraStrings = calloc(numGlyphs, sizeof *ExtraStrings); l = n = 12 * numGlyphs; sp = ExtraStringSpace = malloc(l); n_strcpy(sp, ".notdef", l); ExtraStrings[0] = sp; sp += 8; nExtraStrings = 1; onechar(0, 0); for (i = 1; i < numGlyphs; i++) { ExtraStrings[i] = sp; sp += snprintf(sp, n - (sp - ExtraStringSpace), "index0x%02X", i) + 1; if (sp >= &ExtraStringSpace[n]) sp = &ExtraStringSpace[n]; nExtraStrings++; onechar(i, i); } } else { n = numGlyphs * 12; if (ExtraStrings == NULL) ExtraStrings = calloc(numGlyphs, sizeof *ExtraStrings); if (ExtraStringSpace == NULL) ExtraStringSpace = malloc(n); sp = &ExtraStringSpace[ExtraStringSpacePos]; for (i = 0; i < numGlyphs; i++) if (got_gid[i] == 0) { ExtraStrings[nExtraStrings] = sp; sp += snprintf(sp, n - (sp - ExtraStringSpace), "index0x%02X", i) + 1; if (sp >= &ExtraStringSpace[n]) sp = &ExtraStringSpace[n]; onechar(i, nWGL + nExtraStrings++); } } free(got_gid); got_gid = NULL; } static void ttfname(void) { if (a) { if (PostScript_name && strchr(PostScript_name, ' ') == NULL) a->fontname = strdup(PostScript_name); else { const char *base = a->Font.namefont[0] ? a->Font.namefont : a->base; size_t l = strlen(base) + 5; a->fontname = malloc(l); n_strcpy(a->fontname, base, l); n_strcat(a->fontname, ".TTF", l); } #ifdef DUMP print(SHOW_NAME, "name %s", a->fontname); #endif } } static void get_ttf(void) { long o; int Version; if (pos_post < 0) error("no post table"); o = table_directories[pos_post].offset; switch (Version = pbe32(&contents[o])) { case 0x00010000: ttfname(); get_ttf_post_1_0(o); break; case 0x00020000: ttfname(); get_ttf_post_2_0(o); break; case 0x00025000: ttfname(); get_ttf_post_2_5(o); break; case 0x00030000: ttfname(); get_ttf_post_3_0(o); break; default: error("cannot handle TrueType fonts with " "version %d.%d post table", Version>>16, (Version&0xffff) >> 12); } if (a) afmremap(a); } static void get_head(void) { long o; if (pos_head < 0) error("no head table"); o = table_directories[pos_head].offset; if (pbe32(&contents[o]) != 0x00010000) error("can only handle version 1.0 head tables"); unitsPerEm = pbe16(&contents[o + 18]); xMin = (int16_t)pbe16(&contents[o + 36]); yMin = (int16_t)pbe16(&contents[o + 38]); xMax = (int16_t)pbe16(&contents[o + 40]); yMax = (int16_t)pbe16(&contents[o + 42]); indexToLocFormat = pbe16(&contents[o + 50]); } static void get_post(void) { long o; isFixedPitch = 0; minMemType42 = maxMemType42 = -1; if (pos_post < 0) return; o = table_directories[pos_post].offset; if (pbe32(&contents[o]) > 0x00030000) return; if (table_directories[pos_post].length >= 16) isFixedPitch = pbe32(&contents[o+12]); if (a) a->isFixedPitch = isFixedPitch; if (table_directories[pos_post].length >= 20) minMemType42 = pbe32(&contents[o+16]); if (table_directories[pos_post].length >= 24) maxMemType42 = pbe32(&contents[o+20]); } static void get_maxp(void) { if (pos_maxp < 0) error("no maxp table"); numGlyphs = pbe16(&contents[table_directories[pos_maxp].offset+4]); } static char * build_string(int o, int length, int ucs) { char *string, *sp; int i; int ch; sp = string = malloc(3*length + 1); for (i = 0; i < length; i++) { if (ucs) { ch = pbe16(&contents[o+i]); i++; } else ch = contents[o+i]&0377; if ((ch & 0200) == 0) { switch (ch) { case '\\': case '(': case ')': *sp++ = '\\'; /*FALLTHRU*/ default: *sp++ = ch; } } else if (ch == 169) { /* * 169 happens to be COPYRIGHT SIGN in both MacRoman and * Unicode. */ *sp++ = '('; *sp++ = 'c'; *sp++ = ')'; } } *sp = 0; return string; } static void get_name(void) { char **sp; long o; int count; int stringOffset; int i; int platformID; int encodingID; int languageID; int nameID; int length; int offset; if (pos_name < 0) return; o = table_directories[pos_name].offset; if (pbe16(&contents[o]) != 0) return; count = pbe16(&contents[o+2]); stringOffset = o + pbe16(&contents[o+4]); for (i = 0; i < count; i++) { platformID = pbe16(&contents[o+6+12*i]); encodingID = pbe16(&contents[o+6+12*i+2]); languageID = pbe16(&contents[o+6+12*i+4]); nameID = pbe16(&contents[o+6+12*i+6]); length = pbe16(&contents[o+6+12*i+8]); offset = pbe16(&contents[o+6+12*i+10]); switch (nameID) { case 0: sp = &Copyright; break; case 6: sp = &PostScript_name; break; case 7: sp = &Notice; break; default: sp = NULL; } if (sp != NULL && *sp == NULL) { if (platformID == 1 && encodingID == 0 && languageID == 0) *sp = build_string(stringOffset+offset, length, 0); else if (platformID == 3 && languageID == 0x409) *sp = build_string(stringOffset+offset, length, 1); } } } static void get_OS_2(void) { long o; if (pos_OS_2 < 0) goto dfl; o = table_directories[pos_OS_2].offset; if (pbe16(&contents[o]) > 0x0003) goto dfl; if (table_directories[pos_OS_2].length >= 6) WeightClass = pbe16(&contents[o+4]); else WeightClass = -1; if (table_directories[pos_OS_2].length >= 10) fsType = pbe16(&contents[o+8]); else fsType = -1; if (table_directories[pos_OS_2].length >= 72) { if (a) { a->ascender = _unitconv((int16_t)pbe16(&contents[o + 68])); a->descender = _unitconv((int16_t)pbe16(&contents[o + 70])); } } if (table_directories[pos_OS_2].length >= 92) { if (a) { a->xheight = _unitconv(pbe16(&contents[o + 88])); a->capheight = _unitconv(pbe16(&contents[o + 90])); } } else { dfl: if (a) { a->xheight = 500; a->capheight = 700; } } } static char * GID2SID(unsigned long gid) { if (gid >= nc) return NULL; return getSID(gid2sid[gid]); } int fprintenc(FILE *fd, const char *enc) { const char *cp; for (cp = enc; *cp && !isspace(*cp); cp++); if (*cp) { return fprintf(fd, "(%s) cvn", enc); } else { return fprintf(fd, "/%s", enc); } } #ifndef DPOST static int ScriptList; static int FeatureList; static int LookupList; struct cov { int offset; int CoverageFormat; int RangeCount; int GlyphCount; int cnt; int gid; }; static struct cov * open_cov(int o) { struct cov *cp; cp = calloc(1, sizeof *cp); cp->offset = o; switch (cp->CoverageFormat = pbe16(&contents[o])) { default: free(cp); return NULL; case 1: cp->GlyphCount = pbe16(&contents[o+2]); return cp; case 2: cp->RangeCount = pbe16(&contents[o+2]); cp->gid = -1; return cp; } } static unsigned long get_cov(struct cov *cp) { int Start, End; switch (cp->CoverageFormat) { default: return (unsigned long)-1; case 1: if (cp->cnt < cp->GlyphCount) return pbe16(&contents[cp->offset+4+2*cp->cnt++]); return (unsigned long)-1; case 2: while (cp->cnt < cp->RangeCount) { Start = pbe16(&contents[cp->offset+4+6*cp->cnt]); End = pbe16(&contents[cp->offset+4+6*cp->cnt+2]); if (cp->gid > End) { cp->gid = -1; cp->cnt++; continue; } if (cp->gid < Start) cp->gid = Start; return cp->gid++; } return (unsigned long)-1; } } static void free_cov(struct cov *cp) { free(cp); } struct class { int offset; int ClassFormat; int StartGlyph; int GlyphCount; int ClassRangeCount; int cnt; int gid; }; static struct class * open_class(int o) { struct class *cp; cp = calloc(1, sizeof *cp); cp->offset = o; switch (cp->ClassFormat = pbe16(&contents[o])) { default: free(cp); return NULL; case 1: cp->StartGlyph = pbe16(&contents[o+2]); cp->GlyphCount = pbe16(&contents[o+4]); return cp; case 2: cp->ClassRangeCount = pbe16(&contents[o+2]); cp->gid = -1; return cp; } } static inline void get_class(struct class *cp, int *gp, int *vp) { int Start, End; switch (cp->ClassFormat) { case 1: if (cp->cnt < cp->GlyphCount) { *gp = cp->StartGlyph + cp->cnt; *vp = _pbe16(&contents[cp->offset+6+2*cp->cnt]); cp->cnt++; return; } goto dfl; case 2: while (cp->cnt < cp->ClassRangeCount) { Start = _pbe16(&contents[cp->offset+4+6*cp->cnt]); End = _pbe16(&contents[cp->offset+4+6*cp->cnt+2]); if (cp->gid > End) { cp->gid = -1; cp->cnt++; continue; } if (cp->gid < Start) cp->gid = Start; *gp = cp->gid++; *vp = _pbe16(&contents[cp->offset+4+6*cp->cnt+4]); return; } /*FALLTHRU*/ default: dfl: *gp = -1; *vp = -1; return; } } static void free_class(struct class *cp) { free(cp); } static int get_value_size(int ValueFormat1, int ValueFormat2) { int i, sz = 0; for (i = 0; i < 16; i++) if (ValueFormat1 & (1<= nc ? NULL : nametable[gid]) static inline void kernpair(unsigned long first, unsigned long second, int x) { struct namecache *np1, *np2; if (x == 0 || (x = _unitconv(x)) == 0) return; np1 = GID2name(first); np2 = GID2name(second); if (np1 == NULL || np2 == NULL) return; if (np1->fival[0] != NOCODE && np2->fival[0] != NOCODE) afmaddkernpair(a, np1->fival[0], np2->fival[0], x); if (np1->fival[0] != NOCODE && np2->fival[1] != NOCODE) afmaddkernpair(a, np1->fival[0], np2->fival[1], x); if (np1->fival[1] != NOCODE && np2->fival[0] != NOCODE) afmaddkernpair(a, np1->fival[1], np2->fival[0], x); if (np1->fival[1] != NOCODE && np2->fival[1] != NOCODE) afmaddkernpair(a, np1->fival[1], np2->fival[1], x); } static void kernfinish(void) { free(nametable); } #endif /* !DUMP */ static void get_PairValueRecord(int first, int ValueFormat1, int ValueFormat2 __unused, int o) { int second; int x; second = _pbe16(&contents[o]); x = get_x_adj(ValueFormat1, o+2); kernpair(first, second, x); } static void get_PairSet(int first, int ValueFormat1, int ValueFormat2, int o) { int PairValueCount; int i; int sz; PairValueCount = _pbe16(&contents[o]); sz = get_value_size(ValueFormat1, ValueFormat2); for (i = 0; i < PairValueCount; i++) get_PairValueRecord(first, ValueFormat1, ValueFormat2, o+2+(2+sz)*i); } static void get_PairPosFormat1(int o) { struct cov *cp; int Coverage; int ValueFormat1, ValueFormat2; int PairSetCount; int first; int i; Coverage = o + pbe16(&contents[o+2]); if ((cp = open_cov(Coverage)) == NULL) return; ValueFormat1 = pbe16(&contents[o+4]); ValueFormat2 = pbe16(&contents[o+6]); PairSetCount = pbe16(&contents[o+8]); for (i = 0; i < PairSetCount && (first = get_cov(cp)) >= 0; i++) get_PairSet(first, ValueFormat1, ValueFormat2, o + pbe16(&contents[o+10+2*i])); free_cov(cp); } static void get_PairPosFormat2(int o) { struct class *c1, *c2; int ValueFormat1, ValueFormat2; int ClassDef1, ClassDef2; int Class1Count, Class2Count; int g, *g2 = NULL; int v, *v2 = NULL; int sz; int i, n, a; int x; ValueFormat1 = pbe16(&contents[o+4]); ValueFormat2 = pbe16(&contents[o+6]); ClassDef1 = o + pbe16(&contents[o+8]); ClassDef2 = o + pbe16(&contents[o+10]); Class1Count = pbe16(&contents[o+12]); Class2Count = pbe16(&contents[o+14]); sz = get_value_size(ValueFormat1, ValueFormat2); if ((c1 = open_class(ClassDef1)) != NULL) { if ((c2 = open_class(ClassDef2)) != NULL) { n = a = 0; while (get_class(c2, &g, &v), g >= 0) { if (v < 0 || v >= Class2Count) continue; if (n >= a) { a = a ? 2*a : 128; g2 = realloc(g2, a * sizeof *g2); v2 = realloc(v2, a * sizeof *v2); } g2[n] = g; v2[n] = v; n++; } while (get_class(c1, &g, &v), g >= 0) { if (v < 0 || v >= Class1Count) continue; for (i = 0; i < n; i++) { x = get_x_adj(ValueFormat1, o + 16 + v*Class2Count*sz + v2[i]*sz); kernpair(g, g2[i], x); } } free_class(c2); } free_class(c1); } free(g2); free(v2); } static void get_GPOS_kern1(int _t __unused, int o, const char *_name __unused) { int PosFormat; got_kern = 1; switch (PosFormat = pbe16(&contents[o])) { case 1: get_PairPosFormat1(o); break; } } static void get_GPOS_kern2(int _t __unused, int o, const char *_name __unused) { int PosFormat; got_kern = 1; switch (PosFormat = pbe16(&contents[o])) { case 2: get_PairPosFormat2(o); break; } } static void get_Ligature(int first, int o) { int LigGlyph; unsigned int CompCount; int Component[16]; unsigned int i; char *gn; LigGlyph = pbe16(&contents[o]); CompCount = pbe16(&contents[o+2]); for (i = 0; i < CompCount - 1 && i < sizeof Component / sizeof *Component - 1; i++) { Component[i] = pbe16(&contents[o+4+2*i]); } Component[i] = -1; gn = GID2SID(first); if (gn && gn[0] == 'f' && gn[1] == 0 && CompCount > 1) { gn = GID2SID(Component[0]); if (gn && gn[0] && gn[1] == 0) switch (gn[0]) { case 'f': if (CompCount == 2) { gn = GID2SID(LigGlyph); if (gn && (strcmp(gn, "ff") == 0 || strcmp(gn, "f_f") == 0)) a->Font.ligfont |= LFF; } else if (CompCount == 3) { gn = GID2SID(Component[1]); if (gn[0] && gn[1] == 0) switch (gn[0]) { case 'i': gn = GID2SID(LigGlyph); if (gn && (strcmp(gn, "ffi") == 0 || strcmp(gn, "f_f_i") == 0)) a->Font.ligfont |= LFFI; break; case 'l': gn = GID2SID(LigGlyph); if (gn && (strcmp(gn, "ffl") == 0 || strcmp(gn, "f_f_l") == 0)) a->Font.ligfont |= LFFL; break; } } break; case 'i': if (CompCount == 2) { gn = GID2SID(LigGlyph); if (gn && (strcmp(gn, "fi") == 0 || strcmp(gn, "f_i") == 0)) a->Font.ligfont |= LFI; } break; case 'l': if (CompCount == 2) { gn = GID2SID(LigGlyph); if (gn && (strcmp(gn, "fl") == 0 || strcmp(gn, "f_l") == 0)) a->Font.ligfont |= LFL; } break; } } } static void get_LigatureSet(int first, int o) { int LigatureCount; int i; LigatureCount = pbe16(&contents[o]); for (i = 0; i < LigatureCount; i++) get_Ligature(first, o + pbe16(&contents[o+2+2*i])); } static void get_LigatureSubstFormat1(int _t __unused, int o, const char *_name __unused) { struct cov *cp; int Coverage; int LigSetCount; int i; int first; if (pbe16(&contents[o]) != 1) return; Coverage = o + pbe16(&contents[o+2]); if ((cp = open_cov(Coverage)) == NULL) return; LigSetCount = pbe16(&contents[o+4]); for (i = 0; i < LigSetCount && (first = get_cov(cp)) >= 0; i++) get_LigatureSet(first, o + pbe16(&contents[o+6+2*i])); free_cov(cp); } static struct feature * add_feature(const char *name) { int i; char *np; if (a->features == NULL) a->features = calloc(1, sizeof *a->features); for (i = 0; a->features[i]; i++) if (strcmp(a->features[i]->name, name) == 0) return a->features[i]; a->features = realloc(a->features, (i+2) * sizeof *a->features); a->features[i] = calloc(1, sizeof **a->features); a->features[i]->name = strdup(name); for (np = a->features[i]->name; *np; np++) if (*np == ' ') { *np = 0; break; } a->features[i+1] = NULL; return a->features[i]; } static void add_substitution_pair1(struct feature *fp, int ch1, int ch2) { fp->pairs = realloc(fp->pairs, (fp->npairs+1) * sizeof *fp->pairs); fp->pairs[fp->npairs].ch1 = ch1; fp->pairs[fp->npairs].ch2 = ch2; fp->npairs++; } static void add_substitution_pair(struct feature *fp, int ch1, int ch2) { if (ch1 && ch2) { #ifdef DUMP print(SHOW_SUBSTITUTIONS, "feature %s substitution %s %s", fp->name, GID2SID(ch1), GID2SID(ch2)); #endif if (a->gid2tr[ch1].ch1) { if (a->gid2tr[ch2].ch1) add_substitution_pair1(fp, a->gid2tr[ch1].ch1, a->gid2tr[ch2].ch1); if (a->gid2tr[ch2].ch2) add_substitution_pair1(fp, a->gid2tr[ch1].ch1, a->gid2tr[ch2].ch2); } if (a->gid2tr[ch1].ch2) { if (a->gid2tr[ch2].ch1) add_substitution_pair1(fp, a->gid2tr[ch1].ch2, a->gid2tr[ch2].ch1); if (a->gid2tr[ch2].ch2) add_substitution_pair1(fp, a->gid2tr[ch1].ch2, a->gid2tr[ch2].ch2); } } } static void get_SingleSubstitutionFormat1(int o, const char *name) { struct feature *fp; struct cov *cp; unsigned long c, d; int Coverage; unsigned long DeltaGlyphID; if (pbe16(&contents[o]) != 1) return; Coverage = o + pbe16(&contents[o+2]); if ((cp = open_cov(Coverage)) == NULL) return; DeltaGlyphID = pbe16(&contents[o+4]); fp = add_feature(name); while ((c = get_cov(cp)) != (unsigned long)-1) if ((d = c + DeltaGlyphID) < nc) add_substitution_pair(fp, c, d); free_cov(cp); } static void get_SingleSubstitutionFormat2(int o, const char *name) { struct feature *fp; struct cov *cp; int Coverage; int GlyphCount; int c, i; if (pbe16(&contents[o]) != 2) return; Coverage = o + pbe16(&contents[o+2]); if ((cp = open_cov(Coverage)) == NULL) return; GlyphCount = pbe16(&contents[o+4]); fp = add_feature(name); for (i = 0; i < GlyphCount && (c = get_cov(cp)) >= 0; i++) add_substitution_pair(fp, c, pbe16(&contents[o+6+2*i])); free_cov(cp); } static void get_substitutions(int type, int o, const char *name) { int format; format = pbe16(&contents[o]); switch (type) { case 1: switch (format) { case 1: get_SingleSubstitutionFormat1(o, name); break; case 2: get_SingleSubstitutionFormat2(o, name); break; } } } static void get_lookup(int o, int type, const char *name, void (*func)(int, int, const char *)) { int i, j, t, x, y; int LookupCount; int SubTableCount; LookupCount = pbe16(&contents[o+2]); for (i = 0; i < LookupCount; i++) { x = pbe16(&contents[o+4+2*i]); y = pbe16(&contents[LookupList+2+2*x]); if ((t = pbe16(&contents[LookupList+y])) == type || type < 0) { SubTableCount = pbe16(&contents[LookupList+y+4]); for (j = 0; j < SubTableCount; j++) func(t, LookupList+y + pbe16(&contents[LookupList+y+6+2*j]), name); } } } static void get_LangSys(int o, const char *name, int type, void (*func)(int, int, const char *)) { char nb[5]; int i, x; int FeatureCount; int ReqFeatureIndex; ReqFeatureIndex = pbe16(&contents[o+2]); FeatureCount = pbe16(&contents[o+4]); if (ReqFeatureIndex != 0xFFFF) FeatureCount += ReqFeatureIndex; for (i = 0; i < FeatureCount; i++) { x = pbe16(&contents[o+6+2*i]); if (name == NULL || memcmp(&contents[FeatureList+2+6*x], name, 4) == 0) { memcpy(nb, &contents[FeatureList+2+6*x], 4); nb[4] = 0; get_lookup(FeatureList + pbe16(&contents[FeatureList+2+6*x+4]), type, nb, func); } } } static void get_feature(int table, const char *name, int type, void (*func)(int, int, const char *)) { long o; int i; int DefaultLangSys; int ScriptCount; int Script; if (table < 0) return; o = table_directories[table].offset; if (pbe32(&contents[o]) != 0x00010000) return; ScriptList = o + pbe16(&contents[o+4]); FeatureList = o + pbe16(&contents[o+6]); LookupList = o + pbe16(&contents[o+8]); ScriptCount = pbe16(&contents[ScriptList]); for (i = 0; i < ScriptCount; i++) if (memcmp(&contents[ScriptList+2+6*i], "DFLT", 4) == 0 || memcmp(&contents[ScriptList+2+6*i], "latn", 4) == 0) { Script = ScriptList + pbe16(&contents[ScriptList+2+6*i+4]); DefaultLangSys = Script + pbe16(&contents[Script]); get_LangSys(DefaultLangSys, name, type, func); } } static void get_kern_subtable(int o) { int length; int coverage; int nPairs; int i; int left, right, value; if (pbe16(&contents[o]) != 0) return; length = pbe16(&contents[o+2]); coverage = pbe16(&contents[o+4]); if ((coverage&1) != 1 || /* check: horizontal data */ (coverage&2) != 0 || /* . . . kerning values */ (coverage&4) != 0 || /* . . . not perpendicular */ ((coverage&0xff00) != 0)) /* . . . format 0 */ return; got_kern = 1; nPairs = pbe16(&contents[o+6]); for (i = 0; i < nPairs; i++) { if (o + 14 + 6 * (i+1) > o + length) break; left = pbe16(&contents[o+14+6*i]); right = pbe16(&contents[o+14+6*i+2]); value = (int16_t)pbe16(&contents[o+14+6*i+4]); kernpair(left, right, value); } } static void get_kern(void) { unsigned long o; int nTables; int i, length; if (pos_kern < 0) return; o = table_directories[pos_kern].offset; if (pbe16(&contents[o]) != 0) return; nTables = pbe16(&contents[o+2]); o += 4; for (i = 0; i < nTables; i++) { if (o + 6 > table_directories[pos_kern].offset + table_directories[pos_kern].length) return; length = pbe16(&contents[o+2]); if (o + length > table_directories[pos_kern].offset + table_directories[pos_kern].length) return; get_kern_subtable(o); o += length; } } #endif /* !DPOST */ #ifdef DPOST static void checkembed(void) { /* * Do not check the embedding bits under the assumption that the * resulting PostScript file is sent to a printer. This follows * Adobe's "Font Embedding Guidelines for Adobe Third-party * Developers", 5/16/05, p. 8. * * It is the responsibility of a following distiller command or * the like to check the fsType bit then. * if (fsType != -1 && (fsType&0x030e) == 0x0002 || fsType & 0x0200) error("embedding not allowed"); */ } int otfcff(const char *path, char *_contents, size_t _size, size_t *offset, size_t *length) { int ok = 0; (void) &ok; a = NULL; filename = path; contents = _contents; size = _size; if (setjmp(breakpoint) == 0) { get_offset_table(); get_table_directories(); get_OS_2(); if (pos_CFF < 0) error("no CFF table"); checkembed(); *offset = table_directories[pos_CFF].offset; *length = table_directories[pos_CFF].length; } else ok = -1; return ok; } static uint32_t CalcTableChecksum(uint32_t sum, const char *cp, int length) { while (length > 0) { sum += pbe32(cp); cp += 4; length -= 4; } return sum; } static void sfnts1(struct table *tp, int *offset, uint32_t *ccs, FILE *fp __unused) { int o, length; o = table_directories[*tp->pos].offset; length = table_directories[*tp->pos].length; if (tp->in_sfnts == 2) /* head table */ memset(&contents[o+8], 0, 4); /* checkSumAdjustment */ tp->checksum = CalcTableChecksum(0, &contents[o], length); *ccs = CalcTableChecksum(*ccs, tp->name, 4); *ccs += tp->checksum; *ccs += *offset; *ccs += length; *offset += length; } static void sfnts1a(struct table *tp, int *offset, uint32_t *ccs, FILE *fp) { int o, length, m; o = table_directories[*tp->pos].offset; length = table_directories[*tp->pos].length; if (tp->in_sfnts == 2) { *ccs -= 0xB1B0AFBA; contents[o+8] = (*ccs&0xff000000) >> 24; contents[o+9] = (*ccs&0x00ff0000) >> 16; contents[o+10] = (*ccs&0x0000ff00) >> 8; contents[o+11] = (*ccs&0x000000ff); } fprintf(fp, "%08X%08X%08X%08X", pbe32(tp->name), (unsigned int)tp->checksum, *offset, length); if ((m = length % 4) != 0) length += 4 - m; *offset += length; } static int start_of_next_glyph(int *start, int offset) { int i = *start; int last = INT_MAX; int cur; int o; int tms = 0; if (pos_loca < 0) error("no loca table"); o = table_directories[pos_loca].offset; for (;;) { if (i >= numGlyphs) { i = 0; if (tms++ == 4) return -1; } cur = indexToLocFormat ? pbe32(&contents[o + 4*i]) : pbe16(&contents[o + 2*i]) * 2; if (offset > last && offset < cur) { *start = i; return cur; } if (cur < last) last = cur; i++; } } static void sfnts2(struct table *tp, FILE *fp) { const char hex[] = "0123456789ABCDEF"; int i, o, length, next = -1; int start = 0; o = table_directories[*tp->pos].offset; length = table_directories[*tp->pos].length; putc('<', fp); for (i = 0; i < length; i++) { if (i && i % 36 == 0) putc('\n', fp); if (i && i % 60000 == 0 && tp->in_sfnts == 3) { /* split string at start of next glyph */ next = start_of_next_glyph(&start, i); } if (i == next) fprintf(fp, "00><"); if (i && i % 65534 == 0 && tp->in_sfnts != 3) fprintf(fp, "00>\n<"); putc(hex[(contents[o+i]&0360)>>4], fp); putc(hex[contents[o+i]&017], fp); } while (i++ % 4) fprintf(fp, "00"); fprintf(fp, "00>\n"); } static void build_sfnts(FILE *fp) { int i, o, n; unsigned short nTables; unsigned short searchRange; unsigned short entrySelector; unsigned short rangeShift; uint32_t ccs; nTables = 0; for (i = 0; tables[i].name; i++) if (tables[i].in_sfnts && *tables[i].pos >= 0) nTables++; entrySelector = 0; for (searchRange = 1; searchRange*2 < nTables; searchRange *= 2) entrySelector++; searchRange *= 16; rangeShift = nTables * 16 - searchRange; fprintf(fp, "<%08X%04hX%04hX%04hX%04hX\n", 0x00010000, nTables, searchRange, entrySelector, rangeShift); ccs = 0x00010000 + (nTables<<16) + searchRange + (entrySelector<<16) + rangeShift; o = 12 + nTables * 16; for (i = 0; tables[i].name; i++) if (tables[i].in_sfnts && *tables[i].pos >= 0) sfnts1(&tables[i], &o, &ccs, fp); o = 12 + nTables * 16; n = 0; for (i = 0; tables[i].name; i++) { if (tables[i].in_sfnts && *tables[i].pos >= 0) { if (n++) putc('\n', fp); sfnts1a(&tables[i], &o, &ccs, fp); } } fprintf(fp, "00>\n"); for (i = 0; tables[i].name; i++) if (tables[i].in_sfnts && *tables[i].pos >= 0) sfnts2(&tables[i], fp); } int otft42(char *font, char *path, char *_contents, size_t _size, FILE *fp) { const char *cp; int ok = 0; unsigned long i; (void) &ok; a = NULL; filename = path; contents = _contents; size = _size; if (setjmp(breakpoint) == 0) { get_offset_table(); get_table_directories(); get_head(); get_OS_2(); get_post(); get_maxp(); get_name(); if (ttf == 0) error("not a TrueType font file"); checkembed(); get_ttf(); if (minMemType42 >= 0 && maxMemType42 >= 0 && (minMemType42 || maxMemType42)) fprintf(fp, "%%%%VMUsage: %d %d\n", minMemType42, maxMemType42); fprintf(fp, "11 dict begin\n"); fprintf(fp, "/FontType 42 def\n"); fprintf(fp, "/FontMatrix [1 0 0 1 0 0] def\n"); fprintf(fp, "/FontName /%s def\n", font); fprintf(fp, "/FontBBox [%d %d %d %d] def\n", xMin * 1000 / unitsPerEm, yMin * 1000 / unitsPerEm, xMax * 1000 / unitsPerEm, yMax * 1000 / unitsPerEm); fprintf(fp, "/PaintType 0 def\n"); fprintf(fp, "/Encoding StandardEncoding def\n"); if (fsType != -1 || Notice || Copyright || WeightClass) { fprintf(fp, "/FontInfo 4 dict dup begin\n"); if (fsType != -1) fprintf(fp, "/FSType %d def\n", fsType); if (Notice) fprintf(fp, "/Notice (%s) readonly def\n", Notice); if (Copyright) fprintf(fp, "/Copyright (%s) readonly def\n", Copyright); if (WeightClass) { if (WeightClass <= 350) cp = "Light"; else if (WeightClass <= 550) cp = "Medium"; else if (WeightClass <= 750) cp = "Bold"; else if (WeightClass <= 850) cp = "Ultra"; else cp = "Heavy"; fprintf(fp, "/Weight (%s) readonly def\n", cp); } fprintf(fp, "end readonly def\n"); } fprintf(fp, "/CharStrings %lu dict dup begin\n", nc); for (i = 0; i < nc; i++) { if ((cp = GID2SID(i)) != NULL && (i == 0 || strcmp(cp, ".notdef"))) { fprintenc(fp, cp); fprintf(fp, " %lu def\n", i); } else fprintf(fp, "/index0x%02lX %lu def\n", i, i); } fprintf(fp, "end readonly def\n"); fprintf(fp, "/sfnts["); build_sfnts(fp); fprintf(fp, "]def\n"); fprintf(fp, "FontName currentdict end definefont pop\n"); } else ok = -1; free(PostScript_name); PostScript_name = 0; free(Copyright); Copyright = 0; free(Notice); Notice = 0; free(ExtraStringSpace); ExtraStringSpace = NULL; ExtraStringSpacePos = 0; free(ExtraStrings); ExtraStrings = NULL; nExtraStrings = 0; return ok; } #endif /* DPOST */ int otfget(struct afmtab *_a, char *_contents, size_t _size) { int ok = 0; (void) &ok; a = _a; filename = a->path; contents = _contents; size = _size; if (setjmp(breakpoint) == 0) { get_offset_table(); get_table_directories(); get_head(); get_OS_2(); get_post(); if (ttf == 0) { a->type = TYPE_OTF; get_CFF(); } else { a->type = TYPE_TTF; get_maxp(); get_name(); get_ttf(); } #ifndef DPOST kerninit(); get_feature(pos_GSUB, "liga", 4, get_LigatureSubstFormat1); get_feature(pos_GPOS, "kern", 2, get_GPOS_kern1); get_feature(pos_GPOS, "kern", 2, get_GPOS_kern2); get_feature(pos_GSUB, NULL, -1, get_substitutions); if (ttf && got_kern == 0) get_kern(); kernfinish(); get_cmap(0); #endif /* !DPOST */ a->Font.nwfont = a->nchars > 255 ? 255 : a->nchars; } else ok = -1; free(PostScript_name); PostScript_name = 0; free(Copyright); Copyright = 0; free(Notice); Notice = 0; free_INDEX(CFF.Name); CFF.Name = 0; free_INDEX(CFF.Top_DICT); CFF.Top_DICT = 0; free_INDEX(CFF.String); CFF.String = 0; free_INDEX(CFF.Global_Subr); CFF.Global_Subr = 0; free_INDEX(CFF.CharStrings); CFF.CharStrings = 0; free(ExtraStringSpace); ExtraStringSpace = NULL; ExtraStringSpacePos = 0; free(ExtraStrings); ExtraStrings = NULL; nExtraStrings = 0; free(a->gid2tr); a->gid2tr = NULL; return ok; }