From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- fonts/utilities/fontload/src/subfont.c | 1860 ++++++++++++++++++++++++++++++++ 1 file changed, 1860 insertions(+) create mode 100644 fonts/utilities/fontload/src/subfont.c (limited to 'fonts/utilities/fontload/src/subfont.c') diff --git a/fonts/utilities/fontload/src/subfont.c b/fonts/utilities/fontload/src/subfont.c new file mode 100644 index 0000000000..5c24016d5f --- /dev/null +++ b/fonts/utilities/fontload/src/subfont.c @@ -0,0 +1,1860 @@ +/* SubFont +** +** This program makes new subfont which contains only selected characters. +** The program was started 27-Oct-1994 and began from source codes of the +** t1disasm and t1asm programs whose wroten by I. Lee Hetherington +** (ilh@lcs.mit.edu). +** +** Copyright (C) 1994, 1995, Basil K. Malyshev. All Rights Reserved. +** +** LIMITATIONS: +** This program can prepare only ATM compatible PS Type 1 fonts. +** In this reason you must download other type fonts avoiding this program. +** +** The reasons and applications of this program: +** 1. Some expert fonts have a lot of characters. For example EC/DC +** fonts are designed to cover most of european languages. +** However in each european language only few accented characters +** is used. This program can be used to make own smaller font +** which will be enought for typesetting in your language. +** 2. Together with psfstat.ps program distributed with this program +** you can organize partial font downloading. +** 3. Using this module as part of DVIPS program partial font +** downloading can be done faster. +** +** History: +** 27-Oct-94 Beginning ... +** 1-Nov-94 V1.0 First completly workable version. +** Works together with fload C-shell script which calls +** GhostScript with 'psfstat.ps' macroses to make +** map of required charactrs. +** 3-Nov-94 V1.1 Now can prepare fonts with non standard layout +** that have 'noaccess put' instead of '|' or 'NP'. +** Now can process HYBRID fonts which have two versions +** of the 'Subrs' for High and low resolution devices. +** That is many Oblique fonts (Univers, Helvetica, ...) +** 24-Nov-94 Uploaded to CTAN:fonts/utilities/fontload. +** 25-Nov-94 Fixed for VMS. +** 27-Nov-94 Add ability for the output without eexec that reduces +** size of output file and accelerates downloading process +** but not reduces required printer memory. +** 28-Nov-94 optimize Subrs construction, which slightly reduces +** memory requirements. +** Remove warning on unknown_15 code which is not documented +** by Adobe but used in blank characters. +** Enclose every font into mark ... cleartoark if +** Eexec_Output flag is off. +** 30-Nov-94 V1.2 Ported to MS-DOS, compiled by +** Microsoft (R) C/C++ Optimizing Compiler Version 8.0 +** 19-Dec-94 V1.3 Now can read font map in GhostScript format. +** So, SubFont and GhostScript can share the same font map. +** 7-Jan-95 V1.4 Fixed dcr10 encoding size problem. +** +******* Also, copyright of the t1asm and t1disasm programs is there: ******** +** +** Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. +** +** Permission is hereby granted to use, modify, and distribute this program +** for any purpose provided this copyright notice and the one below remain +** intact. +** +** author of the t1asm and t1disasm programs: +** I. Lee Hetherington (ilh@lcs.mit.edu) +*/ + +# define PROGRAM "SubFont" +# define PROBLEM "BKM Type1 SubFont Extractor" +# define VERSION "1.4" +# define REVDATE "7-Jan-1995" +# define AUTHOR "Basil K.Malyshev (Vassili Malychev)" +# define COPYRIGHT "1994, 1995, Basil K. Malyshev." + +# include +# include +# include +# include + +# ifdef MSDOS +# define SMALL_MEMORY +# define SYSID "MS-DOS" +# define PATH_DELIMITER ';' +# define FILE_DELIMITER '\\' +# define DEFAULTFONTPATH ".;C:\\PSFONTS;C:\\GS;C:\\GS\\FONTS" +# define RB "rb" +# define WB "wb" +# endif + +# ifdef vms +# define SYSID "VMS" +# define PATH_DELIMITER ',' +# define FILE_DELIMITER 0 +# define DEFAULTFONTPATH "SYS$DISK:[],Type1_Fonts:,GS_LIB:" +# define RB "rb" +# define WB "wb" +# endif + +# ifdef unix +# define SYSID "UNIX" +# define PATH_DELIMITER ':' +# define FILE_DELIMITER '/' +# define DEFAULTFONTPATH ".:/usr/local/lib/Fonts" +# define RB "r" +# define WB "w" +# endif + +# ifndef SYSID +# define SMALL_MEMORY +# define SYSID "(Assumed MS-DOS)" +# define PATH_DELIMITER ';' +# define FILE_DELIMITER '\\' +# define DEFAULTFONTPATH ".;C:\\PSFONTS;C:\\GS;C:\\GS\\FONTS" +# define RB "rb" +# define WB "wb" +# endif + +#define LINESIZE 4096 /* 256 */ + +typedef unsigned char byte; + +static int Verbose = 0; +static int Trace = 0; +static int ArrLosts = 0; +static int TouchEncoding = 0; +static int Eexec_Output = 1; + +static FILE *ifp /*VMS: = stdin */ ; +static FILE *ofp /*VMS: = stdout */; +static FILE *ufp = NULL; +static char *uFileName = NULL; +static char line[LINESIZE]; +static int lenIV = 4; + +static char RD_String[] = "RD"; +static char ND_String[] = "noaccess def"; +static char NP_String[] = "noaccess put"; + +static struct { int code; char *name; } StdEnc[] = { + 040 , "space", + 041 , "exclam", + 042 , "quotedbl", + 043 , "numbersign", + 044 , "dollar", + 045 , "percent", + 046 , "ampersand", + 047 , "quoteright", + 050 , "parenleft", + 051 , "parenright", + 052 , "asterisk", + 053 , "plus", + 054 , "comma", + 055 , "hyphen", + 056 , "period", + 057 , "slash", + 060 , "zero", + 061 , "one", + 062 , "two", + 063 , "three", + 064 , "four", + 065 , "five", + 066 , "six", + 067 , "seven", + 070 , "eight", + 071 , "nine", + 072 , "colon", + 073 , "semicolon", + 074 , "less", + 075 , "equal", + 076 , "greater", + 077 , "question", + 0100 , "at", + 0101 , "A", + 0102 , "B", + 0103 , "C", + 0104 , "D", + 0105 , "E", + 0106 , "F", + 0107 , "G", + 0110 , "H", + 0111 , "I", + 0112 , "J", + 0113 , "K", + 0114 , "L", + 0115 , "M", + 0116 , "N", + 0117 , "O", + 0120 , "P", + 0121 , "Q", + 0122 , "R", + 0123 , "S", + 0124 , "T", + 0125 , "U", + 0126 , "V", + 0127 , "W", + 0130 , "X", + 0131 , "Y", + 0132 , "Z", + 0133 , "bracketleft", + 0134 , "backslash", + 0135 , "bracketright", + 0136 , "asciicircum", + 0137 , "underscore", + 0140 , "quoteleft", + 0141 , "a", + 0142 , "b", + 0143 , "c", + 0144 , "d", + 0145 , "e", + 0146 , "f", + 0147 , "g", + 0150 , "h", + 0151 , "i", + 0152 , "j", + 0153 , "k", + 0154 , "l", + 0155 , "m", + 0156 , "n", + 0157 , "o", + 0160 , "p", + 0161 , "q", + 0162 , "r", + 0163 , "s", + 0164 , "t", + 0165 , "u", + 0166 , "v", + 0167 , "w", + 0170 , "x", + 0171 , "y", + 0172 , "z", + 0173 , "braceleft", + 0174 , "bar", + 0175 , "braceright", + 0176 , "asciitilde", + 0241 , "exclamdown", + 0242 , "cent", + 0243 , "sterling", + 0244 , "fraction", + 0245 , "yen", + 0246 , "florin", + 0247 , "section", + 0250 , "currency", + 0251 , "quotesingle", + 0252 , "quotedblleft", + 0253 , "guillemotleft", + 0254 , "guilsinglleft", + 0255 , "guilsinglright", + 0256 , "fi", + 0257 , "fl", + 0261 , "endash", + 0262 , "dagger", + 0263 , "daggerdbl", + 0264 , "periodcentered", + 0266 , "paragraph", + 0267 , "bullet", + 0270 , "quotesinglbase", + 0271 , "quotedblbase", + 0272 , "quotedblright", + 0273 , "guillemotright", + 0274 , "ellipsis", + 0275 , "perthousand", + 0277 , "questiondown", + 0301 , "grave", + 0302 , "acute", + 0303 , "circumflex", + 0304 , "tilde", + 0305 , "macron", + 0306 , "breve", + 0307 , "dotaccent", + 0310 , "dieresis", + 0312 , "ring", + 0313 , "cedilla", + 0315 , "hungarumlaut", + 0316 , "ogonek", + 0317 , "caron", + 0320 , "emdash", + 0341 , "AE", + 0343 , "ordfeminine", + 0350 , "Lslash", + 0351 , "Oslash", + 0352 , "OE", + 0353 , "ordmasculine", + 0361 , "ae", + 0365 , "dotlessi", + 0370 , "lslash", + 0371 , "oslash", + 0372 , "oe", + 0373 , "germandbls", + 0, 0 +}; + +static char *StandardEncoding[256]; + +void init_Encoding(void) +{ + int i; + for( i = 0 ; i < 256 ; i++ ) + StandardEncoding[i] = NULL; + + for( i = 0 ; StdEnc[i].name != NULL ; i++ ) + StandardEncoding[StdEnc[i].code] = StdEnc[i].name ; +} + +static int Files = 0; /* Number of processed fonts */ + +void *xmalloc( int Size ) +{ + void *ptr; + + if ( (ptr=malloc( Size )) == NULL ) + { + fprintf(stderr,"? SubFont: Not enought memory(needed %d bytes)\n",Size); + exit(1); + } + return ptr; +} + +char *xstrdup( char *str ) +{ + char *ptr; + ptr = xmalloc( strlen(str) + 1 ); + strcpy(ptr,str); + return ptr; +} + +# define CHUNK_SIZE 128 +struct ChunkSt + { struct ChunkSt *next; void *ptr[CHUNK_SIZE]; } + *currChunk = NULL, *next; +static int currPtr = CHUNK_SIZE; + +void *fmalloc( int Size , char *tag ) +{ + void *ptr; + + if ( (ptr=malloc( Size )) == NULL ) + { + fprintf(stderr,"? SubFont: Not enought memory for %s(needed %d bytes)\n", + tag,Size); + exit(1); + } + if ( currPtr >= CHUNK_SIZE ) + { + next = xmalloc( sizeof(struct ChunkSt) ); + next->next = currChunk; + currChunk = next; + currPtr = 0; + } + currChunk->ptr[currPtr++] = ptr; + return ptr; +} + +void fAllFree( void ) +/* Freeing all memory which was allocated by fmalloc */ +{ + int j; + long l; + for( l = 0; currChunk != NULL; currChunk = next ) + { + next = currChunk->next; + for( j = 0 ; j < currPtr ; j++,l++ ) free(currChunk->ptr[j]); + free(currChunk); + currPtr = CHUNK_SIZE; + } + if ( Verbose ) fprintf(stderr,"fAllFree(): Freeing %d memory blocks\n",l); +} + +/* decryption stuff */ +static unsigned short er, oer, cr; +static unsigned short c1 = 52845, c2 = 22719; + +/* This function looks for `currentfile eexec' string and returns 1 once found. + If c == 0, then simply check the status. */ + +static char *p_eexec_scan = 0; + +static int eexec_scanner( int /*char*/ c) +{ + static char *key = "currentfile eexec\n"; + + if (!p_eexec_scan) + p_eexec_scan = key; + + if (c && *p_eexec_scan) { + if (c == *p_eexec_scan) + ++p_eexec_scan; + else + p_eexec_scan = key; + } + return *p_eexec_scan == '\0'; +} + +/* This function returns the value of a single hex digit. */ + +static int hexval(char c) +{ + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= '0' && c <= '9') + return c - '0'; + else + return 0; +} + +/* This function returns a single character at a time from a PFA or PFB file. + This stream is mixed ASCII and binary bytes. For PFB files, the section + headers are removed, and \r is replaced by \n in ASCII sections. For PFA + files, the hexdecimal data is turned into binary bytes. */ + + static int first_byte = 1; + static int is_pfa = 0; + static int is_pfb = 0; + static long pfb_remaining = 0; + +static int bgetc() +{ + int c, val; + + /* is_pfa == 1 means PFA initial ASCII section + is_pfa == 2 means PFA hexadecimal section + is_pfb == 1 means PFB ASCII section + is_pfB == 2 means PFB binary section */ + + c = fgetc(ifp); + + if (c == EOF) + return EOF; + + if (first_byte) { + /* Determine if this is a PFA or PFB file by looking at first byte. */ + if (c == 0x80) { + is_pfb = 1; + is_pfa = 0; + } else { + is_pfb = 0; + is_pfa = 1; + } + first_byte = 0; + } + + if (is_pfb) { + /* PFB */ + if (pfb_remaining == 0) { + /* beginning of block---we know c == 0x80 at this point */ + switch (fgetc(ifp)) { + case 1: + is_pfb = 1; + break; + case 2: + is_pfb = 2; + break; + case 3: + return EOF; + default: + fprintf(stderr, "error: is this really a PFB file?\n"); + exit(1); + } + /* get block length */ + pfb_remaining = (long)fgetc(ifp) & 0xff; + pfb_remaining |= ((long)fgetc(ifp) & 0xff) << 8; + pfb_remaining |= ((long)fgetc(ifp) & 0xff) << 16; + pfb_remaining |= ((long)fgetc(ifp) & 0xff) << 24; + /* get character */ + c = fgetc(ifp); + if (c == EOF) + return EOF; + } + --pfb_remaining; + /* in ASCII section change return to newline */ + if (is_pfb == 1 && c == '\r') + c = '\n'; + (void)eexec_scanner(c); + return c; + } else { + /* PFA */ + if (is_pfa == 1) { + /* in initial ASCII */ + if (eexec_scanner(c)) + is_pfa = 2; + return c; + } else { + /* in hexadecimal */ + while (isspace(c)) + c = fgetc(ifp); + val = hexval((char)c) << 4; + val |= hexval((char)(c = fgetc(ifp))); + if (c == EOF) + return EOF; + return val; + } + } +} + +/* Two separate decryption functions because eexec and charstring decryption + must proceed in parallel. */ + +static byte edecrypt(int /*byte */ cipher) +{ + byte plain; + + plain = (byte)(cipher ^ (er >> 8)); + er = (cipher + er) * c1 + c2; + return plain; +} + +static byte cdecrypt( int /*byte*/ cipher) +{ + byte plain; + + plain = (byte)(cipher ^ (cr >> 8)); + cr = (cipher + cr) * c1 + c2; + return plain; +} + +/* This function returns 1 the first time the eexec_scanner returns 1. */ + + static int reported = 0; +static int immediate_eexec() +{ + + if (!reported && eexec_scanner(0)) { + reported = 1; + return 1; + } else { + return 0; + } +} + +/* This function returns a single byte at a time through (possible) eexec + decryption. When immediate_eexec returns 1 it fires up the eexec decryption + machinery. */ + + static int in_eexec = 0, out_eexec = 0; +static int egetc() +{ + int c,j; + + if ((c = bgetc()) == EOF) + return EOF; + + if (!in_eexec) { + if (immediate_eexec()) { + /* start eexec decryption */ + in_eexec = 1; + er = 55665; + /* toss out four random bytes */ + for( j = 4 ; j > 0 ; j-- ) + (void) edecrypt(bgetc()); + } + return c; + } else { + return edecrypt(c); + } +} + +/* This function returns a line of eexec decrypted characters. A line is + terminated by length (including terminating null) greater than LINESIZE, a + newline \n, or one of the special charstring start sequences ` -| ' or + ` RD '. The line, including the terminating newline or charstring start + sequence is put into line[]. If terminated by a charstring start sequence, + the flag start_charstring is set to 1. */ + +static int egetline() +{ + int c,cnt,cntcont; + char *p = line; + + cnt = 0; cntcont = 0; + while (p < line + LINESIZE) { + c = egetc(); + if (c == EOF) + break; + if ( '0' <= c && c <= '9' ) + { cnt = ( cntcont ? cnt * 10 : 0 ) + c - '0' ; cntcont = 1; } + else + cntcont = 0; + *p++ = (char) c; + if (p >= line + 4 && (strncmp(p - 4, " -| ", 4) == 0 || + strncmp(p - 4, " RD ", 4) == 0)) { + for( ; cnt >= 0 ; cnt-- ) *p++ = (char)egetc(); /* load char string */ + } + if (c == '\r') { /* map \r to \n */ + p[-1] = '\n'; + break; + } + if (c == '\n') + break; + } + *p = '\0'; + return (int)(p-line); +} + +/* If the line contains an entry of the form `/lenIV ' then set the global + lenIV to . This indicates the number of random bytes at the beginning + of each charstring. */ + +static void set_lenIV() +{ + char *p = strstr(line, "/lenIV "); + + if (p && isdigit(p[7])) { + lenIV = atoi(p + 7); + } +} + +/* Subroutine to output strings. */ + +# define MAXPOOL 8192 +static char *pool[MAXPOOL]; +static int pool_cnt = 0; + +static void output(char *string) +{ + if ( pool_cnt >= MAXPOOL ) + { fprintf(stderr,"Not enought pool size...\n"); exit(1); } + pool[pool_cnt] = fmalloc( strlen(string) + 1 , "output buffer line" ); + strcpy(pool[pool_cnt],string); + pool_cnt++; +} + +/************************** Output routines .... ************************/ +# define SMALL_MEMORY + +#ifdef SMALL_MEMORY +#define MAXBLOCKLEN 32000 +#else +#define MAXBLOCKLEN ((1<<17)-6) +#endif + +#define MINBLOCKLEN ((1<<8)-6) + +#define MARKER 128 +#define ASCII 1 +#define BINARY 2 +#define DONE 3 + +/* flags */ +static int pfb = 0; +static int active = 0; +/* static int in_eexec = 0; File firstly loaded and then dumped ... */ + +/* for PFB block buffering */ +static byte blockbuf[MAXBLOCKLEN]; +static int blocklen = MAXBLOCKLEN; +static int blockpos = -1; +static int blocktyp = ASCII; + +static byte eencrypt( byte plain) +{ + byte cipher; + + cipher = (byte)(plain ^ (oer >> 8)); + oer = (cipher + oer) * c1 + c2; + return cipher; +} + +/* This function flushes a buffered PFB block. */ + +static void output_block() +{ + int i; + + /* output four-byte block length */ + fputc(blockpos & 0xff, ofp); + fputc((blockpos >> 8) & 0xff, ofp); + fputc((blockpos >> 16) & 0xff, ofp); + fputc((blockpos >> 24) & 0xff, ofp); + + /* output block data */ + for (i = 0; i < blockpos; i++) + fputc(blockbuf[i], ofp); + + /* mark block buffer empty and uninitialized */ + blockpos = -1; +} + +/* This function outputs a single byte. If output is in PFB format then output + is buffered through blockbuf[]. If output is in PFA format, then output + will be hexadecimal if in_eexec is set, ASCII otherwise. */ + +static int hexcol = 0 ; +static void output_byte(byte b) +{ + static char *hexchar = "0123456789ABCDEF"; + + if (pfb) { + /* PFB */ + if (blockpos < 0) { + fputc(MARKER, ofp); + fputc(blocktyp, ofp); + blockpos = 0; + } + blockbuf[blockpos++] = b; + if (blockpos == blocklen) + output_block(); + } else { + /* PFA */ + if (out_eexec) { + /* trim hexadecimal lines to 64 columns */ + if (hexcol >= 64) { + fputc('\n', ofp); + hexcol = 0; + } + fputc(hexchar[(b >> 4) & 0xf], ofp); + fputc(hexchar[b & 0xf], ofp); + hexcol += 2; + } else { + fputc(b, ofp); + } + } +} + +/* This function outputs a byte through possible eexec encryption. */ + +static void eexec_byte(byte b) +{ + if (out_eexec) + output_byte(eencrypt(b)); + else + output_byte(b); +} + +/* This function outputs a null-terminated string through possible eexec + encryption. */ + +static void eexec_string(char *string) +{ + while (*string) + eexec_byte((byte) *string++); +} + +/* This function gets ready for the eexec-encrypted data. If output is in + PFB format then flush current ASCII block and get ready for binary block. + We start encryption with four random (zero) bytes. */ + +static void eexec_start() +{ + if (pfb) { + output_block(); + blocktyp = BINARY; + } + + out_eexec = 1; + oer = 55665; + eexec_byte('B'); + eexec_byte('K'); + eexec_byte('M'); + eexec_byte('!'); +} + +/* This function wraps-up the eexec-encrypted data and writes ASCII trailer. + If output is in PFB format then this entails flushing binary block and + starting an ASCII block. */ + +static void eexec_end() +{ + int i, j; + + if (pfb) { + output_block(); + blocktyp = ASCII; + } else { + fputc('\n', ofp); + } + out_eexec = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 64; j++) + eexec_byte('0'); + eexec_byte('\n'); + } + eexec_string("cleartomark\n"); + if (pfb) { + output_block(); + fputc(MARKER, ofp); + fputc(DONE, ofp); + } +} + +static void Dump_Pool( int from , int to ) +{ + int i; + for ( i = from ; i < to ; i++ ) + { + if ( Eexec_Output ) + { + eexec_string(pool[i]); + if ( strcmp(pool[i], "currentfile eexec\n") == 0 ) eexec_start(); + } + else + { + if ( i == 0 ) + eexec_string("mark %%\n"); + if( strcmp(pool[i], "mark currentfile closefile\n") == 0 ) + eexec_string("end cleartomark%%\n"); + else if ( strcmp(pool[i], "currentfile eexec\n") == 0 ) + eexec_string("systemdict begin\n"); + else + eexec_string(pool[i]); + } + } +} + +static void Dump_CS( int Len , unsigned char *cs ) +{ + if ( Eexec_Output ) + { + char buf[64]; + sprintf(buf," %d %s ", Len, RD_String); + eexec_string(buf); + for( ; Len > 0 ; Len--, cs++) eexec_byte(*cs); + eexec_byte(' '); + } + else + { + int c; + eexec_string("\n<"); + for( c = 2 ; Len > 0 ; Len--, cs++, c += 2) + { + eexec_byte("0123456789ABCDEF"[((*cs)>>4)&0xF]); + eexec_byte("0123456789ABCDEF"[(*cs)&0xF]); + if ( c > 70 ) { eexec_byte('\n'); c = 0; } + } + eexec_string("> "); + } +} + +int Subrs = 0; +int MaxSubrs = 0; +int SubrsPosition = 0; +int HiSubrs = 0; +int HiMaxSubrs = 0; +int HiSubrsPosition = 0; +typedef struct { + unsigned char *cs; + int len; + int use; /* Using marker ... */ + } CSType; +CSType *Subr, *HiSubr; + +int CharStrings = 0; +int CharStringsPosition = 0; +struct { + char *Name; + unsigned char *cs; + int len; + int use; /* Using marker */ + } *CharString; +int CharStringCnt = 0; + +static int sp, stack[128]; +static int cop, vop[32]; +void ProcessCharString( unsigned char *cs , int len ) +{ + int p, i, b, val; + unsigned short cr_save ; + + cr_save = cr; + + cr = 4330; + for (p = 0; p < len && p < lenIV; p++ ) + cdecrypt(cs[p]); + + while ( p < len ) + { + b = cdecrypt(cs[p++]); + if (b >= 32) { + if (b >= 32 && b <= 246) + val = b - 139; + else if (b >= 247 && b <= 250) + val = (b - 247)*256 + 108 + cdecrypt(cs[p++]); + else if (b >= 251 && b <= 254) + val = -(b - 251)*256 - 108 - cdecrypt(cs[p++]); + else if (b == 255) { + val = (cdecrypt(cs[p++]) & 0xff) << 24; + val |= (cdecrypt(cs[p++]) & 0xff) << 16; + val |= (cdecrypt(cs[p++]) & 0xff) << 8; + val |= (cdecrypt(cs[p++]) & 0xff) << 0; + /* in case an int is larger than four bytes---sign extend */ + if (sizeof(int) > 4 && val & (1U << 31)) + for (i = 4; i < sizeof(int); i++) + val |= 0xff << (i * 8); + } + stack[sp++] = val; + } else { + if ( Trace ) fprintf(stderr,"[%d]",b); + switch (b) { + case 1: sp = 0; /* ("hstem"); */ break; + case 3: sp = 0; /* ("vstem"); */ break; + case 4: sp = 0; /* ("vmoveto"); */ break; + case 5: sp = 0; /* ("rlineto"); */ break; + case 6: sp = 0; /* ("hlineto"); */ break; + case 7: sp = 0; /* ("vlineto"); */ break; + case 8: sp = 0; /* ("rrcurveto"); */ break; + case 9: sp = 0; /* ("closepath"); */ break; + case 10: /* ("callsubr"); */ + val = stack[--sp]; + if ( ! ( 0 <= val && val < MaxSubrs ) ) + { + fprintf(stderr,"Illegal call of unexistant subroutine %d\n",val); + exit(1); + } + if ( Trace ) fprintf(stderr,"{%d:",val); + /* if ( ! Subr[val].use ) */ + { /* Process it, if yet not processed ... */ + CSType *SvSubr; + SvSubr = HiSubr; HiSubr = NULL; + Subr[val].use = 1; + ProcessCharString( Subr[val].cs , Subr[val].len ); + HiSubr = SvSubr; + } + if ( HiSubr != NULL ) + { /* Process it, if yet not processed ... */ + CSType *SvSubr; + SvSubr = Subr; Subr = HiSubr; HiSubr = NULL; + Subr[val].use = 1; + ProcessCharString( Subr[val].cs , Subr[val].len ); + HiSubr = Subr; Subr = SvSubr; + } + if ( Trace ) fprintf(stderr,"}"); + break; + case 11: /* ("return"); */ + cr = cr_save; + return; + case 13: sp = 0; /* ("hsbw"); */ break; + case 14: sp = 0; /* ("endchar"); */ break; + case 15: sp = 0; /* Undocumented code but used in blank characters */ + break; + case 21: sp = 0; /* ("rmoveto"); */ break; + case 22: sp = 0; /* ("hmoveto"); */ break; + case 30: sp = 0; /* ("vhcurveto"); */ break; + case 31: sp = 0; /* ("hvcurveto"); */ break; + case 12: + b = cdecrypt(cs[p++]) ; + if ( Trace ) fprintf(stderr,"[%d]",b); + switch (b) { + case 0: sp = 0; /* ("dotsection"); */ break; + case 1: sp = 0; /* ("vstem3"); */ break; + case 2: sp = 0; /* ("hstem3"); */ break; + case 6: /* ("seac"); */ + { + int c1,c2; + c1 = stack[--sp]; + c2 = stack[--sp]; + sp -= 3; + if ( StandardEncoding[c1] == NULL ) + fprintf(stderr,"No character %d in Standard encoding\n",c1); + else + { + for( i = 0 ; i < CharStringCnt ; i++ ) + if ( ! strcmp(CharString[i].Name+1,StandardEncoding[c1]) ) + break; + if ( i >= CharStringCnt ) + fprintf(stderr,"No seac refered character %s in font\n", + StandardEncoding[c1]); + else if ( ! CharString[i].use ) + { + CharString[i].use = 1; + sp = 0; + ProcessCharString( CharString[i].cs , CharString[i].len ); + } + } + c1 = c2; + if ( StandardEncoding[c1] == NULL ) + fprintf(stderr,"No character %d in Standard encoding\n",c1); + else + { + for( i = 0 ; i < CharStringCnt ; i++ ) + if ( ! strcmp(CharString[i].Name+1,StandardEncoding[c1]) ) + break; + if ( i >= CharStringCnt ) + fprintf(stderr,"No seac refered character %s in font\n", + StandardEncoding[c1]); + else if ( ! CharString[i].use ) + { + CharString[i].use = 1; + sp = 0; + ProcessCharString( CharString[i].cs , CharString[i].len ); + } + } + } + break; + case 7: sp = 0; /* ("sbw"); */ break; + case 12: sp--; stack[sp-1] /= stack[sp]; /* ("div"); */ break; + case 16: /* ("callothersubr"); */ + /* I have no Adobe Type 1 manual on hands now and not remember + order of loading arguments in calling of othersubr + but there it is not important. */ + val = stack[--sp]; + cop = stack[--sp]; + for( i = 0 ; i < cop ; i++ ) + vop[i] = stack[--sp]; + /* Special logic there ... */ + if ( val == 3 ) Subr[3].use = 1; /* Used hint replacement */ + break; + case 17: /* ("pop"); */ + stack[sp++] = vop[--cop]; + break; + case 33: sp -= 2; /* sp = 0; */ /* ("setcurrentpoint"); */ break; + default: + fprintf(stderr, "UNKNOWN_12_%d", b); + break; + } + break; + default: + fprintf(stderr, "UNKNOWN_%d", b); + break; + } + } + } /* End while */ + cr = cr_save; +} + +void Fix_String( char *dst , char *Tag , int Val , char *src ) +{ + char *cp,*dp; + strcpy(dst,src); + if ( (cp=strstr(src,Tag)) == NULL ) + { fprintf(stderr,"Nu i nu, not '%s' in '%s'\n",Tag,src); exit(1); } + cp += strlen(Tag); + dp = dst + (cp-src); + while ( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + while ( '0' <= *cp && *cp <= '9' ) cp++; /* skip digits */ + sprintf(dp,"%d%s",Val,cp); +} + +# define MAXENCODINGS 64 +int EncodingPosition = 0; +# ifdef PEDANTICAL_ENCODING_PROCESSING +char **Encoding = 0; +int EncodingCnt = 0; +char **EncodingList[MAXENCODINGS]; + +char *RegisterEncoding( char **Encoding ) +{ + int i,j; + static char buf[64]; + + /* Search the same encoding ... */ + for( i = 0 ; i < EncodingCnt ; i++ ) + { + for( j = 0 ; j < 256 ; j++ ) + if ( strcmp(Encoding[j],EncodingList[i][j]) ) break; + if ( j >= 256 ) break; /* Found the same encoding ... */ + } + if ( i >= EncodingCnt ) + { /* Booking new encoding ... */ + if ( EncodingCnt < MAXENCODINGS ) + EncodingList[EncodingCnt++] = Encoding; + else + fprintf(stderr,"Too many different encodings...\n"); + /* Write this Encoding into file ... */ + fprintf(ofp,"/SubFontEncoding-%d 256 array\n",i); + fprintf(ofp,"0 1 255 {1 index exch /.notdef put} for\n"); + for( j = 0 ; j < 256 ; j++ ) + if ( strcmp(Encoding[j],"/.notdef") ) + fprintf(ofp,"dup %d %s put\n",j,Encoding[j]); + fprintf(ofp,"readonly def\n"); + } + sprintf(buf,"SubFontEncoding-%d",i); + return buf; +} + +void Begin_Encoding( char *line ) +{ + int i; + Encoding = xmalloc( 256 * sizeof(char *) ); + for( i = 0; i < 256 ; i++ ) Encoding[i] = "/.notdef"; +} + +int Fill_Encoding( char *line ) +{ + int IsEncoding ; + char *cp,buf[128]; + + IsEncoding = 1; + if ( (cp=strstr(line," def")) != NULL ) /* End of encoding vector */ + { + char *EncName, buf[128]; + IsEncoding = 0; + EncName = RegisterEncoding( Encoding ); + sprintf(buf,"/Encoding %s def\n",EncName); + pool_cnt--; /* discard previos Encoding line */ + if ( Verbose ) + fprintf(stderr,"End of encoding vector at: %s by %s",line,cp); + output(buf); /* make reference into our encoding ... */ + } + else if ( (cp=strstr(line,"dup ")) != NULL ) + { /* Fill encoding vector by follow material ... */ + int code; + char *ep; + + while ( (cp=strstr(cp,"dup ")) != NULL ) + { + cp += 4; + code = atoi(cp); + if ( code < 0 || code >= 256 ) + { fprintf(stderr,"Invalid encoding '%s'\n",line); exit(1); } + while( *cp && *cp <= ' ' ) cp++; + while( *cp && '0' <= *cp && *cp <= '9' ) cp++; + while( *cp && *cp <= ' ' ) cp++; + if ( *cp != '/' ) + { fprintf(stderr,"Invalid encoding '%s'\n",line); exit(1); } + for( ep = cp ; *ep && *ep > ' ' ; ep++ ); + Encoding[code] = xmalloc( (ep-cp) + 1 ); + memcpy(Encoding[code],cp,ep-cp); + Encoding[code][ep-cp] = 0; + } + } + return IsEncoding; +} +# else +# define MAXENCODINGLINES 512 /* Must be more then 256, for example dcr... */ +int EncodingLines = 0; +char *Encoding[MAXENCODINGLINES]; +int EncodingCnt = 0; +struct { char **Body; int Lines; } EncodingList[MAXENCODINGS]; + +char *RegisterEncoding( char **Encoding ) +{ + int i,j; + static char buf[64]; + + /* Search the same encoding ... */ + for( i = 0 ; i < EncodingCnt ; i++ ) + if ( EncodingList[i].Lines == EncodingLines ) + { + for( j = 0 ; j < EncodingList[i].Lines ; j++ ) + if ( strcmp(Encoding[j],EncodingList[i].Body[j]) ) break; + if ( j >= EncodingList[i].Lines ) break; /* the same encoding ... */ + } + + if ( i >= EncodingCnt ) + { /* Booking new encoding ... */ + if ( EncodingCnt < MAXENCODINGS ) + { + EncodingList[EncodingCnt].Lines = EncodingLines ; + EncodingList[EncodingCnt].Body = + xmalloc( sizeof(char *) * EncodingLines ); + memcpy(EncodingList[EncodingCnt].Body,Encoding, + sizeof(char *) * EncodingLines ); + EncodingCnt++; + } + else + fprintf(stderr,"Too many different encodings...\n"); + /* Write this Encoding into file ... */ + for( j = 0 ; j < EncodingLines ; j++ ) + fputs(Encoding[j],ofp); + fprintf(ofp,"/SubFontEncoding-%d Encoding def\n",i); + } + sprintf(buf,"SubFontEncoding-%d",i); + return buf; +} + +void Begin_Encoding( char *line ) +{ + EncodingLines = 0; + Encoding[EncodingLines++] = xstrdup(line); +} + +int Fill_Encoding( char *line ) +{ + int IsEncoding ; + char *cp; + + IsEncoding = 1; + if ( EncodingLines >= MAXENCODINGLINES ) + { fprintf(stderr,"? SubFont: Too long encoding\n"); exit(1); } + Encoding[EncodingLines++] = xstrdup(line); + if ( (cp=strstr(line," def")) != NULL ) /* End of encoding vector */ + { + char *EncName, buf[128]; + EncName = RegisterEncoding( Encoding ); + sprintf(buf,"/Encoding %s def\n",EncName); + pool_cnt--; /* discard previos Encoding line */ + if ( Verbose ) + fprintf(stderr,"End of encoding vector at: %s by %s",line,cp); + output(buf); /* make reference into our encoding ... */ + return 0; + } + return 1; +} +# endif + +int Process_Font( char *NeedChars ) +{ + int i,k,l; + int IsEncoding; + + /* reset important variables ... */ + Subrs = 0; + MaxSubrs = 0; + SubrsPosition = 0; + HiMaxSubrs = 0; + HiSubrsPosition = 0; + Subr = HiSubr = NULL; + + CharStrings = 0; + CharStringsPosition = 0; + CharStringCnt = 0; + lenIV = 4; + first_byte = 1; + is_pfa = is_pfb = 0; + pfb_remaining = 0; + p_eexec_scan = 0; + reported = 0; + in_eexec = out_eexec = 0; + pool_cnt = 0; + EncodingPosition = 0; + /* Encoding = NULL; */ + IsEncoding = 0; + hexcol = 0; + /* main loop---normally done when reach `mark currentfile closefile' on + output (rest is garbage). */ + + for (;;) { + egetline(); + if (line[0] == '\0') + break; + set_lenIV(); + + if ( IsEncoding ) + { + IsEncoding = Fill_Encoding( line ); + } + else if ( Subrs ) + { + int SubrNo; + char *cp; + for( cp = line ; *cp && *cp <= ' ' ; cp++ ); + if ( strncmp(cp,"dup ",4) != 0 ) + { + fprintf(stderr,"Unexpected end of Subrs: '%s'",line); + fprintf(stderr,"While %d Subrs yet not defined\n",Subrs); + Subrs = 0; + } + else + { + cp += 4; + while( *cp && *cp <= ' ' ) cp++; /* skip leader spaces */ + SubrNo = atoi(cp); + if ( SubrNo < 0 || SubrNo >= MaxSubrs ) + { fprintf(stderr,"Invalid subr number %d\n",SubrNo); exit(1); } + while( '0' <= *cp && *cp <= '9' ) cp++; /* skip digits */ + while( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + Subr[SubrNo].len = atoi(cp); + while( '0' <= *cp && *cp <= '9' ) cp++; /* skip digits */ + while( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + if ( ! ( ( cp[0] == 'R' && cp[1] == 'D' && cp[2] == ' ' ) + || ( cp[0] == '-' && cp[1] == '|' && cp[2] == ' ' ) + ) + ) { fprintf(stderr,"Bad CharString: %s",cp); exit(1); } + if ( cp[0] == 'R' && cp[1] == 'D' ) strcpy(RD_String,"RD"); + if ( cp[0] == '-' && cp[1] == '|' ) strcpy(RD_String,"-|"); + cp += 3 ; + Subr[SubrNo].cs = fmalloc( Subr[SubrNo].len + 1 , "Subrs" ); + memcpy(Subr[SubrNo].cs,cp,Subr[SubrNo].len ); + Subr[SubrNo].cs[Subr[SubrNo].len] = 0; + cp += Subr[SubrNo].len ; + while( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + if ( cp[0] == 'N' && cp[1] == 'P' ) + strcpy(NP_String,"NP"); + else if ( cp[0] == '|' ) + strcpy(NP_String,"|"); + else if ( strncmp(cp,"noaccess put",12) == 0 ) + strcpy(NP_String,"noaccess put"); + else if ( strncmp(cp,"readonly put",12) == 0 ) + strcpy(NP_String,"readonly put"); + else + { fprintf(stderr,"Bad CharString: %s",cp); exit(1); } + + if ( Trace ) fprintf(stderr,"[%d,%d]",SubrNo,Subr[SubrNo].len); + Subrs--; + } + } + else if ( CharStrings ) + { + char *cp; + if ( line[0] != '/' ) + { + fprintf(stderr,"Unexpected end of CharStrings: '%s'",line); + fprintf(stderr,"While %d CharStrings yet not defined\n",Subrs); + CharStrings = 0; + } + else + { + cp = line; + while( *cp && *cp > ' ' ) cp++; /* Skip name */ + *cp++ = 0; + CharString[CharStringCnt].Name = fmalloc(strlen(line)+1,line); + strcpy(CharString[CharStringCnt].Name, line ); + if ( Trace ) fprintf(stderr,"%s",line); + while( *cp && *cp <= ' ' ) cp++; /* Skip spaces ... */ + CharString[CharStringCnt].len = atoi(cp); + while( '0' <= *cp && *cp <= '9' ) cp++; /* skip digits */ + while( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + if ( ! ( ( cp[0] == 'R' && cp[1] == 'D' && cp[2] == ' ' ) + || ( cp[0] == '-' && cp[1] == '|' && cp[2] == ' ' ) + ) + ) { fprintf(stderr,"Bad CharString: %s",cp); exit(1); } + if ( cp[0] == 'R' && cp[1] == 'D' ) strcpy(RD_String,"RD"); + if ( cp[0] == '-' && cp[1] == '|' ) strcpy(RD_String,"-|"); + cp += 3 ; + CharString[CharStringCnt].cs + = fmalloc( CharString[CharStringCnt].len , "CharString" ); + memcpy(CharString[CharStringCnt].cs,cp, + CharString[CharStringCnt].len ); + cp += CharString[CharStringCnt].len ; + while( *cp && *cp <= ' ' ) cp++; /* skip spaces */ + if ( cp[0] == 'N' && cp[1] == 'D' ) + strcpy(ND_String,"ND"); + else if ( cp[0] == '|' && cp[1] == '-' ) + strcpy(ND_String,"|-"); + else if ( strncmp(cp,"noaccess def",12) == 0 ) + strcpy(ND_String,"noaccess def"); + else if ( strncmp(cp,"readonly def",12) == 0 ) + strcpy(ND_String,"readonly def"); + else + { fprintf(stderr,"Bad CharString: %s",cp); exit(1); } + CharStringCnt++; + CharStrings--; + } + } + else + { + char *cp; + if ( (cp=strstr(line,"/Subrs ")) != NULL ) + { /* Start of subrs there ... */ + if ( SubrsPosition ) + { /* HYBRID Type1 fonts have two copies of Subrs, + for High and low resolution devices. + There I will save previously accumulated Subrs ... */ + HiMaxSubrs = MaxSubrs; + HiSubrsPosition = SubrsPosition; + HiSubr = Subr; + } + /* Temporarie, fragments only first copy of Subrs... */ + cp += strlen("/Subrs "); + MaxSubrs = Subrs = atoi(cp); + if ( Verbose ) fprintf(stderr,"Declared %d in Subrs\n",Subrs); + SubrsPosition = pool_cnt ; + Subr = fmalloc( Subrs * sizeof(*Subr) , "Subr array" ); + } + else if ( (cp=strstr(line,"/CharStrings ")) != NULL ) + { /* Start of CharStrings there ... */ + if ( ! CharStringsPosition ) + { /* Only first appearing of /CharStrings indicate real CS */ + cp += strlen("/CharStrings "); + CharStrings = atoi(cp); + if ( Verbose ) + fprintf(stderr,"Declared %d in CharStrings\n",CharStrings); + CharStringsPosition = pool_cnt ; + CharString = fmalloc( CharStrings * sizeof(*CharString) , + "CharString array" ); + CharStringCnt = 0; + } + } + else if ( TouchEncoding && (cp=strstr(line,"/Encoding ")) == line ) + { + if ( (cp=strstr(line,"def")) == NULL ) + { + EncodingPosition = pool_cnt; + IsEncoding = 1; + Begin_Encoding( line ); + } + } + output(line); + } + + if (strcmp(line, "mark currentfile closefile\n") == 0) + break; + } + + if ( Verbose ) + fprintf(stderr,"Loaded %d lines\n",pool_cnt); + + /* Mark ONLY required charstrings ... */ + /* Clear all use markers */ + for( i = 0 ; i < MaxSubrs ; i++ ) Subr[i].use = 0; + if ( HiSubr != NULL ) + for( i = 0 ; i < HiMaxSubrs ; i++ ) HiSubr[i].use = 0; + for( i = 0 ; i < CharStringCnt ; i++ ) CharString[i].use = 0; + + /* Walk Throught Charstrings and mark all used ones. */ + for( i = 0 ; i < CharStringCnt ; i++ ) + { + char buf[128]; + sprintf(buf,"%s/",CharString[i].Name); + if ( strcmp(buf,"/.notdef/") == 0 || strstr(NeedChars,buf) != NULL ) + { + CharString[i].use = 1; + sp = 0; + if ( Trace ) fprintf(stderr,"<%s",buf); + ProcessCharString( CharString[i].cs , CharString[i].len ); + if ( Trace ) fprintf(stderr,">"); + } + } + + /* Simplest variant; replace unused charstrings by shortenest ... */ + l = 0; + for ( i = 0 , k = 0 ; i < MaxSubrs ; i++ ) + if ( ! Subr[i].use ) + { Subr[i] = Subr[3]; Subr[i].use = 0; } + else + { k = i; l++; } + MaxSubrs = k+1; /* Forget tail of unused subrs ... */ + if ( HiSubr != NULL ) + { + for ( i = 0 , k = 0 ; i < HiMaxSubrs ; i++ ) + if ( ! HiSubr[i].use ) + { HiSubr[i] = HiSubr[3]; HiSubr[i].use = 0; } + else + { k = i; l++; } + HiMaxSubrs = k+1; /* Forget tail of unused subrs ... */ + } + + l = MaxSubrs + (HiSubr == NULL ? 0 : HiMaxSubrs) - l; + if ( Verbose ) fprintf(stderr,"%d empty array positions\n",l); + ArrLosts += l * 8; + + /* Now dumps all my fragments ... */ + in_eexec = out_eexec = 0; + if ( SubrsPosition ) + { + if ( HiSubrsPosition ) + { + Dump_Pool( 0 , HiSubrsPosition) ; + if ( HiMaxSubrs > 0 ) /* Can be removed all after filtering ... */ + { /* Dump Subrs there ... */ + Fix_String( line , "/Subrs " , HiMaxSubrs , pool[HiSubrsPosition] ); + eexec_string(line); + for( i = 0 ; i < HiMaxSubrs ; i++ ) + { + if ( (!Eexec_Output) && (!HiSubr[i].use) ) continue; + sprintf(line,"dup %d",i); + eexec_string(line); + Dump_CS(HiSubr[i].len,HiSubr[i].cs); + sprintf(line,"%s\n",NP_String); + eexec_string(line); + } + Dump_Pool( HiSubrsPosition+1, SubrsPosition ) ; + } + else + Dump_Pool( HiSubrsPosition+2 , SubrsPosition) ; + } + else + Dump_Pool( 0 , SubrsPosition) ; + if ( MaxSubrs > 0 ) /* Can be removed all after filtering ... */ + { /* Dump Subrs there ... */ + Fix_String( line , "/Subrs " , MaxSubrs , pool[SubrsPosition] ); + eexec_string(line); + for( i = 0 ; i < MaxSubrs ; i++ ) + { + if ( (!Eexec_Output) && (!Subr[i].use) ) continue; + sprintf(line,"dup %d", i); + eexec_string(line); + Dump_CS(Subr[i].len,Subr[i].cs); + sprintf(line,"%s\n",NP_String); + eexec_string(line); + } + Dump_Pool( SubrsPosition+1, CharStringsPosition ) ; + } + else + Dump_Pool( SubrsPosition+2, CharStringsPosition ) ; + } + else + Dump_Pool( 0, CharStringsPosition ) ; + + for( i = k = 0 ; i < CharStringCnt ; i++ ) + if ( CharString[i].use ) k++; + Fix_String( line , "/CharStrings " , k , pool[CharStringsPosition] ); + eexec_string(line); + for( i = k = 0 ; i < CharStringCnt ; i++ ) + if ( CharString[i].use ) + { + eexec_string(CharString[i].Name); + Dump_CS(CharString[i].len, CharString[i].cs ); + sprintf(line,"%s\n",ND_String); + eexec_string(line); + } + Dump_Pool( CharStringsPosition+1 , pool_cnt ) ; + if ( out_eexec ) + eexec_end(); + else if ( Eexec_Output ) + fprintf(stderr,"? Strange font format (without eexec...)\n"); + + fAllFree(); + return 0; +} + +Copying_Full_Font(void) +{ + int i, cnt; + + lenIV = 4; + first_byte = 1; + is_pfa = is_pfb = 0; + pfb_remaining = 0; + p_eexec_scan = 0; + reported = 0; + in_eexec = out_eexec = 0; + hexcol = 0; + + while ( 1 ) + { + cnt = egetline(); + if ( line[0] == 0 ) break; + set_lenIV(); + for( i = 0 ; i < cnt ; i++ ) + eexec_byte(line[i]); + if (strcmp(line, "mark currentfile closefile\n") == 0) break; + if ( in_eexec && (!out_eexec) ) eexec_start(); + } + if ( out_eexec ) + eexec_end(); + else + fprintf(stderr,"This font is not an ATM compatible, eexec is missed\n"); + return 0; +} + +FILE *Set_Adequate_Read_Mode( FILE *fp , char *fileName ) +/* 25-Nov-94 + I can not correctly read text file which was opened as binary in VMS. + In this reason, if opened file is not PFB i will reopen it in text mode. +*/ +{ +# if defined(vms) || defined(MSDOS) + if ( fgetc(fp) == MARKER ) + ungetc(MARKER,fp); + else + { + fclose(fp); + if ( (fp=fopen(fileName,"r")) == NULL ) + { + fprintf(stderr,"Ops, can't reopen file %s\n",fileName); + exit(1); + } + } +# endif + return fp; +} + +Scan_FontName( char *fileName , FILE *fp ) +{ + int cnt; + + lenIV = 4; + first_byte = 1; + is_pfa = is_pfb = 0; + pfb_remaining = 0; + p_eexec_scan = 0; + reported = 0; + in_eexec = out_eexec = 0; + hexcol = 0; + + if ( (ifp=fopen(fileName,RB)) == NULL ) + { + fprintf(stderr,"? Can't found file %s\n",fileName); + return 0; + } + ifp = Set_Adequate_Read_Mode( ifp , fileName ); + while ( 1 ) + { + cnt = egetline(); + if ( line[0] == 0 ) break; + set_lenIV(); + if( strncmp(line,"/FontName",9) == 0 ) + { + char *cp,*ep; + for( cp = line + 9 ; *cp && *cp <= ' ' ; cp++ ); + for( ep = cp ; *ep && *ep > ' ' ; ep++ ); *ep = '\0'; + fprintf(fp,"%s (%s) ;\n",cp,fileName); + fclose(ifp); + return 1; + } + } + fclose(ifp); + return 0; +} + +struct FontMap { + struct FontMap *next; + char *fontName; + char *fileName; + } *fmp, *fontMap = NULL; + +int main(int ac, char **av) +{ + int ap; + char *cp; + char *Need_Chars = NULL; + char *FontSearchPath = DEFAULTFONTPATH ; + FILE *fp; + char buf[4096]; + + ifp = stdin; + ofp = stdout; + + init_Encoding(); + + for( ap = 1 ; ap < ac ; ap++ ) + if ( av[ap][0] == '-' && av[ap][1] != 0 ) + switch( av[ap][1] ) + { + case 'v': case 'V': /* Like trace verbose */ + Verbose = 1; + break; + case 't': case 'T': /* Trace font processing */ + Trace = 1; + break; + case 'e': case 'E': /* Encoding optimization falg */ + TouchEncoding = atoi(av[ap]+2); + break; + case 'x': case 'X': /* output eexec using flag */ + Eexec_Output = atoi(av[ap]+2); + break; + case 'o': case 'O': /* ... Open output file there */ + cp = av[ap][2] ? av[ap]+2 : av[++ap] ; + if ( (ofp=fopen(cp,"w")) == NULL ) + { fprintf(stderr,"? Can't create file: '%s'\n",cp); return 1; } + break; + case 'a': case 'A': /* ... Open output file for append */ + cp = av[ap][2] ? av[ap]+2 : av[++ap] ; + if ( (ofp=fopen(cp,"a")) == NULL ) + { fprintf(stderr,"? Can't open for append file: '%s'\n",cp); return 1; } + break; + case 'b': case 'B': /* Open binary file for output */ + cp = av[ap][2] ? av[ap]+2 : av[++ap] ; + if ( (ofp=fopen(cp,WB)) == NULL ) + { fprintf(stderr,"? Can't create file: '%s'\n",cp); return 1; } + pfb = 1; + break; + case 'c': case 'C': /* Copy specified file to output as is */ + /* Generally, this code solves problems of the file merging + of different record type in VMS operating system. + */ + cp = av[ap][2] ? av[ap]+2 : av[++ap] ; + if ( cp[0] == '-' && cp[1] == 0 ) + ifp = stdin ; + else if ( (ifp=fopen(cp,"r")) == NULL ) + { fprintf(stderr,"? Can't found file: '%s'\n",cp); return 1; } + while ( fgets(buf,sizeof(buf),ifp) != NULL ) + fputs(buf,ofp); + if ( ifp != stdin ) fclose(ifp); + Files++; + break; + case 'u': case 'U': /* Open binary file for output */ + uFileName = av[ap][2] ? av[ap]+2 : av[++ap] ; + break; + case 'n': case 'N': /* Load required names ... */ + Need_Chars = av[ap] + 2 ; + break; + case 'i': case 'I': /* Install font search path */ + FontSearchPath = av[ap]+2; + break; + case 'm': case 'M': /* font mapping file */ + cp = av[ap][2] ? av[ap]+2 : av[++ap] ; + if ( (fp=fopen(cp,"r")) == NULL ) + {fprintf(stderr,"? SubFont: Can't found file '%s'\n",cp); return 1;} + while ( fgets(buf,sizeof(buf),fp) != NULL ) + { + char *fontp,*ecp; + for( cp = buf; *cp && *cp <= ' ' ; cp++ ); /* skip spaces */ + if ( *cp == 0 || *cp == '%' ) continue; /* Comment or empty line */ + if ( *cp == '/' ) + { /* Process GhostScript like font map */ + fontp = ++cp; + while ( *cp && *cp > ' ' ) cp++; /* search end of font name */ + *cp++ = 0; + while ( *cp && *cp <= ' ' ) cp++; + if ( *cp == '(' ) + { /* Format like to: '/FontName (file-name) ; */ + for( ecp = ++cp; *ecp && *ecp > ' ' && *ecp != ')'; ecp++); + *ecp = 0; + } + else + { /* Format like to: '/Fontmap file-name' */ + for( ecp=cp ; *ecp && *ecp > ' ' ; ecp++); + *ecp = 0; + } + } + else + { /* Process simple format Fontmap */ + fontp = cp; + while ( *cp && *cp > ' ' ) cp++; /* search end of font name */ + *cp++ = 0; + while ( *cp && *cp <= ' ' ) cp++; + for( ecp=cp ; *ecp && *ecp > ' ' ; ecp++); *ecp = 0; + } + /* Add entry to font mapping list */ + fmp = xmalloc(sizeof(struct FontMap)); + fmp->next = fontMap; + fmp->fontName = xstrdup(fontp); + fmp->fileName = xstrdup(cp); + fontMap = fmp; + } + fclose(fp); + break; + case 'f': case 'F': /* Load all fonts according psfontstat list */ + if ( pfb ) + { + fprintf(stderr, + "Processing several fonts into one PFB not available.\n"); + return 1; + } + else + { + cp = av[ap][2] ? av[ap]+2 : (ap+1next) + if ( strcmp(fmp->fontName,fontName) == 0 ) + { + /* fprintf(stderr,"Font '%s' looks in file '%s'\n", + fmp->fontName,fmp->fileName); */ + strcpy(fontName,fmp->fileName); + break; + } + /* install list of required characters */ + Need_Chars = cp; + /* Search font file */ + for( ifp = NULL, cp = FontSearchPath ; *cp > ' ' ; cp = ep ) + { + int j; + if( (ep=strchr(cp,PATH_DELIMITER)) == NULL ) + ep = cp + strlen(cp); + j = (int)(ep - cp); if ( *ep == PATH_DELIMITER ) ep++; + memcpy(fileName,cp,j); + if ( FILE_DELIMITER != '\0' ) + if ( j && fileName[j-1] != FILE_DELIMITER ) + fileName[j++] = FILE_DELIMITER; + strcpy(fileName+j,fontName); j = strlen(fileName); + if ( Verbose ) fprintf(stderr,"Try open '%s'\n",fileName); + if ( (ifp=fopen(fileName,RB)) != NULL ) break; + if ( strcmp(fntName,fontName) == 0 ) + { + strcpy(fileName+j,".pfb"); + if ( Verbose ) fprintf(stderr,"Try open '%s'\n",fileName); + if ( (ifp=fopen(fileName,RB)) != NULL ) break; + strcpy(fileName+j,".pfa"); + if ( Verbose ) fprintf(stderr,"Try open '%s'\n",fileName); + if ( (ifp=fopen(fileName,RB)) != NULL ) break; + } + } + if ( ifp == NULL ) + { + fprintf(stderr,"Can't found font '%s' in path '%s'\n", + fontName,FontSearchPath); + if ( ufp == NULL && uFileName != NULL ) + { + if ( (ufp=fopen(uFileName,"w")) == NULL ) + { fprintf(stderr,"? Can't create file: '%s'\n",uFileName); } + } + if ( ufp != NULL ) + fprintf(ufp,"%s\n",fontName); + continue; + } + else + fprintf(stderr,"Process font '%s' from file '%s'\n", + fntName,fileName); + /*fprintf(ofp,"(Loading font %s\\n) print flush\n",fontName);*/ + TouchEncoding++; + Eexec_Output--; + ifp = Set_Adequate_Read_Mode( ifp , fileName ); + Process_Font( Need_Chars ); + Eexec_Output++; + TouchEncoding--; + if ( ifp != stdin ) fclose(ifp); + Files++; + } + } + break; + case 'z': case 'Z': /* This command is used to make font map */ + if ( av[ap][2] == '\0' ) + ofp = stdout; + else if ( (ofp=fopen(av[ap]+2,"a")) == NULL ) + { + fprintf(stderr,"? SubFont: Can't write file '%s'\n",av[ap]+2); + return 1; + } + for( ap++ ; ap < ac ; ap++ ) + Scan_FontName( av[ap] , ofp ); + return 0; + default: + fprintf(stderr,"? SubFont: Unknown option '%s'\n",av[ap]); + return 1; + } + else + { + if ( pfb && Files ) + { + fprintf(stderr, + "Processing several fonts into one PFB not available.\n"); + return 1; + } +# ifndef vms + if ( av[ap][0] == '-' && av[ap][1] == 0 ) + ifp = stdin ; + else +# endif + if ( (ifp=fopen(av[ap],RB)) == NULL ) + { fprintf(stderr,"? Can't found file: '%s'\n",av[ap]); return 1; } + ifp = Set_Adequate_Read_Mode( ifp , av[ap] ); + if ( Need_Chars == NULL ) + { if ( Copying_Full_Font() ) exit(1); } + else + Process_Font( Need_Chars ); + if ( ifp != stdin ) fclose(ifp); + Files++; + } + + if ( ! Files ) + { + fprintf(stderr,"%s designed by %s\n",PROBLEM,AUTHOR); + fprintf(stderr,"Shortly called %s, Version %s/%s, Revision Date %s\n", + PROGRAM, VERSION, SYSID, REVDATE); + fprintf(stderr,"Copyright (C) %s All Rights Reserved.\n\n",COPYRIGHT); + fprintf(stderr,"Usage: SubFont [options] { -n... | } \n"); + fprintf(stderr," Options are:\n"); + fprintf(stderr," -v - Verbose ...\n"); + fprintf(stderr," -o - Output file (Default is stdout)\n"); + fprintf(stderr," -a - Output file in append(text) mode\n"); + fprintf(stderr," -b - Output binary file (PFB)\n"); + fprintf(stderr," -c - Copying specified file to output as is\n"); + fprintf(stderr," -n/../../ - List of names of required characters ...\n"); + fprintf(stderr," - Process font from file...\n"); +# ifndef vms + fprintf(stderr," - - Process font from stdin...\n"); +# endif + fprintf(stderr," -f - Process font list from file.\n"); + fprintf(stderr," -m - Font mapping file (used with -f)\n"); + fprintf(stderr," -I - Font search path (used with -f)\n"); + fprintf(stderr," Default='%s'\n",FontSearchPath); + fprintf(stderr," -u - File for put list of undefined fonts (used with -f)\n"); + fprintf(stderr," -e# - Encoding optimization flag...\n"); + fprintf(stderr," -x# - output eexec using flag...\n"); + fprintf(stderr," -z - read files and print it PS name...\n"); + return 1; + } + else + { + fprintf(stderr,"Totaly %d files are processed.\n",Files % 10000 ); + if ( Verbose ) + fprintf(stderr,"Totally %d unused bytes in Subr arrays\n",ArrLosts); + } + if ( ofp != stdout ) fclose(ofp); + if ( ufp != NULL ) fclose(ufp); + return 0; +} + -- cgit v1.2.3