summaryrefslogtreecommitdiff
path: root/fonts/utilities/fontload/src/subfont.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /fonts/utilities/fontload/src/subfont.c
Initial commit
Diffstat (limited to 'fonts/utilities/fontload/src/subfont.c')
-rw-r--r--fonts/utilities/fontload/src/subfont.c1860
1 files changed, 1860 insertions, 0 deletions
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 <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <ctype.h>
+
+# 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 <num>' then set the global
+ lenIV to <num>. 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+1<ac?av[++ap]:"-") ;
+ if ( cp[0] == '-' && cp[1] == '\0' )
+ fp = stdin;
+ else if ( (fp=fopen(cp,"r")) == NULL )
+ { fprintf(stderr,"No file '%s'\n",cp); return 1; }
+ Files += 10000 ;
+ while ( fgets( buf, sizeof(buf), fp ) != NULL )
+ {
+ char *cp, *ep, fntName[64],fontName[64],fileName[256];
+ /* extract font name */
+ if ( (cp=strchr(buf,'/')) == NULL || cp == buf )
+ { fprintf(stderr,"Invalid: '%s'\n",buf); return 1; }
+ memcpy(fontName,buf,(int)(cp-buf)); fontName[cp-buf] = '\0';
+ strcpy(fntName,fontName);
+ /* Search alias in map ... */
+ for( fmp = fontMap ; fmp != NULL ; fmp=fmp->next)
+ 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... | <in-file> } \n");
+ fprintf(stderr," Options are:\n");
+ fprintf(stderr," -v - Verbose ...\n");
+ fprintf(stderr," -o<file> - Output file (Default is stdout)\n");
+ fprintf(stderr," -a<file> - Output file in append(text) mode\n");
+ fprintf(stderr," -b<file> - Output binary file (PFB)\n");
+ fprintf(stderr," -c<file> - Copying specified file to output as is\n");
+ fprintf(stderr," -n/../../ - List of names of required characters ...\n");
+ fprintf(stderr," <file> - Process font from file...\n");
+# ifndef vms
+ fprintf(stderr," - - Process font from stdin...\n");
+# endif
+ fprintf(stderr," -f<file> - Process font list from file.\n");
+ fprintf(stderr," -m<file> - Font mapping file (used with -f)\n");
+ fprintf(stderr," -I<path> - Font search path (used with -f)\n");
+ fprintf(stderr," Default='%s'\n",FontSearchPath);
+ fprintf(stderr," -u<file> - 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;
+}
+