Back to index

tetex-bin  3.0
writet1.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
00003 
00004 This file is part of pdfTeX.
00005 
00006 pdfTeX is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 pdfTeX is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with pdfTeX; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#23 $
00021 */
00022 
00023 static const char perforce_id[] = 
00024     "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#23 $";
00025 
00026 #ifdef pdfTeX /* writet1 used with pdfTeX */
00027 #include "ptexlib.h"           
00028 #define t1_log(s)           tex_printf(s)
00029 #define t1_open()           \
00030     open_input(&t1_file, kpse_type1_format, FOPEN_RBIN_MODE)
00031 #define enc_open()      \
00032     open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE)
00033 #define external_enc()      (fm_cur->encoding)->glyph_names
00034 #define full_file_name()    (char*)nameoffile + 1
00035 #define get_length1()       t1_length1 = t1_offset() - t1_save_offset
00036 #define get_length2()       t1_length2 = t1_offset() - t1_save_offset
00037 #define get_length3()       t1_length3 = t1_offset() - t1_save_offset
00038 #define is_used_char(c)     pdfcharmarked(tex_font, c)
00039 #define t1_putchar          fb_putchar
00040 #define t1_offset           fb_offset  
00041 #define out_eexec_char      t1_putchar
00042 #define save_offset()       t1_save_offset = t1_offset()
00043 #define end_last_eexec_line()   \
00044     t1_eexec_encrypt = false
00045 #define update_builtin_enc(font, glyph_names)    update_enc(font, glyph_names) 
00046 #define t1_char(c)          c
00047 #define embed_all_glyphs(tex_font)  fm_cur->all_glyphs
00048 #define extra_charset()     fm_cur->charset
00049 #define update_subset_tag() \
00050     strncpy(fb_array + t1_fontname_offset, fm_cur->subset_tag, 6)
00051 
00052 integer t1_length1, t1_length2, t1_length3;
00053 static integer t1_save_offset;
00054 static integer t1_fontname_offset;
00055 extern char *fb_array;
00056 
00057 #else /* writet1 used with dvips */
00058 #include "dvips.h"
00059 #include "ptexmac.h"
00060 #undef  fm_extend
00061 #define fm_extend(f)        0
00062 #undef  fm_slant
00063 #define fm_slant(f)         0
00064 #undef  is_reencoded
00065 #define is_reencoded(f)     (cur_enc_name != NULL)
00066 #undef  is_subsetted
00067 #define is_subsetted(f)     true
00068 #undef  is_included
00069 #define is_included(f)      true
00070 #undef  set_cur_file_name
00071 #define set_cur_file_name(s)    cur_file_name = s
00072 #define t1_open()           \
00073     ((t1_file = search(headerpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
00074 #define enc_open()           \
00075     ((enc_file = search(encpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
00076 #define external_enc()      ext_glyph_names
00077 #define full_file_name()    cur_file_name
00078 #define get_length1()
00079 #define get_length2()
00080 #define get_length3()
00081 #define is_used_char(c)     (grid[c] == 1)
00082 #define out_eexec_char      t1_outhex
00083 #define save_offset()
00084 #define end_last_eexec_line()       \
00085     hexline_length = HEXLINE_WIDTH; \
00086     end_hexline();                  \
00087     t1_eexec_encrypt = false
00088 #define t1_log(s)
00089 #define t1_scan_only()
00090 #define t1_include()
00091 #define t1_putchar(c)       fputc(c, bitfile)
00092 #define t1_scan_keys()
00093 #define update_builtin_enc(font, glyph_names) 
00094 #define embed_all_glyphs(tex_font)  false
00095 #undef pdfmovechars
00096 #ifdef SHIFTLOWCHARS
00097 extern Boolean shiftlowchars;
00098 #define pdfmovechars shiftlowchars
00099 #define t1_char(c)          T1Char(c)
00100 #else /* SHIFTLOWCHARS */
00101 #define t1_char(c)          c
00102 #define pdfmovechars 0
00103 #endif /* SHIFTLOWCHARS */
00104 #define extra_charset()     dvips_extra_charset
00105 #define make_subset_tag(a, b)
00106 #define update_subset_tag()
00107 
00108 static char *dvips_extra_charset ;
00109 extern FILE *bitfile ;
00110 extern FILE *search();
00111 static char *cur_file_name;
00112 static char *cur_enc_name;
00113 static unsigned char *grid;
00114 static char *ext_glyph_names[MAX_CHAR_CODE + 1];                                        
00115 static char print_buf[PRINTF_BUF_SIZE];
00116 static int  hexline_length;
00117 static char notdef[] = ".notdef";
00118 static size_t last_ptr_index;
00119 #endif /* pdfTeX */
00120 
00121 #include <kpathsea/c-vararg.h>
00122 #include <kpathsea/c-proto.h>
00123 
00124 #define t1_getchar()    getc(t1_file)
00125 #define t1_ungetchar(c) ungetc(c, t1_file)
00126 #define t1_eof()        feof(t1_file)
00127 #define t1_close()      xfclose(t1_file, cur_file_name)
00128 
00129 #define enc_getchar()   getc(enc_file)
00130 #define enc_eof()       feof(enc_file)
00131 #define enc_close()     xfclose(enc_file, cur_file_name)
00132 
00133 #define valid_code(c)   (c >= 0 && c <= MAX_CHAR_CODE)
00134 
00135 static const char *standard_glyph_names[MAX_CHAR_CODE + 1] = {
00136 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00137 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00138 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00139 notdef, notdef, notdef, notdef, notdef, "space", "exclam", "quotedbl",
00140 "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft",
00141 "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
00142 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
00143 "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at",
00144 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
00145 "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
00146 "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a",
00147 "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
00148 "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
00149 "braceright", "asciitilde", notdef, notdef, notdef, notdef, notdef, notdef,
00150 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00151 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00152 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00153 notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
00154 "section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
00155 "guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash", "dagger",
00156 "daggerdbl", "periodcentered", notdef, "paragraph", "bullet",
00157 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
00158 "ellipsis", "perthousand", notdef, "questiondown", notdef, "grave", "acute",
00159 "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", notdef,
00160 "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash",
00161 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
00162 notdef, notdef, notdef, notdef, notdef, notdef, notdef, "AE", notdef,
00163 "ordfeminine", notdef, notdef, notdef, notdef, "Lslash", "Oslash", "OE",
00164 "ordmasculine", notdef, notdef, notdef, notdef, notdef, "ae", notdef, notdef,
00165 notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe", "germandbls",
00166 notdef, notdef, notdef, notdef
00167 };
00168 
00169 static char charstringname[] = "/CharStrings";
00170 
00171 char **t1_glyph_names;
00172 char *t1_builtin_glyph_names[MAX_CHAR_CODE + 1];                                        
00173 static boolean read_encoding_only;
00174 static int t1_encoding;
00175 
00176 #define T1_BUF_SIZE   0x10
00177 #define ENC_BUF_SIZE  0x1000
00178 
00179 #define ENC_STANDARD  0
00180 #define ENC_BUILTIN   1
00181 
00182 #define CS_HSTEM            1
00183 #define CS_VSTEM            3
00184 #define CS_VMOVETO          4
00185 #define CS_RLINETO          5
00186 #define CS_HLINETO          6
00187 #define CS_VLINETO          7
00188 #define CS_RRCURVETO        8
00189 #define CS_CLOSEPATH        9
00190 #define CS_CALLSUBR         10
00191 #define CS_RETURN           11
00192 #define CS_ESCAPE           12
00193 #define CS_HSBW             13
00194 #define CS_ENDCHAR          14
00195 #define CS_RMOVETO          21
00196 #define CS_HMOVETO          22
00197 #define CS_VHCURVETO        30
00198 #define CS_HVCURVETO        31
00199 #define CS_1BYTE_MAX        (CS_HVCURVETO + 1)
00200 
00201 #define CS_DOTSECTION       CS_1BYTE_MAX + 0
00202 #define CS_VSTEM3           CS_1BYTE_MAX + 1
00203 #define CS_HSTEM3           CS_1BYTE_MAX + 2
00204 #define CS_SEAC             CS_1BYTE_MAX + 6
00205 #define CS_SBW              CS_1BYTE_MAX + 7
00206 #define CS_DIV              CS_1BYTE_MAX + 12
00207 #define CS_CALLOTHERSUBR    CS_1BYTE_MAX + 16
00208 #define CS_POP              CS_1BYTE_MAX + 17
00209 #define CS_SETCURRENTPOINT  CS_1BYTE_MAX + 33
00210 #define CS_2BYTE_MAX        (CS_SETCURRENTPOINT + 1)
00211 #define CS_MAX              CS_2BYTE_MAX
00212 
00213 typedef unsigned char byte;
00214 
00215 typedef struct {
00216     byte nargs;     /* number of arguments */
00217     boolean bottom; /* take arguments from bottom of stack? */
00218     boolean clear;  /* clear stack? */
00219     boolean valid;
00220 } cc_entry; /* CharString Command */
00221 
00222 typedef struct {
00223     char *name;             /* glyph name (or notdef for Subrs entry) */
00224     byte *data;
00225     unsigned short len;     /* length of the whole string */
00226     unsigned short cslen;   /* length of the encoded part of the string */
00227     boolean used;
00228     boolean valid;
00229 } cs_entry;
00230 
00231 static unsigned short t1_dr, t1_er;
00232 static const unsigned short t1_c1 = 52845, t1_c2 = 22719;
00233 static unsigned short t1_cslen;
00234 static short t1_lenIV;
00235 static char enc_line[ENC_BUF_SIZE];
00236 
00237 /* define t1_line_ptr, t1_line_array & t1_line_limit */
00238 typedef char t1_line_entry;
00239 define_array(t1_line);   
00240 
00241 /* define t1_buf_ptr, t1_buf_array & t1_buf_limit */
00242 typedef char t1_buf_entry;
00243 define_array(t1_buf);   
00244 
00245 static int cs_start;
00246 
00247 static cs_entry *cs_tab, *cs_ptr, *cs_notdef;
00248 static char *cs_dict_start, *cs_dict_end;
00249 static int cs_count, cs_size, cs_size_pos;
00250 
00251 static cs_entry *subr_tab;
00252 static char *subr_array_start, *subr_array_end;
00253 static int subr_max, subr_size, subr_size_pos;
00254 
00255 /* This list contains the begin/end tokens commonly used in the */
00256 /* /Subrs array of a Type 1 font.                                */
00257 static const char *cs_token_pairs_list[][2] = {
00258   {" RD", "NP"},
00259   {" -|", "|"},
00260   {" RD", "noaccess put"},
00261   {" -|", "noaccess put"},
00262   {NULL, NULL}
00263 };
00264 static const char **cs_token_pair;
00265 
00266 static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
00267 static int  t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
00268 static long t1_block_length;
00269 static int  last_hexbyte;
00270 static FILE *t1_file;
00271 static FILE *enc_file;
00272 
00273 #define str_prefix(s1, s2)  (strncmp(s1, s2, strlen(s2)) == 0)
00274 #define t1_prefix(s)        str_prefix(t1_line_array, s)
00275 #define t1_buf_prefix(s)    str_prefix(t1_buf_array, s)
00276 #define t1_suffix(s)        str_suffix(t1_line_array, t1_line_ptr, s)
00277 #define t1_buf_suffix(s)    str_suffix(t1_buf_array, t1_buf_ptr, s)
00278 #define t1_charstrings()    strstr(t1_line_array, charstringname)
00279 #define t1_subrs()          t1_prefix("/Subrs")
00280 #define t1_end_eexec()      t1_suffix("mark currentfile closefile")
00281 #define t1_cleartomark()    t1_prefix("cleartomark")
00282 
00283 #ifndef pdfTeX
00284 static void pdftex_fail(char *fmt,...)
00285 {
00286     va_list args;
00287     va_start(args, fmt);
00288     fputs("\nError: module writet1", stderr);
00289     if (cur_file_name)
00290         fprintf(stderr, " (file %s)", cur_file_name);
00291     fputs(": ", stderr);
00292     vsprintf(print_buf, fmt, args);
00293     fputs(print_buf, stderr);
00294     fputs("\n ==> Fatal error occurred, the output PS file is not finished!\n", stderr);
00295     va_end(args);
00296     exit(-1);
00297 }
00298 
00299 static void pdftex_warn(char *fmt,...)
00300 {
00301     va_list args;
00302     va_start(args, fmt);
00303     fputs("\nWarning: module writet1 of dvips", stderr);
00304     if (cur_file_name)
00305         fprintf(stderr, " (file %s)", cur_file_name);
00306     fputs(": ", stderr);
00307     vsprintf(print_buf, fmt, args);
00308     fputs(print_buf, stderr);
00309     fputs("\n", stderr);
00310     va_end(args);
00311 }
00312 
00313 #define HEXLINE_WIDTH 64
00314 
00315 static void end_hexline()
00316 {
00317     if (hexline_length == HEXLINE_WIDTH) {
00318         fputs("\n", bitfile);
00319         hexline_length = 0;
00320     }
00321 }
00322 
00323 static void t1_outhex(byte b)
00324 {
00325     static char *hexdigits = "0123456789ABCDEF";
00326     t1_putchar(hexdigits[b/16]);
00327     t1_putchar(hexdigits[b%16]);
00328     hexline_length += 2;
00329     end_hexline();
00330 }
00331 #endif /* pdfTeX */
00332 
00333 
00334 static void enc_getline(void)
00335 {
00336     char *p;
00337     int c;
00338 restart:
00339     if (enc_eof())
00340         pdftex_fail("unexpected end of file");
00341     p = enc_line;
00342     do {
00343         c = enc_getchar();
00344         append_char_to_buf(c, p, enc_line, ENC_BUF_SIZE);
00345     } while (c != 10);
00346     append_eol(p, enc_line, ENC_BUF_SIZE);
00347     if (p - enc_line < 2 || *enc_line == '%')
00348         goto restart;
00349 }
00350 
00351 void load_enc(char *enc_name, char **glyph_names)
00352 {
00353     char buf[ENC_BUF_SIZE], *p, *r;
00354     int names_count;
00355     set_cur_file_name(enc_name);
00356     if (!enc_open()) {
00357         pdftex_warn("cannot open encoding file for reading");
00358         cur_file_name = NULL;
00359         return;
00360     }
00361     t1_log("{");
00362     t1_log(cur_file_name = full_file_name());
00363     enc_getline();
00364     if (*enc_line != '/' || (r = strchr(enc_line, '[')) == NULL) {
00365         remove_eol(r, enc_line);
00366         pdftex_fail("invalid encoding vector (a name or `[' missing): `%s'", enc_line);
00367     }
00368     names_count = 0;
00369     r++; /* skip '[' */
00370     skip(r, ' ');
00371     for (;;) {
00372         while (*r == '/') {
00373             for (p = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
00374             *p = 0;
00375             skip(r, ' ');
00376             if (names_count > MAX_CHAR_CODE)
00377                 pdftex_fail("encoding vector contains more than %i names",
00378                             (int)(MAX_CHAR_CODE + 1));
00379             if (strcmp(buf, notdef) != 0)
00380                 glyph_names[names_count] = xstrdup(buf);
00381             names_count++;
00382         }
00383         if (*r != 10 && *r != '%') {
00384             if (strncmp(r, "] def", strlen("] def")) == 0) 
00385                 goto done;
00386             else {
00387                 remove_eol(r, enc_line);
00388                 pdftex_fail("invalid encoding vector: a name or `] def' expected: `%s'", enc_line);
00389             }
00390         }
00391         enc_getline();
00392         r = enc_line;
00393     }
00394 done:
00395     enc_close();
00396     t1_log("}");
00397     cur_file_name = NULL;
00398 }
00399 
00400 static void t1_check_pfa(void)
00401 {
00402     int c = t1_getchar();
00403     if (c != 128)
00404         t1_pfa = true;
00405     else 
00406         t1_pfa = false;
00407     t1_ungetchar(c);
00408 }
00409 
00410 static int t1_getbyte(void)
00411 {
00412     int c = t1_getchar();
00413     if (t1_pfa)
00414         return c;
00415     if (t1_block_length == 0) {
00416         if (c != 128)
00417             pdftex_fail("invalid marker");
00418         c = t1_getchar();
00419         if (c == 3) {
00420             while (!t1_eof())
00421                 t1_getchar();
00422             return EOF;
00423         }
00424         t1_block_length = t1_getchar() & 0xff;
00425         t1_block_length |= (t1_getchar() & 0xff) << 8;
00426         t1_block_length |= (t1_getchar() & 0xff) << 16;
00427         t1_block_length |= (t1_getchar() & 0xff) << 24;
00428         c = t1_getchar();
00429     }
00430     t1_block_length--;
00431     return c;
00432 }
00433 
00434 static int hexval(int c)
00435 {
00436     if (c >= 'A' && c <= 'F')
00437         return c - 'A' + 10;
00438     else if (c >= 'a' && c <= 'f')
00439         return c - 'a' + 10;
00440     else if (c >= '0' && c <= '9')
00441         return c - '0';
00442     else
00443         return -1;
00444 }
00445 
00446 static byte edecrypt(byte cipher)
00447 {
00448     byte plain;
00449     if (t1_pfa) {
00450         while (cipher == 10 || cipher == 13)
00451             cipher = t1_getbyte();
00452         last_hexbyte = cipher = (hexval(cipher) << 4) + hexval(t1_getbyte());
00453     }
00454     plain = (cipher^(t1_dr >> 8));
00455     t1_dr = (cipher + t1_dr)*t1_c1 + t1_c2;
00456     return plain;
00457 }
00458 
00459 static byte cdecrypt(byte cipher, unsigned short *cr)
00460 {
00461     byte plain = (cipher^(*cr >> 8));
00462     *cr = (cipher + *cr)*t1_c1 + t1_c2;
00463     return plain;
00464 }
00465 
00466 static byte eencrypt(byte plain)
00467 {
00468     byte cipher = (plain^(t1_er >> 8));
00469     t1_er = (cipher + t1_er)*t1_c1 + t1_c2;
00470     return cipher;
00471 }
00472 
00473 static byte cencrypt(byte plain, unsigned short *cr)
00474 {
00475     byte cipher = (plain^(*cr >> 8));
00476     *cr = (cipher + *cr)*t1_c1 + t1_c2;
00477     return cipher;
00478 }
00479 
00480 static char *eol(char *s)
00481 {
00482     char *p = strend(s);
00483     if (p - s > 1 && p[-1] != 10) {
00484         *p++ = 10;
00485         *p = 0;
00486     }
00487     return p;
00488 }
00489 
00490 static float t1_scan_num(char *p, char **r)
00491 {
00492     float f;
00493     skip(p, ' ');
00494     if (sscanf(p, "%g", &f) != 1) {
00495         remove_eol(p, t1_line_array);
00496         pdftex_fail("a number expected: `%s'", t1_line_array);
00497     }
00498     if (r != NULL) {
00499         for (; isdigit(*p) || *p == '.' || 
00500                *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
00501         *r = p;
00502     }
00503     return f;
00504 }
00505 
00506 static boolean str_suffix(const char *begin_buf, const char *end_buf, 
00507                           const char *s) 
00508 {
00509     const char *s1 = end_buf - 1, 
00510                *s2 = strend(s) - 1;
00511     if (*s1 == 10)
00512         s1--;
00513     while (s1 >= begin_buf && s2 >= s) {
00514         if (*s1-- != *s2--)
00515             return false;
00516     }
00517     return s2 < s;
00518 }
00519 
00520 static void t1_getline(void) 
00521 {
00522     int c, l, eexec_scan;
00523     char *p;
00524     static const char eexec_str[] = "currentfile eexec";
00525     static int eexec_len = 17; /* strlen(eexec_str) */
00526 restart:
00527     if (t1_eof())
00528         pdftex_fail("unexpected end of file");
00529     t1_line_ptr = t1_line_array;
00530     alloc_array(t1_line, 1, T1_BUF_SIZE);
00531     t1_cslen = 0;
00532     eexec_scan = 0;
00533     c = t1_getbyte();
00534     if (c == EOF)
00535         goto exit;
00536     while (!t1_eof()) {
00537         if (t1_in_eexec == 1) 
00538             c = edecrypt(c);
00539         alloc_array(t1_line, 1, T1_BUF_SIZE);
00540         append_char_to_buf(c, t1_line_ptr, t1_line_array, t1_line_limit);
00541         if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
00542             if (t1_line_array[eexec_scan] == eexec_str[eexec_scan])
00543                 eexec_scan++;
00544             else
00545                 eexec_scan = -1;
00546         }
00547         if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32))
00548             break;
00549         if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line_array > 4) && 
00550            (t1_suffix(" RD ") || t1_suffix(" -| "))) {
00551             p = t1_line_ptr - 5;
00552             while (*p != ' ')
00553                 p--;
00554             t1_cslen = l = t1_scan_num(p + 1, 0);
00555             cs_start = t1_line_ptr - t1_line_array; /* cs_start is an index now */
00556             alloc_array(t1_line, l, T1_BUF_SIZE);
00557             while (l-- > 0)
00558                 *t1_line_ptr++ = edecrypt(t1_getbyte());
00559         }
00560         c = t1_getbyte();
00561     }
00562     alloc_array(t1_line, 2, T1_BUF_SIZE); /* append_eol can append 2 chars */
00563     append_eol(t1_line_ptr, t1_line_array, t1_line_limit);
00564     if (t1_line_ptr - t1_line_array < 2)
00565         goto restart;
00566     if (eexec_scan == eexec_len)
00567         t1_in_eexec = 1;
00568 exit:
00569     /* ensure that t1_buf_array has as much room as t1_line_array */
00570     t1_buf_ptr = t1_buf_array;
00571     alloc_array(t1_buf, t1_line_limit, t1_line_limit);
00572 }
00573 
00574 static void t1_putline(void) 
00575 {
00576     char *p = t1_line_array;
00577     if (t1_line_ptr - t1_line_array <= 1)
00578         return;
00579     if (t1_eexec_encrypt)  {
00580         while (p < t1_line_ptr)
00581             out_eexec_char(eencrypt(*p++));
00582     }
00583     else 
00584         while (p < t1_line_ptr)
00585             t1_putchar(*p++);
00586 }
00587 
00588 static void t1_puts(const char *s)
00589 {
00590     if (s != t1_line_array)
00591         strcpy(t1_line_array, s);
00592     t1_line_ptr = strend(t1_line_array);
00593     t1_putline();
00594 }
00595 
00596 static void t1_printf(const char *fmt,...)
00597 {
00598     va_list args;
00599     va_start(args, fmt);
00600     vsprintf(t1_line_array, fmt, args);
00601     t1_puts(t1_line_array);                                    
00602     va_end(args);
00603 }
00604 
00605 static void t1_init_params(const char *open_name_prefix) 
00606 {
00607     t1_log(open_name_prefix);
00608     t1_log(cur_file_name);
00609     t1_lenIV = 4;
00610     t1_dr = 55665;
00611     t1_er = 55665;
00612     t1_in_eexec = 0;
00613     t1_cs = false;
00614     t1_scan = true;
00615     t1_synthetic = false;
00616     t1_eexec_encrypt = false;
00617     t1_block_length = 0;
00618     t1_check_pfa();
00619 }
00620 
00621 static void t1_close_font_file(const char *close_name_suffix)
00622 {
00623     t1_log(close_name_suffix);
00624     t1_close();
00625     cur_file_name = NULL;
00626 }
00627 
00628 static void t1_check_block_len(boolean decrypt)
00629 {
00630     int l, c;
00631     if (t1_block_length == 0)
00632        return;
00633     c = t1_getbyte();
00634     if (decrypt) 
00635         c = edecrypt(c);
00636     l = t1_block_length;
00637     if (!(l == 0 && (c == 10 || c == 13))) {
00638         pdftex_warn("%i bytes more than expected were ignored", l + 1);
00639         while (l-- > 0)
00640             t1_getbyte();
00641     }
00642 }
00643 
00644 static void t1_start_eexec(void)
00645 {
00646     int i;
00647     if (is_included(fm_cur)) {
00648         get_length1();
00649         save_offset();
00650     }
00651     if (!t1_pfa)
00652         t1_check_block_len(false);
00653     for (t1_line_ptr = t1_line_array, i = 0; i < 4; i++) {
00654         edecrypt(t1_getbyte());
00655         *t1_line_ptr++ = 0;
00656     }
00657     t1_eexec_encrypt = true;
00658     if (is_included(fm_cur))
00659         t1_putline(); /* to put the first four bytes */
00660 }
00661 
00662 static void t1_stop_eexec(void)
00663 {
00664     int c;
00665     if (is_included(fm_cur)) {
00666         get_length2();
00667         save_offset();
00668     }
00669     end_last_eexec_line();
00670     if (!t1_pfa)
00671         t1_check_block_len(true);
00672     else {
00673         c = edecrypt(t1_getbyte());
00674         if (!(c == 10 || c == 13)) {
00675             if (last_hexbyte == 0)
00676                 t1_puts("00");
00677             else
00678                 pdftex_warn("unexpected data after eexec");
00679         }
00680     }
00681     t1_cs = false;
00682     t1_in_eexec = 2;
00683 }
00684 
00685 #ifdef pdfTeX
00686 static void t1_modify_fm(void)
00687 {
00688  /*
00689   * font matrix is given as six numbers a0..a5, which stands for the matrix
00690   * 
00691   *           a0 a1 0
00692   *     M =   a2 a3 0
00693   *           a4 a5 1
00694   * 
00695   * ExtendFont is given as
00696   * 
00697   *           e 0 0
00698   *     E =   0 1 0
00699   *           0 0 1
00700   * 
00701   * SlantFont is given as
00702   * 
00703   *           1 0 0
00704   *     S =   s 1 0
00705   *           0 0 1
00706   * 
00707   * and the final transformation is
00708   * 
00709   *                    e*a0        e*a1       0
00710   *     F =  E.S.M  =  s*e*a0+a2   s*e*a1+a3  0
00711   *                    a4          a5         1
00712   */
00713     float e, s, a[6], b[6];
00714     int i, c;
00715     char *p, *q, *r;
00716     if ((p = strchr(t1_line_array, '[')) == 0)
00717         if ((p = strchr(t1_line_array, '{')) == 0) {
00718             remove_eol(p, t1_line_array);
00719             pdftex_fail("FontMatrix: an array expected: `%s'", t1_line_array);
00720         }
00721     c = *p++; /* save the character '[' resp. '{' */
00722     strncpy(t1_buf_array, t1_line_array, (unsigned)(p - t1_line_array));
00723     r = t1_buf_array + (p - t1_line_array);
00724     for (i = 0; i < 6; i++) {
00725         a[i] = t1_scan_num(p, &q);
00726         p = q;
00727     }
00728     if (fm_extend(fm_cur) != 0)
00729         e = fm_extend(fm_cur)*1E-3;
00730     else
00731         e = 1;
00732     s = fm_slant(fm_cur)*1E-3;
00733     b[0] = e*a[0];
00734     b[1] = e*a[1];
00735     b[2] = s*e*a[0] + a[2];
00736     b[3] = s*e*a[1] + a[3];
00737     b[4] = a[4];
00738     b[5] = a[5];
00739     for (i = 0; i < 6; i++) {
00740         sprintf(r, "%g ", b[i]);
00741         r = strend(r);
00742     }
00743     if (c == '[') {
00744         while (*p != ']' && *p != 0)
00745             p++;
00746     }
00747     else {
00748         while (*p != '}' && *p != 0)
00749             p++;
00750     }
00751     if (*p == 0) {
00752         remove_eol(p, t1_line_array);
00753         pdftex_fail("FontMatrix: cannot find the corresponding character to '%c': `%s'",  c, t1_line_array);
00754     }
00755     strcpy(r, p);
00756     strcpy(t1_line_array, t1_buf_array);
00757     t1_line_ptr = eol(t1_line_array);
00758 }
00759 
00760 static void t1_modify_italic(void)
00761 {
00762     float a;
00763     char *p, *r;
00764     if (fm_slant(fm_cur) == 0)
00765         return;
00766     p = strchr(t1_line_array, ' ');
00767     strncpy(t1_buf_array, t1_line_array, (unsigned)(p - t1_line_array + 1));
00768     a = t1_scan_num(p + 1, &r);
00769     a -= atan(fm_slant(fm_cur)*1E-3)*(180/M_PI);
00770     sprintf(t1_buf_array + (p - t1_line_array + 1), "%g", a);
00771     strcpy(strend(t1_buf_array), r);
00772     strcpy(t1_line_array, t1_buf_array);
00773     t1_line_ptr = eol(t1_line_array);
00774     font_keys[ITALIC_ANGLE_CODE].value = round(a);
00775     font_keys[ITALIC_ANGLE_CODE].valid = true;
00776 }
00777 
00778 static void t1_scan_keys(void)
00779 {
00780     int i, k;
00781     char *p, *q, *r;
00782     key_entry *key;
00783     if (fm_extend(fm_cur) != 0 || fm_slant(fm_cur) != 0) {
00784         if (t1_prefix("/FontMatrix")) {
00785             t1_modify_fm();
00786             return;
00787         }
00788         if (t1_prefix("/ItalicAngle")) {
00789             t1_modify_italic();
00790             return;
00791         }
00792     }
00793     if (t1_prefix("/FontType")) {
00794         p = t1_line_array + strlen("FontType") + 1;
00795         if ((i = t1_scan_num(p, 0)) != 1)
00796             pdftex_fail("Type%d fonts unsupported by pdfTeX", i);
00797         return;
00798     }
00799     for (key = font_keys; key - font_keys  < MAX_KEY_CODE; key++)
00800         if (strncmp(t1_line_array + 1, key->t1name, strlen(key->t1name)) == 0)
00801           break;
00802     if (key - font_keys == MAX_KEY_CODE)
00803         return;
00804     key->valid = true;
00805     p = t1_line_array + strlen(key->t1name) + 1;
00806     skip(p, ' ');
00807     if ((k = key - font_keys) == FONTNAME_CODE) {
00808         if (*p != '/') {
00809             remove_eol(p, t1_line_array);
00810             pdftex_fail("a name expected: `%s'", t1_line_array);
00811         }
00812         r = ++p; /* skip the slash */
00813         for (q = t1_buf_array; *p != ' ' && *p != 10; *q++ = *p++);
00814         *q = 0;
00815         if (fm_slant(fm_cur) != 0) {
00816             sprintf(q, "-Slant_%i", (int)fm_slant(fm_cur));
00817             q = strend(q);
00818         }
00819         if (fm_extend(fm_cur) != 0) {
00820             sprintf(q, "-Extend_%i", (int)fm_extend(fm_cur));
00821         }
00822         strncpy(fontname_buf, t1_buf_array, FONTNAME_BUF_SIZE);
00823         /* at this moment we cannot call make_subset_tag() yet, as the encoding 
00824          * is not read; thus we mark the offset of the subset tag and write it
00825          * later */
00826         if (is_included(fm_cur) && is_subsetted(fm_cur)) {
00827             t1_fontname_offset = fb_offset() + (r - t1_line_array);
00828             strcpy(t1_buf_array, p);
00829             sprintf(r, "ABCDEF+%s%s", fontname_buf, t1_buf_array);
00830             t1_line_ptr = eol(r);
00831         }
00832         return;
00833     }
00834     if ((k == STEMV_CODE ||  k == FONTBBOX1_CODE) &&
00835         (*p == '[' || *p == '{'))
00836         p++;
00837     if (k == FONTBBOX1_CODE) {
00838         for (i = 0; i < 4; i++) {
00839             key[i].value = t1_scan_num(p, &r);
00840             p = r;
00841         }
00842         return;
00843     }
00844     key->value = t1_scan_num(p, 0);
00845 }
00846 
00847 #endif /* pdfTeX */
00848 
00849 static void t1_scan_param(void) 
00850 {
00851     static const char *lenIV = "/lenIV";
00852     if (!t1_scan || *t1_line_array != '/')
00853         return;
00854     if (t1_prefix(lenIV)) {
00855         t1_lenIV = t1_scan_num(t1_line_array + strlen(lenIV), 0);
00856         return;
00857     }
00858     t1_scan_keys();
00859 }
00860 
00861 static void copy_glyph_names(char **glyph_names, int a, int b)
00862 {
00863     if (glyph_names[b] != notdef) {
00864         free(glyph_names[b]);
00865         glyph_names[b] = (char*) notdef;
00866     }
00867     if (glyph_names[a] != notdef) {
00868         glyph_names[b] = xstrdup(glyph_names[a]);
00869     }
00870 }
00871 
00872 static void t1_builtin_enc(void)
00873 {
00874     int i, a, b, c, counter = 0;
00875     char *r, *p;
00876    /*
00877     * At this moment "/Encoding" is the prefix of t1_line_array
00878     */
00879     if (t1_suffix("def")) { /* predefined encoding */
00880         sscanf(t1_line_array + strlen("/Encoding"), "%256s", t1_buf_array);
00881         if (strcmp(t1_buf_array, "StandardEncoding") == 0) {
00882             for (i = 0; i <= MAX_CHAR_CODE; i++)
00883                 if (standard_glyph_names[i] == notdef)
00884                     t1_builtin_glyph_names[i] = (char*) notdef;
00885                 else
00886                     t1_builtin_glyph_names[i] = xstrdup(standard_glyph_names[i]);
00887             t1_encoding = ENC_STANDARD;
00888         }
00889         else 
00890             pdftex_fail("cannot subset font (unknown predefined encoding `%s')", 
00891                         t1_buf_array);
00892         return;
00893     } else
00894         t1_encoding = ENC_BUILTIN;
00895    /*
00896     * At this moment "/Encoding" is the prefix of t1_line_array, and the encoding is
00897     * not a predefined encoding
00898     * 
00899     * We have two possible forms of Encoding vector. The first case is
00900     * 
00901     *     /Encoding [/a /b /c...] readonly def
00902     * 
00903     * and the second case can look like
00904     * 
00905     *     /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
00906     *     dup 0 /x put
00907     *     dup 1 /y put
00908     *     ...
00909     *     readonly def
00910     */
00911     for (i = 0; i <= MAX_CHAR_CODE; i++)
00912         t1_builtin_glyph_names[i] = (char*) notdef;
00913     if (t1_prefix("/Encoding [") || t1_prefix("/Encoding[")) { /* the first case */
00914         r = strchr(t1_line_array, '[') + 1;
00915         skip(r, ' ');
00916         for(;;) {
00917             while (*r == '/') {
00918                 for (p = t1_buf_array, r++;
00919                      *r != 32 && *r != 10 && *r != ']' && *r != '/';
00920                      *p++ = *r++);
00921                 *p = 0;
00922                 skip(r, ' ');
00923                 if (counter > MAX_CHAR_CODE)
00924                     pdftex_fail("encoding vector contains more than %i names",
00925                             (int)(MAX_CHAR_CODE + 1));
00926                 if (strcmp(t1_buf_array, notdef) != 0)
00927                     t1_builtin_glyph_names[counter] = xstrdup(t1_buf_array);
00928                 counter++;
00929             }
00930             if (*r != 10 && *r != '%') {
00931                 if (str_prefix(r, "] def") || str_prefix(r, "] readonly def"))
00932                     break;
00933                 else {
00934                     remove_eol(r, t1_line_array);
00935                     pdftex_fail("a name or `] def' or `] readonly def' expected: `%s'",
00936                                 t1_line_array);
00937                 }
00938             }
00939             t1_getline();
00940             r = t1_line_array;
00941         }
00942     }
00943     else { /* the second case */
00944         p = strchr(t1_line_array, 10); 
00945         for (;;) {
00946             if (*p == 10) {
00947                 t1_getline();
00948                 p = t1_line_array;
00949             }
00950             /*
00951              check for `dup <index> <glyph> put'
00952              */
00953             if (sscanf(p, "dup %i%256s put", &i, t1_buf_array) == 2 && 
00954                 *t1_buf_array == '/' && valid_code(i)) {
00955                 if (strcmp(t1_buf_array + 1, notdef) != 0)
00956                     t1_builtin_glyph_names[i] = xstrdup(t1_buf_array + 1);
00957                 p = strstr(p, " put") + strlen(" put");
00958                 skip(p, ' ');
00959             }
00960             /*
00961              check for `dup dup <to> exch <from> get put'
00962              */
00963             else if (sscanf(p, "dup dup %i exch %i get put", &b, &a) == 2 &&
00964                      valid_code(a) && valid_code(b)) {
00965                 copy_glyph_names(t1_builtin_glyph_names, a, b);
00966                 p = strstr(p, " get put") + strlen(" get put");
00967                 skip(p, ' ');
00968             }
00969             /*
00970              check for `dup dup <from> <size> getinterval <to> exch putinterval'
00971              */
00972             else if (sscanf(p, "dup dup %i %i getinterval %i exch putinterval", 
00973                             &a, &c, &b) == 3 && 
00974                      valid_code(a) && valid_code(b) && valid_code(c)) {
00975                 for (i = 0; i < c; i++)
00976                     copy_glyph_names(t1_builtin_glyph_names, a + i, b + i);
00977                 p = strstr(p, " putinterval") + strlen(" putinterval");
00978                 skip(p, ' ');
00979             }
00980             /*
00981              check for `def' or `readonly def'
00982              */
00983             else if ((p == t1_line_array || (p > t1_line_array && p[-1] == ' ')) &&
00984                      strcmp(p, "def\n") == 0)
00985                 return;
00986             /* 
00987              skip an unrecognizable word 
00988              */
00989             else {
00990                 while (*p != ' ' && *p != 10)
00991                     p++;    
00992                 skip(p, ' ');
00993             }
00994         }
00995     }
00996 }
00997 
00998 static void t1_check_end(void)
00999 {
01000     if (t1_eof())
01001         return;
01002     t1_getline();
01003     if (t1_prefix("{restore}"))
01004         t1_putline();
01005 }
01006 
01007 #ifdef pdfTeX
01008 static boolean t1_open_fontfile(const char *open_name_prefix)
01009 {
01010     char *ex_ffname = NULL;
01011     ff_entry *ff;
01012     ff = check_ff_exist(fm_cur);
01013     if (ff->ff_path != NULL)
01014         t1_file = xfopen(cur_file_name = ff->ff_path, FOPEN_RBIN_MODE);
01015     else {
01016         set_cur_file_name(fm_cur->ff_name);
01017         pdftex_warn("cannot open Type 1 font file for reading");
01018         return false;
01019     }
01020     t1_init_params(open_name_prefix);
01021     fontfile_found = true;
01022     return true;
01023 }
01024 
01025 boolean t1_read_enc(fm_entry *fm)
01026 {
01027     read_encoding_only = true;
01028     fm_cur = fm;
01029     if (!t1_open_fontfile("{"))
01030         return false;
01031     while (!t1_prefix("/Encoding"))
01032         t1_getline();
01033     t1_builtin_enc(); 
01034     t1_close_font_file("}");
01035     return true;
01036 }
01037 
01038 static void t1_scan_only(void)
01039 {
01040     do {
01041         t1_getline();
01042         t1_scan_param(); 
01043     } while (t1_in_eexec == 0);
01044     t1_start_eexec();
01045     do {
01046         t1_getline();
01047         t1_scan_param();
01048     } while (!(t1_charstrings() || t1_subrs()));
01049 }
01050 
01051 static void t1_include(void)
01052 {
01053     save_offset();
01054     do {
01055         t1_getline();
01056         t1_scan_param();
01057         t1_putline();
01058     } while (t1_in_eexec == 0);
01059     t1_start_eexec();
01060     do {
01061         t1_getline();
01062         t1_scan_param();
01063         t1_putline();
01064     } while (!(t1_charstrings() || t1_subrs()));
01065     t1_cs = true;
01066     do {
01067         t1_getline();
01068         t1_putline();
01069     } while (!t1_end_eexec());
01070     t1_stop_eexec();
01071     do {
01072         t1_getline();
01073         t1_putline();
01074     } while (!t1_cleartomark());
01075     t1_check_end(); /* write "{restore}if" if found */
01076     get_length3();
01077 }
01078 
01079 #else /* not pdfTeX */
01080 static boolean t1_open_fontfile(char *open_name_prefix)
01081 {
01082     if (!t1_open())
01083         return false;
01084     t1_init_params(open_name_prefix);
01085     return true;
01086 }
01087 #endif /* pdfTeX */
01088 
01089 #define check_subr(subr) \
01090     if (subr >= subr_size || subr < 0) \
01091         pdftex_fail("Subrs array: entry index out of range (%i)",  subr);
01092 
01093 static const char **check_cs_token_pair()
01094 {
01095     const char **p = (const char**) cs_token_pairs_list;
01096     for (; p[0] != NULL; ++p) 
01097         if (t1_buf_prefix(p[0]) && t1_buf_suffix(p[1]))
01098             return p;
01099     return NULL;
01100 }
01101 
01102 static void cs_store(boolean is_subr)
01103 {
01104     char *p;
01105     cs_entry *ptr;
01106     int subr;
01107     for (p = t1_line_array, t1_buf_ptr = t1_buf_array; *p != ' '; *t1_buf_ptr++ = *p++);
01108     *t1_buf_ptr = 0;
01109     if (is_subr) {
01110         subr = t1_scan_num(p + 1, 0);
01111         check_subr(subr);
01112         ptr = subr_tab + subr;
01113     }
01114     else {
01115         ptr = cs_ptr++;
01116         if (cs_ptr - cs_tab > cs_size)
01117             pdftex_fail("CharStrings dict: more entries than dict size (%i)", cs_size);
01118         if (strcmp(t1_buf_array + 1, notdef) == 0) /* skip the slash */
01119             ptr->name = (char*) notdef;
01120         else
01121             ptr->name = xstrdup(t1_buf_array + 1); 
01122     }
01123     /* copy " RD " + cs data to t1_buf_array */
01124     memcpy(t1_buf_array, t1_line_array + cs_start - 4, (unsigned)(t1_cslen + 4));
01125     /* copy the end of cs data to t1_buf_array */
01126     for (p = t1_line_array + cs_start + t1_cslen, t1_buf_ptr = t1_buf_array + t1_cslen + 4; 
01127          *p != 10; *t1_buf_ptr++ = *p++);
01128     *t1_buf_ptr++ = 10;
01129     if (is_subr && cs_token_pair == NULL)
01130         cs_token_pair = check_cs_token_pair();
01131     ptr->len = t1_buf_ptr - t1_buf_array;
01132     ptr->cslen = t1_cslen;
01133     ptr->data = xtalloc(ptr->len, byte);
01134     memcpy(ptr->data, t1_buf_array, ptr->len);
01135     ptr->valid = true;
01136 }
01137 
01138 #define store_subr()    cs_store(true)
01139 #define store_cs()      cs_store(false)
01140 
01141 #define CC_STACK_SIZE       24
01142 
01143 static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
01144 static cc_entry cc_tab[CS_MAX];
01145 static boolean is_cc_init = false;
01146 
01147 
01148 #define cc_pop(N)                       \
01149     if (stack_ptr - cc_stack < (N))     \
01150         stack_error(N);                 \
01151     stack_ptr -= N
01152 
01153 #define stack_error(N) {                \
01154     pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \
01155                  N, stack_ptr - cc_stack);                               \
01156     goto cs_error;                    \
01157 }
01158 
01159 /*
01160 static integer cc_get(integer index) 
01161 {
01162     if (index <  0) {
01163         if (stack_ptr + index < cc_stack )
01164             stack_error(stack_ptr - cc_stack + index);
01165         return *(stack_ptr + index);
01166     }
01167     else {
01168         if (cc_stack  + index >= stack_ptr)
01169             stack_error(index);
01170         return cc_stack[index];
01171     }
01172 }
01173 */
01174 
01175 #define cc_get(N)   ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
01176 
01177 #define cc_push(V)  *stack_ptr++ = V
01178 #define cc_clear()  stack_ptr = cc_stack
01179     
01180 #define set_cc(N, B, A, C) \
01181     cc_tab[N].nargs = A;   \
01182     cc_tab[N].bottom = B;  \
01183     cc_tab[N].clear = C;   \
01184     cc_tab[N].valid = true
01185     
01186 static void cc_init(void)
01187 {
01188     int i;
01189     if (is_cc_init)
01190         return;
01191     for (i = 0; i < CS_MAX; i++)
01192         cc_tab[i].valid = false;
01193     set_cc(CS_HSTEM,           true,   2, true);
01194     set_cc(CS_VSTEM,           true,   2, true);
01195     set_cc(CS_VMOVETO,         true,   1, true);
01196     set_cc(CS_RLINETO,         true,   2, true);
01197     set_cc(CS_HLINETO,         true,   1, true);
01198     set_cc(CS_VLINETO,         true,   1, true);
01199     set_cc(CS_RRCURVETO,       true,   6, true);
01200     set_cc(CS_CLOSEPATH,       false,  0, true);
01201     set_cc(CS_CALLSUBR,        false,  1, false);
01202     set_cc(CS_RETURN,          false,  0, false);
01203     /*
01204     set_cc(CS_ESCAPE,          false,  0, false);
01205     */
01206     set_cc(CS_HSBW,            true,   2, true);
01207     set_cc(CS_ENDCHAR,         false,  0, true);
01208     set_cc(CS_RMOVETO,         true,   2, true);
01209     set_cc(CS_HMOVETO,         true,   1, true);
01210     set_cc(CS_VHCURVETO,       true,   4, true);
01211     set_cc(CS_HVCURVETO,       true,   4, true);
01212     set_cc(CS_DOTSECTION,      false,  0, true);
01213     set_cc(CS_VSTEM3,          true,   6, true);
01214     set_cc(CS_HSTEM3,          true,   6, true);
01215     set_cc(CS_SEAC,            true,   5, true);
01216     set_cc(CS_SBW,             true,   4, true);
01217     set_cc(CS_DIV,             false,  2, false);
01218     set_cc(CS_CALLOTHERSUBR,   false,  0, false);
01219     set_cc(CS_POP,             false,  0, false);
01220     set_cc(CS_SETCURRENTPOINT, true,   2, true);
01221     is_cc_init = true;
01222 }
01223 
01224 #define cs_getchar()    cdecrypt(*data++, &cr)
01225 
01226 #define mark_subr(n)    cs_mark(0, n)
01227 #define mark_cs(s)      cs_mark(s, 0)
01228 
01229 static void cs_warn(const char *cs_name, int subr, const char *fmt,...)
01230 {
01231     char buf[SMALL_BUF_SIZE];
01232     va_list args;
01233     va_start(args, fmt);
01234     vsprintf(buf, fmt, args);
01235     va_end(args);
01236     if (cs_name == NULL)
01237         pdftex_warn("Subr (%i): %s", (int)subr, buf);
01238     else
01239         pdftex_warn("CharString (/%s): %s", cs_name, buf);
01240 }
01241 
01242 static void cs_mark(const char *cs_name, int subr)
01243 {
01244     byte *data;
01245     int i, b, cs_len;
01246     integer a, a1, a2;
01247     unsigned short cr;
01248     static integer lastargOtherSubr3 = 3; /* the argument of last call to 
01249                                              OtherSubrs[3] */
01250     cs_entry *ptr;
01251     cc_entry *cc;
01252     if (cs_name == NULL) {
01253         check_subr(subr);
01254         ptr = subr_tab + subr;
01255         if (!ptr->valid)
01256             return;
01257     }
01258     else {
01259         if (cs_notdef != NULL && 
01260             (cs_name == notdef || strcmp(cs_name, notdef) == 0))
01261             ptr = cs_notdef;
01262         else {
01263             for (ptr = cs_tab; ptr < cs_ptr; ptr++)
01264                 if (strcmp(ptr->name, cs_name) == 0)
01265                     break;
01266             if (ptr == cs_ptr) {
01267                 pdftex_warn("glyph `%s' undefined", cs_name);
01268                 return;
01269             }
01270             if (ptr->name == notdef)
01271                 cs_notdef = ptr;
01272         }
01273     }
01274     /* only marked CharString entries and invalid entries can be skipped;
01275        valid marked subrs must be parsed to keep the stack in sync */
01276     if (!ptr->valid || (ptr->used && cs_name != NULL))
01277         return; 
01278     ptr->used = true;
01279     cr = 4330; 
01280     cs_len = ptr->cslen;
01281     data = ptr->data + 4;
01282     for (i = 0; i < t1_lenIV; i++, cs_len--)
01283         cs_getchar();
01284     while (cs_len > 0) {
01285         --cs_len;
01286         b = cs_getchar();
01287         if (b >= 32) {
01288             if (b <= 246)
01289                 a = b - 139;
01290             else if (b <= 250) {
01291                 --cs_len;
01292                 a = ((b - 247) << 8) + 108 + cs_getchar();
01293             } 
01294             else if (b <= 254) {
01295                 --cs_len;
01296                 a = -((b - 251) << 8) - 108 - cs_getchar();
01297             } 
01298             else {
01299                 cs_len -= 4;
01300                 a =  (cs_getchar() & 0xff) << 24;
01301                 a |= (cs_getchar() & 0xff) << 16;
01302                 a |= (cs_getchar() & 0xff) <<  8;
01303                 a |= (cs_getchar() & 0xff) <<  0;
01304                 if (sizeof(integer) > 4 && (a & 0x80000000))
01305                     a |= ~0x7FFFFFFF;
01306             }
01307             cc_push(a);
01308         }
01309         else {
01310             if (b == CS_ESCAPE) {
01311                 b = cs_getchar() + CS_1BYTE_MAX;
01312                 cs_len--;
01313             }
01314             if (b >= CS_MAX) {
01315                 cs_warn(cs_name, subr, "command value out of range: %i", (int)b);
01316                 goto cs_error;
01317             }
01318             cc = cc_tab + b;
01319             if (!cc->valid) {
01320                 cs_warn(cs_name, subr, "command not valid: %i", (int)b);
01321                 goto cs_error;
01322             }
01323             if (cc->bottom) {
01324                 if (stack_ptr - cc_stack < cc->nargs)
01325                     cs_warn(cs_name, subr, 
01326                             "less arguments on stack (%i) than required (%i)",
01327                             (int)(stack_ptr - cc_stack), (int)cc->nargs);
01328                 else if (stack_ptr - cc_stack > cc->nargs)
01329                     cs_warn(cs_name, subr, 
01330                             "more arguments on stack (%i) than required (%i)",
01331                             (int)(stack_ptr - cc_stack), (int)cc->nargs);
01332             }
01333             switch (cc - cc_tab) {
01334             case CS_CALLSUBR:
01335                 a1 = cc_get(-1);
01336                 cc_pop(1);
01337                 mark_subr(a1);
01338                 if (!subr_tab[a1].valid) {
01339                     cs_warn(cs_name, subr, 
01340                             "cannot call subr (%i)", (int)a1);
01341                     goto cs_error;
01342                 }
01343                 break;
01344             case CS_DIV:
01345                 cc_pop(2);
01346                 cc_push(0);
01347                 break;
01348             case CS_CALLOTHERSUBR:
01349                 if (cc_get(-1) == 3)
01350                     lastargOtherSubr3 = cc_get(-3);
01351                 a1 = cc_get(-2) + 2;
01352                 cc_pop(a1);
01353                 break;
01354             case CS_POP:
01355                 cc_push(lastargOtherSubr3);
01356                 /* the only case when we care about the value being pushed onto
01357                    stack is when POP follows CALLOTHERSUBR (changing hints by
01358                    OtherSubrs[3]) 
01359                  */
01360                 break;
01361             case CS_SEAC:
01362                 a1 = cc_get(3);
01363                 a2 = cc_get(4);
01364                 cc_clear();
01365                 mark_cs(standard_glyph_names[a1]);
01366                 mark_cs(standard_glyph_names[a2]);
01367                 break;
01368             default:
01369                 if (cc->clear)
01370                     cc_clear();
01371             }
01372         }
01373     }
01374     return;
01375 cs_error: /* an error occured during parsing */
01376     cc_clear();
01377     ptr->valid = false;
01378     ptr->used = false;
01379 }
01380 
01381 static void t1_subset_ascii_part(void)
01382 {
01383     int i, j;
01384     save_offset();
01385     t1_getline();
01386     while (!t1_prefix("/Encoding")) {
01387         t1_scan_param();
01388         t1_putline();
01389         t1_getline();
01390     }
01391     t1_builtin_enc(); 
01392     if (is_reencoded(fm_cur))
01393         t1_glyph_names = external_enc();
01394     else {
01395         t1_glyph_names = t1_builtin_glyph_names;
01396         update_builtin_enc(tex_font, t1_glyph_names); 
01397     }
01398     if (is_included(fm_cur) && is_subsetted(fm_cur)) {
01399         make_subset_tag(fm_cur, t1_glyph_names);
01400         update_subset_tag();
01401     }
01402     if (pdfmovechars == 0 && t1_encoding == ENC_STANDARD)
01403         t1_puts("/Encoding StandardEncoding def\n");
01404     else {
01405         t1_puts("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
01406         for (i = 0, j = 0; i <= MAX_CHAR_CODE; i++) {
01407             if (is_used_char(i) && t1_glyph_names[i] != notdef) {
01408                 j++;
01409                 t1_printf("dup %i /%s put\n", (int)t1_char(i), t1_glyph_names[i]);
01410             }
01411         }
01412         /* We didn't mark anything for the Encoding array. */
01413         /* We add "dup 0 /.notdef put" for compatibility   */
01414         /* with Acrobat 5.0.                               */
01415         if (j == 0)
01416             t1_puts("dup 0 /.notdef put\n");
01417         t1_puts("readonly def\n");
01418     }
01419     do {
01420         t1_getline();
01421         t1_scan_param();
01422         if (!t1_prefix("/UniqueID")) /* ignore UniqueID for subsetted fonts */
01423             t1_putline();
01424     } while (t1_in_eexec == 0);
01425 }
01426 
01427 #define t1_subr_flush()  t1_flush_cs(true)
01428 #define t1_cs_flush()    t1_flush_cs(false)
01429 
01430 static void t1_flush_cs(boolean);
01431 
01432 static void cs_init(void)
01433 {
01434     cs_ptr = cs_tab = NULL;
01435     cs_dict_start =  cs_dict_end = NULL;
01436     cs_count = cs_size = cs_size_pos = 0;
01437     cs_token_pair = NULL;
01438     subr_tab = NULL;
01439     subr_array_start = subr_array_end = NULL;
01440     subr_max = subr_size = subr_size_pos = 0;
01441 }
01442 
01443 static void init_cs_entry(cs_entry *cs)
01444 {
01445     cs->data = NULL;
01446     cs->name = NULL;
01447     cs->len = 0;
01448     cs->cslen = 0;
01449     cs->used = false;
01450     cs->valid = false;
01451 }
01452 
01453 static void t1_mark_glyphs(void);
01454 
01455 static void t1_read_subrs(void)
01456 {
01457     int i, s;
01458     cs_entry *ptr;
01459     t1_getline();
01460     while (!(t1_charstrings() || t1_subrs())) {
01461         t1_scan_param(); 
01462         t1_putline();
01463         t1_getline();
01464     }
01465 found:
01466     t1_cs = true;
01467     t1_scan = false;
01468     if (!t1_subrs())
01469        return;
01470     subr_size_pos = strlen("/Subrs") + 1; 
01471     /* subr_size_pos points to the number indicating dict size after "/Subrs" */
01472     subr_size = t1_scan_num(t1_line_array + subr_size_pos, 0);
01473     if (subr_size == 0) {
01474         while (!t1_charstrings())
01475             t1_getline();
01476         return;
01477     }
01478     subr_tab = xtalloc(subr_size, cs_entry);
01479     for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
01480         init_cs_entry(ptr);
01481     subr_array_start = xstrdup(t1_line_array);
01482     t1_getline();
01483     while (t1_cslen) {
01484         store_subr();
01485         t1_getline();
01486     }
01487     /* mark the first four entries without parsing */
01488     for (i = 0; i < subr_size && i < 4; i++)
01489         subr_tab[i].used = true;
01490     /* the end of the Subrs array might have more than one line so we need to
01491        concatnate them to subr_array_end. Unfortunately some fonts don't have
01492        the Subrs array followed by the CharStrings dict immediately (synthetic
01493        fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then
01494        we will treat the font as synthetic and ignore everything until next
01495        Subrs is found
01496      */
01497 #define POST_SUBRS_SCAN     5
01498     s = 0;
01499     *t1_buf_array = 0;
01500     for (i = 0; i < POST_SUBRS_SCAN; i++) {
01501         if (t1_charstrings())
01502                break;
01503         s += t1_line_ptr - t1_line_array;
01504         alloc_array(t1_buf, s, T1_BUF_SIZE);
01505         strcat(t1_buf_array, t1_line_array);
01506         t1_getline();
01507     }
01508     subr_array_end = xstrdup(t1_buf_array);
01509     if (i == POST_SUBRS_SCAN) { /* CharStrings not found; 
01510                                    suppose synthetic font */
01511         for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
01512             if (ptr->valid)
01513                 xfree(ptr->data);
01514         xfree(subr_tab);
01515         xfree(subr_array_start);
01516         xfree(subr_array_end);
01517         cs_init();
01518         t1_cs = false;
01519         t1_synthetic = true;
01520         while (!(t1_charstrings() || t1_subrs()))
01521             t1_getline();
01522         goto found;
01523     }
01524 }
01525 
01526 static void t1_flush_cs(boolean is_subr)
01527 {
01528     char *p;
01529     byte *r, *return_cs = NULL;
01530     cs_entry *tab, *end_tab, *ptr;
01531     char *start_line, *line_end;
01532     int count, size_pos;
01533     unsigned short cr, cs_len;
01534     if (is_subr) {
01535         start_line = subr_array_start;
01536         line_end = subr_array_end;
01537         size_pos = subr_size_pos;
01538         tab = subr_tab;
01539         count = subr_max + 1;
01540         end_tab = subr_tab + count;
01541     }
01542     else {
01543         start_line = cs_dict_start;
01544         line_end = cs_dict_end;
01545         size_pos = cs_size_pos;
01546         tab =  cs_tab;
01547         end_tab = cs_ptr;
01548         count = cs_count;
01549     }
01550     t1_line_ptr = t1_line_array;
01551     for (p = start_line; p - start_line < size_pos;)
01552         *t1_line_ptr++ = *p++;
01553     while (isdigit(*p))
01554         p++;
01555     sprintf(t1_line_ptr, "%u", count);
01556     strcat(t1_line_ptr, p);
01557     t1_line_ptr = eol(t1_line_array);
01558     t1_putline();
01559 
01560     /* create return_cs to replace unsused subr's */
01561     if (is_subr) {
01562         cr = 4330;
01563         cs_len = 0;
01564         return_cs = xtalloc(t1_lenIV + 1, byte);
01565         if (t1_lenIV > 0) {
01566             for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++)
01567                 *r = cencrypt(0x00, &cr);
01568             *r = cencrypt(CS_RETURN, &cr);
01569         }
01570         else {
01571             *return_cs = CS_RETURN;
01572         }
01573         cs_len++;
01574     }
01575 
01576     for (ptr = tab; ptr < end_tab; ptr++) {
01577         if (ptr->used) {
01578             if (is_subr)
01579                 sprintf(t1_line_array, "dup %u %u", ptr - tab, ptr->cslen);
01580             else
01581                 sprintf(t1_line_array, "/%s %u", ptr->name, ptr->cslen);
01582             p = strend(t1_line_array);
01583             memcpy(p, ptr->data, ptr->len);
01584             t1_line_ptr = p + ptr->len;
01585             t1_putline();
01586         }
01587         else {
01588             /* replace unsused subr's by return_cs */
01589             if (is_subr) {
01590                 sprintf(t1_line_array, "dup %u %u%s ", ptr - tab, cs_len,
01591                         cs_token_pair[0]);
01592                 p = strend(t1_line_array);
01593                 memcpy(p, return_cs, cs_len);
01594                 t1_line_ptr = p + cs_len;
01595                 t1_putline();
01596                 sprintf(t1_line_array, " %s", cs_token_pair[1]);
01597                 t1_line_ptr = eol(t1_line_array);
01598                 t1_putline();
01599             }
01600         }
01601         xfree(ptr->data);
01602         if (ptr->name != notdef)
01603             xfree(ptr->name);
01604     }
01605     sprintf(t1_line_array, "%s", line_end);
01606     t1_line_ptr = eol(t1_line_array);
01607     t1_putline();
01608     if (is_subr)
01609         xfree(return_cs);
01610     xfree(tab);
01611     xfree(start_line);
01612     xfree(line_end);
01613 }
01614 
01615 static void t1_mark_glyphs(void)
01616 {
01617     int i;
01618     char *charset = extra_charset();
01619     char *g, *s, *r;
01620     cs_entry *ptr;
01621     if (t1_synthetic || embed_all_glyphs(tex_font)) { /* mark everything */
01622         if (cs_tab != NULL)
01623             for (ptr = cs_tab; ptr < cs_ptr; ptr++)
01624                 if (ptr->valid)
01625                     ptr->used = true;
01626         if (subr_tab != NULL) {
01627             for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
01628                 if (ptr->valid)
01629                     ptr->used = true;
01630             subr_max = subr_size - 1;
01631         }
01632         return;
01633     }
01634     mark_cs(notdef);
01635     for (i = 0; i <= MAX_CHAR_CODE; i++)
01636         if (is_used_char(i)) {
01637             if (t1_glyph_names[i] == notdef)
01638                 pdftex_warn("character %i is mapped to %s", i, notdef);
01639             else
01640                 mark_cs(t1_glyph_names[i]);
01641         }
01642     if (charset == NULL)
01643         goto set_subr_max;
01644     g = s = charset + 1; /* skip the first '/' */
01645     r = strend(g);
01646     while (g < r) {
01647         while (*s != '/' && s < r)
01648             s++;
01649         *s = 0; /* terminate g by rewriting '/' to 0 */
01650         mark_cs(g);
01651         g = s + 1;
01652     }
01653 set_subr_max:
01654     if (subr_tab != NULL)
01655         for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
01656             if (ptr->used && ptr - subr_tab > subr_max)
01657                 subr_max = ptr - subr_tab;
01658 }
01659 
01660 static void t1_subset_charstrings(void)
01661 {
01662     cs_entry *ptr;
01663     cs_size_pos = strstr(t1_line_array, charstringname) + strlen(charstringname)
01664                   - t1_line_array + 1; 
01665     /* cs_size_pos points to the number indicating
01666        dict size after "/CharStrings" */
01667     cs_size = t1_scan_num(t1_line_array + cs_size_pos, 0);
01668     cs_ptr = cs_tab = xtalloc(cs_size, cs_entry);
01669     for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++)
01670         init_cs_entry(ptr);
01671     cs_notdef = NULL;
01672     cs_dict_start = xstrdup(t1_line_array);
01673     t1_getline();
01674     while (t1_cslen) {
01675         store_cs();
01676         t1_getline();
01677     }
01678     cs_dict_end = xstrdup(t1_line_array);
01679     t1_mark_glyphs();
01680     if (subr_tab != NULL) {
01681         if (cs_token_pair == NULL)
01682             pdftex_fail("This Type 1 font uses mismatched subroutine begin/end token pairs.");
01683         t1_subr_flush();
01684     }
01685     for (cs_count = 0, ptr = cs_tab; ptr < cs_ptr; ptr++)
01686         if (ptr->used)
01687             cs_count++;
01688     t1_cs_flush();
01689 }
01690 
01691 static void t1_subset_end(void)
01692 {
01693     if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
01694         while (!strstr(t1_line_array, "definefont")) {
01695             t1_getline();
01696             t1_putline();
01697         }
01698         while (!t1_end_eexec())
01699             t1_getline();   /* ignore the rest */
01700         t1_putline();       /* write "mark currentfile closefile" */
01701     }
01702     else while (!t1_end_eexec()) { /* copy to "mark currentfile closefile" */
01703         t1_getline();
01704         t1_putline();
01705     }
01706     t1_stop_eexec();
01707     while (!t1_cleartomark()) {
01708         t1_getline();
01709         t1_putline();
01710     }
01711     if (!t1_synthetic)  /* don't check "{restore}if" for synthetic fonts */
01712         t1_check_end(); /* write "{restore}if" if found */
01713     get_length3();
01714 }
01715 
01716 void writet1(void)
01717 {
01718     read_encoding_only = false;
01719 #ifdef pdfTeX
01720     if (strcasecmp(strend(fm_fontfile(fm_cur)) - 4, ".otf") == 0) {
01721         if (!is_included(fm_cur) || is_subsetted(fm_cur))
01722             pdftex_fail("OTF fonts must be included entirely");
01723         writeotf();
01724         is_otf_font = true;
01725         return;
01726     }
01727 #endif
01728     if (!is_included(fm_cur)) { /* scan parameters from font file */
01729         if (!t1_open_fontfile("{"))
01730             return;
01731         t1_scan_only();
01732         t1_close_font_file("}");
01733         return;
01734     }
01735     if (!is_subsetted(fm_cur)) { /* include entire font */
01736         if (!t1_open_fontfile("<<"))
01737             return;
01738         t1_include();
01739         t1_close_font_file(">>");
01740         return;
01741     } 
01742     /* partial downloading */
01743     if (!t1_open_fontfile("<"))
01744         return;
01745     t1_subset_ascii_part();
01746     t1_start_eexec();
01747     cc_init();
01748     cs_init();
01749     t1_read_subrs();
01750     t1_subset_charstrings();
01751     t1_subset_end();
01752     t1_close_font_file(">");
01753 }
01754 
01755 void t1_free()
01756 {
01757     xfree(t1_line_array);
01758     xfree(t1_buf_array);
01759 }
01760 
01761 #ifndef pdfTeX
01762 boolean t1_subset(char *fontfile, char *encfile, unsigned char *g)
01763 {
01764     int i;
01765     cur_enc_name = encfile;
01766     for (i = 0; i <= MAX_CHAR_CODE; i++)
01767         ext_glyph_names[i] = (char*) notdef;
01768     if (cur_enc_name != NULL)
01769         load_enc(cur_enc_name, ext_glyph_names);
01770     grid = g;
01771     cur_file_name = fontfile;
01772     hexline_length = 0;
01773     writet1();
01774     for (i = 0; i <= MAX_CHAR_CODE; i++)
01775         if (ext_glyph_names[i] != notdef)
01776             free(ext_glyph_names[i]);
01777     return 1 ; /* note:  there *is* no unsuccessful return */
01778 }
01779 
01780 boolean t1_subset_2(char *fontfile, unsigned char *g, char *extraGlyphs)
01781 {
01782     int i;
01783     for (i = 0; i <= MAX_CHAR_CODE; i++)
01784         ext_glyph_names[i] = (char*) notdef;
01785     grid = g;
01786     cur_file_name = fontfile;
01787     hexline_length = 0;
01788     dvips_extra_charset = extraGlyphs ;
01789     writet1();
01790     for (i = 0; i <= MAX_CHAR_CODE; i++)
01791         if (ext_glyph_names[i] != notdef)
01792             free(ext_glyph_names[i]);
01793     return 1 ; /* note:  there *is* no unsuccessful return */
01794 }
01795 #endif /* not pdfTeX */