home *** CD-ROM | disk | FTP | other *** search
- From: kevin@kosman.UUCP (Kevin O'Gorman)
- Newsgroups: comp.lang.postscript,comp.fonts,alt.sources
- Subject: Untype1.c program -- a pipeline, more portable version
- Message-ID: <1270@kosman.UUCP>
- Date: 3 Dec 90 23:59:16 GMT
-
- A little while ago, Chris Sears (sears@dungeon.enet.dec.com) posted a
- set of programs to decode eexec-ed type 1 font programs. I had some
- trouble with that version, especially on MSDOS, so I combined some stuff
- and made this version, which compiles on MSC 5.1 and 6.00A, as well as
- under gcc on my SYSV UNIX. It should be reasonably portable, since
- the machines differ in word-size and endianness. There are some SYSV-isms,
- but just in the names of include files, I think. Also, see NEED_STRSTR.
-
- This routine also can be used in a pipeline. Specify - for the standard
- input. Output is always on stdout.
-
- I HAVE been having some trouble with it though -- the resulting
- PostScript seems always to get a VMERROR on my LaserWriter Plus, on any
- real font. Ideas? The result is informative anyway.
-
- I tried sending this to Chris first, but email to the indicated address
- does not work. Chris, thanks for the original.
-
- This is a single source file, not in shar format. Beware the trailing
- signature.
-
- /*
- * untype1.c -- decrypt an Adobe font file encrypted for eexec
- *
- * original by Chris B. Sears (sears@dungeon.enet.dec.com)
- *
- * Modified for portability by Kevin O'Gorman (kosman!kevin), because MSDOS
- * had trouble with intermediate files that were mixed binary and text, and
- * because it's really all one task. (3 Dec 1990)
- *
- * The original was distributed without a copyright notice, and no comment
- * about the status. I take that to place it in the public domain. I
- * (Kevin O'Gorman) specifically place my modifications in the public domain
- * -- I assert no rights, and accept no responsibility.
- *
- * As a courtesy, I request that notices of authorship be kept honest and
- * complete (and don't forget your own).
- *
- * usage:
- * untype1 [-s] inputfile
- *
- * The optional -s switch causes the output to be truncated at the first line
- * containing the token "definefont". This is useful in conjunction with the
- * shell scripts distributed by Chris Sears.
- *
- * The font-related code assumes that the font is eexec encoded (they almost
- * always are); the copying loop for stuff outside of eexec does not check
- * for font-related things. Further, the RD and -| tokens are hardwired in.
- *
- * Inputfile may be specified as "-".
- *
- * The decoded result is placed on the standard output.
- *
- * Current status: the results get VMerrors on my LaserWriter Plus, even if
- * I setpacking to true. The results are nevertheless very informative.
- *
- * Things to do:
- * 1: directly turn a type1 into a type3 font.
- * 2: draw the font characters large, with the hints and control points
- * made visible.
- * 3: decode printer internal fonts (type 5).
- * 4: strip ^D (from some postscript files) and ^Z (from MSDOS) characters.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #define SEEK_SET 0
-
- #define TRUE 1
- #define FALSE 0
-
- #define EEXEC_SKIP_BYTES 4
- #define MAX_ESCAPE 33
-
- int lenIV = 4; /* CharString salt length */
-
- typedef struct {
- char *command;
- int value;
- } Command;
-
- #define BUFFERSIZE 4096
- static int skip_salt = EEXEC_SKIP_BYTES + 1;
- static FILE *in;
- static char in_buff[BUFFERSIZE], out_buff[BUFFERSIZE];
- static int in_size, in_ptr;
- static int o, obase;
- static unsigned short int
- cr, cc1, cc2, er, ec1, ec2;
- #define ER 55665
- #define EC1 52845
- #define EC2 22719
- #define CR 4330
- #define CC1 52845
- #define CC2 22719
- static int count, csalt;
-
- Command commands[] = {
- { "notdefined_c0", 0 },
- { "hstem", 1 },
- { "notdefined_c2", 2 },
- { "vstem", 3 },
- { "vmoveto", 4 },
- { "chars_rlineto", 5 },
- { "hlineto", 6 },
- { "vlineto", 7 },
- { "rrcurveto", 8 },
- { "chars_closepath",9 },
- { "callsubr", 10 },
- { "return", 11 },
- { "escape", 12 },
- { "hsbw", 13 },
- { "endchar", 14 },
- { "notdefined_c15", 15 },
- { "notdefined_c16", 16 },
- { "notdefined_c17", 17 },
- { "notdefined_c18", 18 },
- { "notdefined_c19", 19 },
- { "notdefined_c20", 20 },
- { "chars_rmoveto", 21 },
- { "hmoveto", 22 },
- { "notdefined_c23", 23 },
- { "notdefined_c24", 24 },
- { "notdefined_c25", 25 },
- { "notdefined_c26", 26 },
- { "notdefined_c27", 27 },
- { "notdefined_c28", 28 },
- { "notdefined_c29", 29 },
- { "vhcurveto", 30 },
- { "hvcurveto", 31 }
- };
-
- Command escapes[] = {
- { "dotsection", 0 },
- { "vstem3", 1 },
- { "hstem3", 2 },
- { "notdefined_e3", 3 },
- { "notdefined_e4", 4 },
- { "notdefined_e5", 5 },
- { "seac", 6 },
- { "sbw", 7 },
- { "notdefined_e8", 8 },
- { "notdefined_e9", 9 },
- { "notdefined_e10", 10 },
- { "notdefined_e11", 11 },
- { "chars_div", 12 },
- { "notdefined_e13", 13 },
- { "notdefined_e14", 14 },
- { "notdefined_e15", 15 },
- { "callothersubr", 16 },
- { "chars_pop", 17 },
- { "notdefined_e18", 18 },
- { "notdefined_e19", 19 },
- { "notdefined_e20", 20 },
- { "notdefined_e21", 21 },
- { "notdefined_e22", 22 },
- { "notdefined_e23", 23 },
- { "notdefined_e24", 24 },
- { "notdefined_e25", 25 },
- { "notdefined_e26", 26 },
- { "notdefined_e27", 27 },
- { "notdefined_e28", 28 },
- { "notdefined_e29", 29 },
- { "notdefined_e30", 30 },
- { "notdefined_e31", 31 },
- { "notdefined_e32", 32 },
- { "setcurrentpoint",33 }
- };
-
- unsigned char GetPlain()
- {
- if (in_ptr >= in_size) {
- if(fgets(in_buff, BUFSIZ, in) == NULL) {
- fprintf(stderr,"Errror -- end of file.\n");
- exit(1);
- }
- in_size = strlen(in_buff) - 1;
- in_ptr = 0;
- }
- return in_buff[in_ptr++];
- }
-
- unsigned int GetHexChar()
- {
- unsigned int byte;
-
- /* skip whitespace */
- do {
- byte = GetPlain();
- } while ((byte == '\n') || (byte == ' ') || (byte == '\t')
- || (byte == '\r') || (byte == '\f'));
-
- /* figure the digit */
- if ( (byte >= '0') && (byte <= '9') ) return (byte - '0');
- if ( (byte >= 'A') && (byte <= 'F') ) return (byte - 'A' + 10);
- if ( (byte >= 'a') && (byte <= 'f') ) return (byte - 'a' + 10);
-
- /* anything else is an error */
- fprintf(stderr, "Illegal hex digit.\n");
- exit (1);
- }
-
- unsigned char
- EDeCrypt()
- {
- unsigned char ch1, ch2, plain, cipher;
-
- /*
- * Decode cipher.
- */
- do {
- ch1 = GetHexChar();
- ch2 = GetHexChar();
- cipher = (ch1 << 4) + ch2;
-
- plain = (cipher ^ (er >> 8));
- er = (cipher + er) * ec1 + ec2;
- if (skip_salt) skip_salt--;
- } while (skip_salt);
-
- return plain;
- }
-
- unsigned char
- CDeCrypt()
- {
- unsigned char plain, cypher;
- if (count <= 0) {
- fprintf(stderr,"Reading too many bytes of charstring data.\n");
- exit(1);
- }
- do {
- cypher = EDeCrypt();
- count--;
- plain = (cypher ^ (cr >> 8));
- cr = (cypher + cr) * cc1 + cc2;
- if (csalt) csalt--;
- } while (csalt);
-
- return plain;
- }
-
- #ifdef NEED_STRSTR
- char *
- strstr(char *string, char *target)
- {
- int slen, tlen, i;
- tlen = strlen(target);
- slen = strlen(string);
- for (i=0; i+tlen <= slen; i++) {
- if (!strncmp(target, &string[i],tlen)) return (&string[i]);
- }
- return NULL;
- }
- #endif
-
- void
- out_check()
- {
- out_buff[o] = '\0'; /* terminate the string */
- /* mostly serves to help use CodeView */
- if (o-obase > 78) {
- int ptr;
- unsigned char c;
-
- for (ptr=obase+78; ptr>obase; ptr--) {
- c = out_buff[ptr];
- if(c==' ' || c=='\t') break;
- }
- if (ptr-obase < 10) return;
- for (; ptr>obase; ptr--) {
- c = out_buff[ptr];
- if (isalpha(c)) break;
- }
- if (ptr-obase < 10) return;
- for (;; ptr++) {
- c = out_buff[ptr];
- if(c==' ' || c=='\t') break;
- }
- out_buff[ptr] = '\0';
- fputs(out_buff, stdout);
- strcpy(out_buff,"\n\t");
- strcat(out_buff,&out_buff[ptr+1]);
- o = strlen(out_buff);
- obase = -6;
- }
- }
-
-
- void
- main(argc, argv)
- int argc;
- char **argv;
- {
- unsigned char plainchar;
- char *count_pos;
- int i;
- int line_pos;
- long value;
- #define DATA_STATE 0
- #define CHAR_STATE 1
- #define CINZ_STATE 2
- int state = DATA_STATE;
- unsigned char byte;
-
- if ((argc != 2 && argc != 3)
- || (argc == 3 && strcmp(argv[1],"-s"))) {
- fprintf(stderr, "Usage: %s [-s] input\n", argv[0]);
- exit(0);
- }
-
- if (strcmp(argv[argc-1], "-")) {
- if ((in = fopen(argv[argc-1], "r")) == NULL) {
- fprintf(stderr,
- "%s: can't open %s\n", argv[0], argv[argc-1]);
- exit(0);
- }
- } else {in = stdin;}
-
- /*
- * Just copy to output until we see an eexec.
- */
- COPYFILE:
- while (1) {
- if (fgets(in_buff, BUFSIZ, in) == NULL) goto fin;
- if (strcmp(in_buff, "currentfile eexec\n") == 0)
- break;
- fprintf(stdout, "%s", in_buff);
- }
-
- skip_salt = EEXEC_SKIP_BYTES + 1;
- er = ER;
- ec1 = EC1;
- ec2 = EC2;
-
- for (in_ptr = 999, in_size = 0, o=0, obase=0;;) {
- switch(state) {
- case CINZ_STATE:
- cr = CR;
- cc1 = CC1;
- cc2 = CC2;
- csalt = lenIV + 1;
- for (count_pos = &out_buff[o-5];
- (count_pos >= out_buff) && (*count_pos != ' ');
- count_pos--)
- ;
-
- /* This can be at the beginning of a line */
- if (*count_pos == ' ')
- count_pos++;
-
- count = atoi(count_pos);
-
- /*
- * Change "count RD" to "{"
- */
- o = count_pos - out_buff;
- out_buff[o++] = '{';
- out_buff[o] = '\0';
-
- state = CHAR_STATE;
-
- case CHAR_STATE:
- for ( ; count > 0; i += 2) {
- /*
- * Translate the buffer.
- */
- byte = CDeCrypt();
- if (byte == 11) { /* return */
- o += sprintf(&out_buff[o], " %s",
- commands[byte].command);
- out_check();
- break;
- } else if (byte == 12) { /* escape */
- byte = CDeCrypt();
- if (byte > MAX_ESCAPE) {
- o += sprintf(&out_buff[o],
- " not_defined_e%d", byte);
- out_check();
- } else {
- o += sprintf(&out_buff[o], " %s",
- escapes[byte].command);
- out_check();
- }
- continue;
- } else if (byte < 32) {
- o += sprintf(&out_buff[o], " %s",
- commands[byte].command);
- out_check();
- }
- if (byte >= 32) {
- if (byte <= 246) {
- o += sprintf(&out_buff[o], " %d",
- byte - 139);
- out_check();
- } else if ((byte >= 247) && (byte <= 250)) {
- o += sprintf(&out_buff[o], " %d",
- (byte - 247) * 256
- + CDeCrypt() + 108);
- out_check();
- }
- else if ((byte >= 251) && (byte <= 254)) {
- o += sprintf(&out_buff[o], " %d",
- -((int)byte - 251) * 256
- - (int)CDeCrypt() - 108);
- out_check();
- }
- else if (byte == 255) {
- value = CDeCrypt();
- value <<= 8;
- value += CDeCrypt();
- value <<= 8;
- value += CDeCrypt();
- value <<= 8;
- value += CDeCrypt();
- o +=sprintf(&out_buff[o],
- /* NOTE: long value */ " %ld", value);
- out_check();
- }
- }
- }
-
- o += sprintf(&out_buff[o], " }");
- out_check();
- state = DATA_STATE;
-
- case DATA_STATE:
- /*
- * Decrypt a line of hex.
- */
- plainchar = EDeCrypt();
-
- out_buff[o++] = plainchar;
- out_check();
-
- if ((o >=4) && !strncmp(" RD ", &out_buff[o-4], 4)) {
- state = CINZ_STATE;
- break;
- }
- if ((o >=4) && !strncmp(" -| ", &out_buff[o-4], 4)) {
- state = CINZ_STATE;
- break;
- }
- if (plainchar == '\n') {
- if (argc==3 && strstr(out_buff,"definefont")) goto fin;
- if (strncmp("/lenIV", out_buff, 6) == 0)
- lenIV = atoi(out_buff + 7);
- if ((count_pos =
- strstr(out_buff,"currentfile closefile"))
- != NULL){
- strcpy(count_pos, "\n");
- fputs(out_buff, stdout);
- goto COPYFILE;
- }
- fputs(out_buff, stdout);
- o = 0;
- obase = 0;
- }
- } /* switch */
- } /* for (reading file) */
-
- fin: fclose(in);
-
- exit(0);
- }
-
- --
- Kevin O'Gorman ( kevin@kosman.UUCP, kevin%kosman.uucp@nrc.com )
- voice: 805-984-8042 Vital Computer Systems, 5115 Beachcomber, Oxnard, CA 93035
- Non-Disclaimer: my boss is me, and he stands behind everything I say.
-