contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / contrib / ttf2pfb / t1asm.c
blob5b63aab0699ad44d253b566de825cfe0466d5f1f
1 /* t1asm
2 **
3 ** This program `assembles' Adobe Type-1 font programs in pseudo-PostScript
4 ** form into either PFB or PFA format. The human readable/editable input is
5 ** charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font
6 ** Format' version 1.1 (the `black book'). There is a companion program,
7 ** t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript
8 ** file.
9 **
10 ** Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
12 ** Permission is hereby granted to use, modify, and distribute this program
13 ** for any purpose provided this copyright notice and the one below remain
14 ** intact.
16 ** author: I. Lee Hetherington (ilh@lcs.mit.edu)
19 #ifndef lint
20 static char sccsid[] =
21 "@(#) t1asm.c 1.2 10:09:46 5/22/92";
22 static char copyright[] =
23 "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
24 #endif
26 /* Note: this is ANSI C. */
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
33 #ifdef MSDOS
34 #define WB "wb"
35 #else
36 #define WB "w"
37 #endif
39 #define BANNER "This is t1asm 1.2.\n"
40 #define LINESIZE 256
42 #define MAXBLOCKLEN ((1<<17)-6)
43 #define MINBLOCKLEN ((1<<8)-6)
45 #define MARKER 128
46 #define ASCII 1
47 #define BINARY 2
48 #define DONE 3
50 typedef unsigned char byte;
52 static FILE *ifp = stdin;
53 static FILE *ofp = stdout;
55 /* flags */
56 static int pfb = 0;
57 static int active = 0;
58 static int start_charstring = 0;
59 static int in_eexec = 0;
61 static char line[LINESIZE + 1];
63 /* lenIV and charstring start command */
64 static int lenIV = 4;
65 static char cs_start[10];
67 /* for charstring buffering */
68 static byte charstring_buf[65535];
69 static byte *charstring_bp;
71 /* for PFB block buffering */
72 static byte blockbuf[MAXBLOCKLEN];
73 static int blocklen = MAXBLOCKLEN;
74 static int blockpos = -1;
75 static int blocktyp = ASCII;
77 /* decryption stuff */
78 static unsigned short er, cr;
79 static unsigned short c1 = 52845, c2 = 22719;
81 /* table of charstring commands */
82 static struct command {
83 char *name;
84 int one, two;
85 } command_table[] = {
86 { "callothersubr", 12, 16 },
87 { "callsubr", 10, -1 },
88 { "closepath", 9, -1 },
89 { "div", 12, 12 },
90 { "dotsection", 12, 0 },
91 { "endchar", 14, -1 },
92 { "escape", 12, -1 },
93 { "hlineto", 6, -1 },
94 { "hmoveto", 22, -1 },
95 { "hsbw", 13, -1 },
96 { "hstem", 1, -1 },
97 { "hstem3", 12, 2 },
98 { "hvcurveto", 31, -1 },
99 { "pop", 12, 17 },
100 { "return", 11, -1 },
101 { "rlineto", 5, -1 },
102 { "rmoveto", 21, -1 },
103 { "rrcurveto", 8, -1 },
104 { "sbw", 12, 7 },
105 { "seac", 12, 6 },
106 { "setcurrentpoint", 12, 33 },
107 { "vhcurveto", 30, -1 },
108 { "vlineto", 7, -1 },
109 { "vmoveto", 4, -1 },
110 { "vstem", 3, -1 },
111 { "vstem3", 12, 1 },
112 }; /* alphabetical */
114 /* Two separate decryption functions because eexec and charstring decryption
115 must proceed in parallel. */
117 static byte eencrypt(byte plain)
119 byte cipher;
121 cipher = (plain ^ (er >> 8));
122 er = (cipher + er) * c1 + c2;
123 return cipher;
126 static byte cencrypt(byte plain)
128 byte cipher;
130 cipher = (plain ^ (cr >> 8));
131 cr = (cipher + cr) * c1 + c2;
132 return cipher;
135 /* This function flushes a buffered PFB block. */
137 static void output_block()
139 int i;
141 /* output four-byte block length */
142 fputc(blockpos & 0xff, ofp);
143 fputc((blockpos >> 8) & 0xff, ofp);
144 fputc((blockpos >> 16) & 0xff, ofp);
145 fputc((blockpos >> 24) & 0xff, ofp);
147 /* output block data */
148 for (i = 0; i < blockpos; i++)
149 fputc(blockbuf[i], ofp);
151 /* mark block buffer empty and uninitialized */
152 blockpos = -1;
155 /* This function outputs a single byte. If output is in PFB format then output
156 is buffered through blockbuf[]. If output is in PFA format, then output
157 will be hexadecimal if in_eexec is set, ASCII otherwise. */
159 static void output_byte(byte b)
161 static char *hexchar = "0123456789ABCDEF";
162 static int hexcol = 0;
164 if (pfb) {
165 /* PFB */
166 if (blockpos < 0) {
167 fputc(MARKER, ofp);
168 fputc(blocktyp, ofp);
169 blockpos = 0;
171 blockbuf[blockpos++] = b;
172 if (blockpos == blocklen)
173 output_block();
174 } else {
175 /* PFA */
176 if (in_eexec) {
177 /* trim hexadecimal lines to 64 columns */
178 if (hexcol >= 64) {
179 fputc('\n', ofp);
180 hexcol = 0;
182 fputc(hexchar[(b >> 4) & 0xf], ofp);
183 fputc(hexchar[b & 0xf], ofp);
184 hexcol += 2;
185 } else {
186 fputc(b, ofp);
191 /* This function outputs a byte through possible eexec encryption. */
193 static void eexec_byte(byte b)
195 if (in_eexec)
196 output_byte(eencrypt(b));
197 else
198 output_byte(b);
201 /* This function outputs a null-terminated string through possible eexec
202 encryption. */
204 static void eexec_string(char *string)
206 while (*string)
207 eexec_byte((byte) *string++);
210 /* This function gets ready for the eexec-encrypted data. If output is in
211 PFB format then flush current ASCII block and get ready for binary block.
212 We start encryption with four random (zero) bytes. */
214 static void eexec_start()
216 eexec_string(line);
217 if (pfb) {
218 output_block();
219 blocktyp = BINARY;
222 in_eexec = 1;
223 er = 55665;
224 eexec_byte(0);
225 eexec_byte(0);
226 eexec_byte(0);
227 eexec_byte(0);
230 /* This function wraps-up the eexec-encrypted data and writes ASCII trailer.
231 If output is in PFB format then this entails flushing binary block and
232 starting an ASCII block. */
234 static void eexec_end()
236 int i, j;
238 if (pfb) {
239 output_block();
240 blocktyp = ASCII;
241 } else {
242 fputc('\n', ofp);
244 in_eexec = 0;
245 for (i = 0; i < 7; i++) {
246 for (j = 0; j < 64; j++)
247 eexec_byte('0');
248 eexec_byte('\n');
250 eexec_string("cleartomark\n");
251 if (pfb) {
252 output_block();
253 fputc(MARKER, ofp);
254 fputc(DONE, ofp);
258 /* This function returns an input line of characters. A line is terminated by
259 length (including terminating null) greater than LINESIZE, a newline \n, or
260 when active (looking for charstrings) by '{'. When terminated by a newline
261 the newline is put into line[]. When terminated by '{', the '{' is not put
262 into line[], and the flag start_charstring is set to 1. */
264 static void getline()
266 int c;
267 char *p = line;
268 int comment = 0;
270 start_charstring = 0;
271 while (p < line + LINESIZE) {
272 c = fgetc(ifp);
273 if (c == EOF)
274 break;
275 if (c == '%')
276 comment = 1;
277 if (active && !comment && c == '{') {
278 start_charstring = 1;
279 break;
281 *p++ = (char) c;
282 if (c == '\n')
283 break;
285 *p = '\0';
288 /* This function is used by the binary search, bsearch(), for command names in
289 the command table. */
291 static int command_compare(const void *key, const void *item)
293 return strcmp((char *) key, ((struct command *) item)->name);
296 /* This function returns 1 if the string is an integer and 0 otherwise. */
298 static int is_integer(char *string)
300 if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') {
301 while (*++string && isdigit(*string))
302 ; /* deliberately empty */
303 if (!*string)
304 return 1;
306 return 0;
309 /* This function initializes charstring encryption. Note that this is called
310 at the beginning of every charstring. */
312 static void charstring_start()
314 int i;
316 charstring_bp = charstring_buf;
317 cr = 4330;
318 for (i = 0; i < lenIV; i++)
319 *charstring_bp++ = cencrypt((byte) 0);
322 /* This function encrypts and buffers a single byte of charstring data. */
324 static void charstring_byte(v)
325 int v;
327 byte b = ((unsigned int)v) & 0xff;
329 if (charstring_bp - charstring_buf > sizeof(charstring_buf)) {
330 fprintf(stderr, "error: charstring_buf full (%d bytes)\n",
331 sizeof(charstring_buf));
332 exit(1);
334 *charstring_bp++ = cencrypt(b);
337 /* This function outputs buffered, encrypted charstring data through possible
338 eexec encryption. */
340 static void charstring_end()
342 byte *bp;
344 sprintf(line, "%d %s ", charstring_bp - charstring_buf, cs_start);
345 eexec_string(line);
346 for (bp = charstring_buf; bp < charstring_bp; bp++)
347 eexec_byte(*bp);
350 /* This function generates the charstring representation of an integer. */
352 static void charstring_int(int num)
354 int x;
356 if (num >= -107 && num <= 107) {
357 charstring_byte(num + 139);
358 } else if (num >= 108 && num <= 1131) {
359 x = num - 108;
360 charstring_byte(x / 256 + 247);
361 charstring_byte(x % 256);
362 } else if (num >= -1131 && num <= -108) {
363 x = abs(num) - 108;
364 charstring_byte(x / 256 + 251);
365 charstring_byte(x % 256);
366 } else if (num >= (-2147483647-1) && num <= 2147483647) {
367 charstring_byte(255);
368 charstring_byte(num >> 24);
369 charstring_byte(num >> 16);
370 charstring_byte(num >> 8);
371 charstring_byte(num);
372 } else {
373 fprintf(stderr,
374 "error: cannot format the integer %d, too large\n", num);
375 exit(1);
379 /* This function parses an entire charstring into integers and commands,
380 outputting bytes through the charstring buffer. */
382 static void parse_charstring()
384 struct command *cp;
386 charstring_start();
387 while (fscanf(ifp, "%s", line) == 1) {
388 if (line[0] == '%') {
389 /* eat comment to end of line */
390 while (fgetc(ifp) != '\n' && !feof(ifp))
391 ; /* deliberately empty */
392 continue;
394 if (line[0] == '}')
395 break;
396 if (is_integer(line)) {
397 charstring_int(atoi(line));
398 } else {
399 cp = (struct command *)
400 bsearch((void *) line, (void *) command_table,
401 sizeof(command_table) / sizeof(struct command),
402 sizeof(struct command),
403 command_compare);
404 if (cp) {
405 charstring_byte(cp->one);
406 if (cp->two >= 0)
407 charstring_byte(cp->two);
408 } else {
409 fprintf(stderr, "error: cannot use `%s' in charstring\n", cp->name);
410 exit(1);
414 charstring_end();
417 static void usage()
419 fprintf(stderr,
420 "usage: t1asm [-b] [-l block-length] [input [output]]\n");
421 fprintf(stderr,
422 "\n-b means output in PFB format, otherwise PFA format.\n");
423 fprintf(stderr,
424 "The block length applies to the length of blocks in the\n");
425 fprintf(stderr,
426 "PFB output file; the default is to use the largest possible.\n");
427 exit(1);
431 int main(int argc, char **argv)
433 char *p, *q, *r;
434 int c;
436 extern char *optarg;
437 extern int optind;
438 extern int getopt(int argc, char **argv, char *optstring);
440 fprintf(stderr, "%s", BANNER);
442 /* interpret command line arguments using getopt */
443 while ((c = getopt(argc, argv, "bl:")) != -1)
444 switch (c) {
445 case 'b':
446 pfb = 1;
447 break;
448 case 'l':
449 blocklen = atoi(optarg);
450 if (blocklen < MINBLOCKLEN) {
451 blocklen = MINBLOCKLEN;
452 fprintf(stderr,
453 "warning: using minimum block length of %d\n",
454 blocklen);
455 } else if (blocklen > MAXBLOCKLEN) {
456 blocklen = MAXBLOCKLEN;
457 fprintf(stderr,
458 "warning: using maximum block length of %d\n",
459 blocklen);
461 break;
462 default:
463 usage();
464 break;
466 if (argc - optind > 2)
467 usage();
469 /* possibly open input & output files */
470 if (argc - optind >= 1) {
471 ifp = fopen(argv[optind], "r");
472 if (!ifp) {
473 fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
474 exit(1);
477 if (argc - optind >= 2) {
478 ofp = fopen(argv[optind + 1], WB);
479 if (!ofp) {
480 fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
481 exit(1);
485 /* Finally, we loop until no more input. Some special things to look for
486 are the `currentfile eexec' line, the beginning of the `/Subrs'
487 definition, the definition of `/lenIV', and the definition of the
488 charstring start command which has `...string currentfile...' in it. */
490 while (!feof(ifp) && !ferror(ifp)) {
491 getline();
492 if (strcmp(line, "currentfile eexec\n") == 0) {
493 eexec_start();
494 continue;
495 } else if (strstr(line, "/Subrs") && isspace(line[6])) {
496 active = 1;
497 } else if ((p = strstr(line, "/lenIV"))) {
498 sscanf(p, "%*s %d", &lenIV);
499 } else if ((p = strstr(line, "string currentfile"))) {
500 /* locate the name of the charstring start command */
501 *p = '\0'; /* damage line[] */
502 q = strrchr(line, '/');
503 if (q) {
504 r = cs_start;
505 ++q;
506 while (!isspace(*q) && *q != '{')
507 *r++ = *q++;
508 *r = '\0';
510 *p = 's'; /* repair line[] */
512 /* output line data */
513 eexec_string(line);
514 if (start_charstring) {
515 if (!cs_start[0]) {
516 fprintf(stderr, "error: couldn't find charstring start command\n");
517 exit(1);
519 parse_charstring();
522 eexec_end();
524 fclose(ifp);
525 fclose(ofp);
527 return 0;