aboutsummaryrefslogtreecommitdiffstats
path: root/troff/troff.d/otf.c
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2016-10-06 21:30:09 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2016-10-06 21:30:09 +0000
commitaa7798c94fa57f6c00fab4393c9fe91334864371 (patch)
tree61b5a60e9c086b1ba44b4718e7666304a8edab6f /troff/troff.d/otf.c
downloadsrc-aa7798c94fa57f6c00fab4393c9fe91334864371.tar.gz
src-aa7798c94fa57f6c00fab4393c9fe91334864371.zip
Import heirloom doctools snapshot from git as of 161006vendor/heirloom-doctools/20161006
Notes
Notes: svn path=/vendor/heirloom-doctools/dist/; revision=306788 svn path=/vendor/heirloom-doctools/20161006/; revision=306789; tag=vendor/heirloom-doctools/20161006
Diffstat (limited to 'troff/troff.d/otf.c')
-rw-r--r--troff/troff.d/otf.c3597
1 files changed, 3597 insertions, 0 deletions
diff --git a/troff/troff.d/otf.c b/troff/troff.d/otf.c
new file mode 100644
index 000000000000..1f3643030cf9
--- /dev/null
+++ b/troff/troff.d/otf.c
@@ -0,0 +1,3597 @@
+/*
+ * 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <limits.h>
+#include "dev.h"
+#include "afm.h"
+
+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;
+short xMin, yMin, xMax, yMax;
+short indexToLocFormat;
+static struct afmtab *a;
+static int 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 },
+ { "cmap", &pos_cmap, 0 },
+ { "cvt ", &pos_cvt, 1 },
+ { "fpgm", &pos_fpgm, 1 },
+ { "GPOS", &pos_GPOS, 0 },
+ { "GSUB", &pos_GSUB, 0 },
+ { "head", &pos_head, 2 },
+ { "hhea", &pos_hhea, 1 },
+ { "hmtx", &pos_hmtx, 1 },
+ { "kern", &pos_kern, 0 },
+ { "loca", &pos_loca, 1 },
+ { "maxp", &pos_maxp, 1 },
+ { "name", &pos_name, 0 },
+ { "OS/2", &pos_OS_2, 0 },
+ { "post", &pos_post, 0 },
+ { "prep", &pos_prep, 1 },
+ { "vhea", &pos_vhea, 1 },
+ { "vmtx", &pos_vmtx, 1 },
+ { "glyf", &pos_glyf, 3 }, /* holds glyph data */
+ { NULL, NULL, 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, 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(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(int 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;
+ int 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)
+{
+ long 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)
+{
+ int i;
+
+ otfalloc(numGlyphs);
+ for (i = 0; i < numGlyphs; i++)
+ onechar(i, i);
+}
+
+static void
+get_ttf_post_2_0(int o)
+{
+ int numberOfGlyphs;
+ int numberNewGlyphs;
+ int 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)
+{
+ int numberOfGlyphs;
+ int i, 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 */
+
+static void
+addunitab(int c, int u)
+{
+#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, int 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, 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)
+{
+ int numTables;
+ int platformID;
+ int encodingID;
+ int offset;
+ int i, 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;
+ }
+ numTables = pbe16(&contents[o+2]);
+ if (4 + 8*numTables > 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 < numTables; 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)
+{
+ 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(int gid)
+{
+ if (gid < 0 || 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 int
+get_cov(struct cov *cp)
+{
+ int Start, End;
+
+ switch (cp->CoverageFormat) {
+ default:
+ return -1;
+ case 1:
+ if (cp->cnt < cp->GlyphCount)
+ return pbe16(&contents[cp->offset+4+2*cp->cnt++]);
+ return -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 -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<<i))
+ sz += 2;
+ for (i = 0; i < 16; i++)
+ if (ValueFormat2 & (1<<i))
+ sz += 2;
+ return sz;
+}
+
+static inline int
+get_x_adj(int ValueFormat1, int o)
+{
+ int x = 0;
+ int z = 0;
+
+ if (ValueFormat1 & 0x0001) {
+ x += (int16_t)_pbe16(&contents[o+z]);
+ z += 2;
+ }
+ if (ValueFormat1 & 0x0002)
+ z += 2;
+ if (ValueFormat1 & 0x0004) {
+ x += (int16_t)_pbe16(&contents[o+z]);
+ z += 2;
+ }
+ return x;
+}
+
+static void kerninit(void);
+static void kernfinish(void);
+
+static int got_kern;
+
+#ifdef DUMP
+static void kernpair(int, int, int);
+#else /* !DUMP */
+
+static struct namecache **nametable;
+
+static void
+kerninit(void)
+{
+ char *cp;
+ int i;
+
+ got_kern = 0;
+ nametable = calloc(nc, sizeof *nametable);
+ for (i = 0; i < nc; i++)
+ if ((cp = GID2SID(i)) != NULL)
+ nametable[i] = afmnamelook(a, cp);
+}
+
+#define GID2name(gid) ((gid) < 0 || (gid) >= nc ? NULL : nametable[gid])
+
+static inline void
+kernpair(int first, int 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, 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, int o, const char *_name)
+{
+ int PosFormat;
+
+ got_kern = 1;
+ switch (PosFormat = pbe16(&contents[o])) {
+ case 1:
+ get_PairPosFormat1(o);
+ break;
+ }
+}
+
+static void
+get_GPOS_kern2(int _t, int o, const char *_name)
+{
+ 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;
+ int CompCount;
+ int Component[16];
+ 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, int o, const char *_name)
+{
+ 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;
+ int c, d;
+ int Coverage;
+ int 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)) >= 0)
+ 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)
+{
+ 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)
+{
+ 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 numTables;
+ unsigned short searchRange;
+ unsigned short entrySelector;
+ unsigned short rangeShift;
+ uint32_t ccs;
+
+ numTables = 0;
+ for (i = 0; tables[i].name; i++)
+ if (tables[i].in_sfnts && *tables[i].pos >= 0)
+ numTables++;
+ entrySelector = 0;
+ for (searchRange = 1; searchRange*2 < numTables; searchRange *= 2)
+ entrySelector++;
+ searchRange *= 16;
+ rangeShift = numTables * 16 - searchRange;
+ fprintf(fp, "<%08X%04hX%04hX%04hX%04hX\n", 0x00010000,
+ numTables, searchRange, entrySelector, rangeShift);
+ ccs = 0x00010000 + (numTables<<16) + searchRange +
+ (entrySelector<<16) + rangeShift;
+ o = 12 + numTables * 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 + numTables * 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)
+{
+ char *cp;
+ int ok = 0;
+ int 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 %d 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, " %d def\n", i);
+ } else
+ fprintf(fp, "/index0x%02X %d 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;
+}