/* Copyright (c) 2006 Taco Hoekwater This file is part of MetaPost. MetaPost is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. MetaPost is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with MetaPost; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id$ */ static const char perforce_id[] = "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#25 $"; # include "mplib.h" # define t1_open() \ open_input(&t1_file, kpse_type1_format, FOPEN_RBIN_MODE) # define enc_open() \ open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE) # define external_enc() (fm_cur->encoding)->glyph_names # define full_file_name() cur_file_name # define get_length1() # define get_length2() # define get_length3() # define is_used_char(c) mpcharmarked(tex_font, c) # define out_eexec_char t1_outhex # define save_offset() # define end_last_eexec_line() \ hexline_length = HEXLINE_WIDTH; \ end_hexline(); \ t1_eexec_encrypt = false # define t1_log(s) mp_printf(s) # define t1_putchar(c) fputc(c, bitfile) # define embed_all_glyphs(tex_font) false # undef pdfmovechars # ifdef SHIFTLOWCHARS extern char errbuf[]; extern Boolean shiftlowchars; # define pdfmovechars shiftlowchars # define t1_char(c) T1Char(c) # else /* SHIFTLOWCHARS */ # define t1_char(c) c # define pdfmovechars 0 # endif /* SHIFTLOWCHARS */ # define extra_charset() dvips_extra_charset # define update_subset_tag() # define fixedcontent true static char *dvips_extra_charset; static int hexline_length; const char notdef[] = ".notdef"; /* static size_t last_ptr_index; */ #include #include #include #define t1_getchar() getc(t1_file) #define t1_ungetchar(c) ungetc(c, t1_file) #define t1_eof() feof(t1_file) #define t1_close() xfclose(t1_file, cur_file_name) #define enc_getchar() getc(enc_file) #define enc_eof() feof(enc_file) #define enc_close() xfclose(enc_file, cur_file_name) #define valid_code(c) (c >= 0 && c < 256) static const char *standard_glyph_names[256] = { notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash", "dagger", "daggerdbl", "periodcentered", notdef, "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", notdef, "questiondown", notdef, "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", notdef, "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash", notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, "AE", notdef, "ordfeminine", notdef, notdef, notdef, notdef, "Lslash", "Oslash", "OE", "ordmasculine", notdef, notdef, notdef, notdef, notdef, "ae", notdef, notdef, notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe", "germandbls", notdef, notdef, notdef, notdef }; static char charstringname[] = "/CharStrings"; char **t1_glyph_names; char *t1_builtin_glyph_names[256]; char charsetstr[0x4000]; static boolean read_encoding_only; static int t1_encoding; #define T1_BUF_SIZE 0x10 #define ENC_BUF_SIZE 0x1000 #define ENC_STANDARD 0 #define ENC_BUILTIN 1 #define CS_HSTEM 1 #define CS_VSTEM 3 #define CS_VMOVETO 4 #define CS_RLINETO 5 #define CS_HLINETO 6 #define CS_VLINETO 7 #define CS_RRCURVETO 8 #define CS_CLOSEPATH 9 #define CS_CALLSUBR 10 #define CS_RETURN 11 #define CS_ESCAPE 12 #define CS_HSBW 13 #define CS_ENDCHAR 14 #define CS_RMOVETO 21 #define CS_HMOVETO 22 #define CS_VHCURVETO 30 #define CS_HVCURVETO 31 #define CS_1BYTE_MAX (CS_HVCURVETO + 1) #define CS_DOTSECTION CS_1BYTE_MAX + 0 #define CS_VSTEM3 CS_1BYTE_MAX + 1 #define CS_HSTEM3 CS_1BYTE_MAX + 2 #define CS_SEAC CS_1BYTE_MAX + 6 #define CS_SBW CS_1BYTE_MAX + 7 #define CS_DIV CS_1BYTE_MAX + 12 #define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16 #define CS_POP CS_1BYTE_MAX + 17 #define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33 #define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1) #define CS_MAX CS_2BYTE_MAX typedef unsigned char byte; typedef struct { byte nargs; /* number of arguments */ boolean bottom; /* take arguments from bottom of stack? */ boolean clear; /* clear stack? */ boolean valid; } cc_entry; /* CharString Command */ typedef struct { char *name; /* glyph name (or notdef for Subrs entry) */ byte *data; unsigned short len; /* length of the whole string */ unsigned short cslen; /* length of the encoded part of the string */ boolean used; boolean valid; } cs_entry; static unsigned short t1_dr, t1_er; static const unsigned short t1_c1 = 52845, t1_c2 = 22719; static unsigned short t1_cslen; static short t1_lenIV; static char enc_line[ENC_BUF_SIZE]; /* define t1_line_ptr, t1_line_array & t1_line_limit */ typedef char t1_line_entry; define_array (t1_line); /* define t1_buf_ptr, t1_buf_array & t1_buf_limit */ typedef char t1_buf_entry; define_array (t1_buf); static int cs_start; static cs_entry *cs_tab, *cs_ptr, *cs_notdef; static char *cs_dict_start, *cs_dict_end; static int cs_count, cs_size, cs_size_pos; static cs_entry *subr_tab; static char *subr_array_start, *subr_array_end; static int subr_max, subr_size, subr_size_pos; /* This list contains the begin/end tokens commonly used in the */ /* /Subrs array of a Type 1 font. */ static const char *cs_token_pairs_list[][2] = { {" RD", "NP"}, {" -|", "|"}, {" RD", "noaccess put"}, {" -|", "noaccess put"}, {NULL, NULL} }; static const char **cs_token_pair; static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic; static int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */ static long t1_block_length; static int last_hexbyte; static FILE *t1_file; static FILE *enc_file; #define t1_prefix(s) str_prefix(t1_line_array, s) #define t1_buf_prefix(s) str_prefix(t1_buf_array, s) #define t1_suffix(s) str_suffix(t1_line_array, t1_line_ptr, s) #define t1_buf_suffix(s) str_suffix(t1_buf_array, t1_buf_ptr, s) #define t1_charstrings() strstr(t1_line_array, charstringname) #define t1_subrs() t1_prefix("/Subrs") #define t1_end_eexec() t1_suffix("mark currentfile closefile") #define t1_cleartomark() t1_prefix("cleartomark") #ifndef pdfTeX # define HEXLINE_WIDTH 64 static void end_hexline () { if (hexline_length == HEXLINE_WIDTH) { fputs ("\n", bitfile); hexline_length = 0; } } static void t1_outhex (byte b) { static char *hexdigits = "0123456789ABCDEF"; t1_putchar (hexdigits[b / 16]); t1_putchar (hexdigits[b % 16]); hexline_length += 2; end_hexline (); } #endif /* pdfTeX */ static void enc_getline (void) { char *p; int c; restart: if (enc_eof ()) pdftex_fail ("unexpected end of file"); p = enc_line; do { c = enc_getchar (); append_char_to_buf (c, p, enc_line, ENC_BUF_SIZE); } while (c != 10); append_eol (p, enc_line, ENC_BUF_SIZE); if (p - enc_line < 2 || *enc_line == '%') goto restart; } void load_enc (char *enc_name, char **enc_encname, char **glyph_names) { char buf[ENC_BUF_SIZE], *p, *r; int names_count; char *myname; set_cur_file_name (enc_name); if (!enc_open ()) { pdftex_warn ("cannot open encoding file for reading"); cur_file_name = NULL; return; } t1_log ("{"); t1_log (cur_file_name = full_file_name ()); enc_getline (); if (*enc_line != '/' || (r = strchr (enc_line, '[')) == NULL) { remove_eol (r, enc_line); pdftex_fail ("invalid encoding vector (a name or `[' missing): `%s'", enc_line); } while (*(r-1)==' ') r--; /* strip trailing spaces from encoding name */ myname = xmalloc(r-enc_line); memcpy(myname,enc_line+1,(r-enc_line)-1); *(myname+(r-enc_line-1))=0; *enc_encname = myname; while (*r!='[') r++; r++; /* skip '[' */ names_count = 0; skip (r, ' '); for (;;) { while (*r == '/') { for (p = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++); *p = 0; skip (r, ' '); if (names_count > 256) pdftex_fail ("encoding vector contains more than 256 names"); if (strcmp (buf, notdef) != 0) glyph_names[names_count] = xstrdup (buf); names_count++; } if (*r != 10 && *r != '%') { if (str_prefix (r, "] def")) goto done; else { remove_eol (r, enc_line); pdftex_fail ("invalid encoding vector: a name or `] def' expected: `%s'", enc_line); } } enc_getline (); r = enc_line; } done: enc_close (); t1_log ("}"); cur_file_name = NULL; } static void t1_check_pfa (void) { const int c = t1_getchar (); t1_pfa = (c != 128) ? true : false; t1_ungetchar (c); } static int t1_getbyte (void) { int c = t1_getchar (); if (t1_pfa) return c; if (t1_block_length == 0) { if (c != 128) pdftex_fail ("invalid marker"); c = t1_getchar (); if (c == 3) { while (!t1_eof ()) t1_getchar (); return EOF; } t1_block_length = t1_getchar () & 0xff; t1_block_length |= (t1_getchar () & 0xff) << 8; t1_block_length |= (t1_getchar () & 0xff) << 16; t1_block_length |= (t1_getchar () & 0xff) << 24; c = t1_getchar (); } t1_block_length--; return c; } static int hexval (int 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 -1; } static byte edecrypt (byte cipher) { byte plain; if (t1_pfa) { while (cipher == 10 || cipher == 13) cipher = t1_getbyte (); last_hexbyte = cipher = (hexval (cipher) << 4) + hexval (t1_getbyte ()); } plain = (cipher ^ (t1_dr >> 8)); t1_dr = (cipher + t1_dr) * t1_c1 + t1_c2; return plain; } static byte cdecrypt (byte cipher, unsigned short *cr) { const byte plain = (cipher ^ (*cr >> 8)); *cr = (cipher + *cr) * t1_c1 + t1_c2; return plain; } static byte eencrypt (byte plain) { const byte cipher = (plain ^ (t1_er >> 8)); t1_er = (cipher + t1_er) * t1_c1 + t1_c2; return cipher; } static byte cencrypt (byte plain, unsigned short *cr) { const byte cipher = (plain ^ (*cr >> 8)); *cr = (cipher + *cr) * t1_c1 + t1_c2; return cipher; } static char *eol (char *s) { char *p = strend (s); if (p - s > 1 && p[-1] != 10) { *p++ = 10; *p = 0; } return p; } static float t1_scan_num (char *p, char **r) { float f; skip (p, ' '); if (sscanf (p, "%g", &f) != 1) { remove_eol (p, t1_line_array); pdftex_fail ("a number expected: `%s'", t1_line_array); } if (r != NULL) { for (; isdigit (*p) || *p == '.' || *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++); *r = p; } return f; } static boolean str_suffix (const char *begin_buf, const char *end_buf, const char *s) { const char *s1 = end_buf - 1, *s2 = strend (s) - 1; if (*s1 == 10) s1--; while (s1 >= begin_buf && s2 >= s) { if (*s1-- != *s2--) return false; } return s2 < s; } static void t1_getline (void) { int c, l, eexec_scan; char *p; static const char eexec_str[] = "currentfile eexec"; static int eexec_len = 17; /* strlen(eexec_str) */ restart: if (t1_eof ()) pdftex_fail ("unexpected end of file"); t1_line_ptr = t1_line_array; alloc_array (t1_line, 1, T1_BUF_SIZE); t1_cslen = 0; eexec_scan = 0; c = t1_getbyte (); if (c == EOF) goto exit; while (!t1_eof ()) { if (t1_in_eexec == 1) c = edecrypt (c); alloc_array (t1_line, 1, T1_BUF_SIZE); append_char_to_buf (c, t1_line_ptr, t1_line_array, t1_line_limit); if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) { if (t1_line_array[eexec_scan] == eexec_str[eexec_scan]) eexec_scan++; else eexec_scan = -1; } if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32)) break; if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line_array > 4) && (t1_suffix (" RD ") || t1_suffix (" -| "))) { p = t1_line_ptr - 5; while (*p != ' ') p--; t1_cslen = l = t1_scan_num (p + 1, 0); cs_start = t1_line_ptr - t1_line_array; /* cs_start is an index now */ alloc_array (t1_line, l, T1_BUF_SIZE); while (l-- > 0) *t1_line_ptr++ = edecrypt (t1_getbyte ()); } c = t1_getbyte (); } alloc_array (t1_line, 2, T1_BUF_SIZE); /* append_eol can append 2 chars */ append_eol (t1_line_ptr, t1_line_array, t1_line_limit); if (t1_line_ptr - t1_line_array < 2) goto restart; if (eexec_scan == eexec_len) t1_in_eexec = 1; exit: /* ensure that t1_buf_array has as much room as t1_line_array */ t1_buf_ptr = t1_buf_array; alloc_array (t1_buf, t1_line_limit, t1_line_limit); } static void t1_putline (void) { char *p = t1_line_array; if (t1_line_ptr - t1_line_array <= 1) return; if (t1_eexec_encrypt) { while (p < t1_line_ptr) out_eexec_char (eencrypt (*p++)); } else { while (p < t1_line_ptr) t1_putchar (*p++); } } static void t1_puts (const char *s) { if (s != t1_line_array) strcpy (t1_line_array, s); t1_line_ptr = strend (t1_line_array); t1_putline (); } static void t1_printf (const char *fmt, ...) { va_list args; va_start (args, fmt); vsprintf (t1_line_array, fmt, args); t1_puts (t1_line_array); va_end (args); } static void t1_init_params (const char *open_name_prefix) { if ((open_name_prefix != NULL) && strlen(open_name_prefix)) { t1_log (open_name_prefix); t1_log (cur_file_name); } t1_lenIV = 4; t1_dr = 55665; t1_er = 55665; t1_in_eexec = 0; t1_cs = false; t1_scan = true; t1_synthetic = false; t1_eexec_encrypt = false; t1_block_length = 0; t1_check_pfa (); } static void t1_close_font_file (const char *close_name_suffix) { if ((close_name_suffix != NULL) && strlen(close_name_suffix)) { t1_log (close_name_suffix); } t1_close (); cur_file_name = NULL; } static void t1_check_block_len (boolean decrypt) { int l, c; if (t1_block_length == 0) return; c = t1_getbyte (); if (decrypt) c = edecrypt (c); l = t1_block_length; if (!(l == 0 && (c == 10 || c == 13))) { pdftex_warn ("%i bytes more than expected were ignored", l + 1); while (l-- > 0) t1_getbyte (); } } static void t1_start_eexec (fm_entry *fm_cur) { int i; if (is_included (fm_cur)) { get_length1 (); save_offset (); } if (!t1_pfa) t1_check_block_len (false); for (t1_line_ptr = t1_line_array, i = 0; i < 4; i++) { edecrypt (t1_getbyte ()); *t1_line_ptr++ = 0; } t1_eexec_encrypt = true; if (!read_encoding_only) if (is_included (fm_cur)) t1_putline (); /* to put the first four bytes */ } static void t1_stop_eexec (fm_entry *fm_cur) { int c; if (is_included (fm_cur)) { get_length2 (); save_offset (); } end_last_eexec_line (); if (!t1_pfa) t1_check_block_len (true); else { c = edecrypt (t1_getbyte ()); if (!(c == 10 || c == 13)) { if (last_hexbyte == 0) t1_puts ("00"); else pdftex_warn ("unexpected data after eexec"); } } t1_cs = false; t1_in_eexec = 2; } #ifdef pdfTeX /* macros for various transforms; currently only slant and extend are used */ # define do_xshift(x,a) {x[4]+=a;} # define do_yshift(x,a) {x[5]+=a;} # define do_xscale(x,a) {x[0]*=a; x[2]*=a; x[4]*=a;} # define do_yscale(x,a) {x[1]*=a; x[3]*=a; x[5]*=a;} # define do_extend(x,a) {do_xscale(x,a);} # define do_scale(x,a) {do_xscale(x,a); do_yscale(x,a);} # define do_slant(x,a) {x[0]+=x[1]*(a); x[2]+=x[3]*(a); x[4]+=x[5]*(a);} # define do_shear(x,a) {x[1]+=x[0]*(a); x[3]+=x[2]*(a); x[5]+=x[4]*(a);} # define do_rotate(x,a) \ {float t, u=cos(a), v=sin(a); \ t =x[0]*u+x[1]*-v; \ x[1] =x[0]*v+x[1]* u; x[0]=t; \ t =x[2]*u+x[3]*-v; \ x[3] =x[2]*v+x[3]* u; x[2]=t; \ t =x[4]*u+x[5]*-v; \ x[5] =x[4]*v+x[5]* u; x[4]=t;} static void t1_modify_fm (void) { /* * font matrix is given as six numbers a0..a5, which stands for the matrix * * a0 a1 0 * M = a2 a3 0 * a4 a5 1 * * ExtendFont is given as * * e 0 0 * E = 0 1 0 * 0 0 1 * * SlantFont is given as * * 1 0 0 * S = s 1 0 * 0 0 1 * * The slant transform must be done _before_ the extend transform * for compatibility! */ float a[6]; int i, c; char *p, *q, *r; if ((p = strchr (t1_line_array, '[')) == 0) if ((p = strchr (t1_line_array, '{')) == 0) { remove_eol (p, t1_line_array); pdftex_fail ("FontMatrix: an array expected: `%s'", t1_line_array); } c = *p++; /* save the character '[' resp. '{' */ strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array)); r = t1_buf_array + (p - t1_line_array); for (i = 0; i < 6; i++) { a[i] = t1_scan_num (p, &q); p = q; } if (fm_slant (fm_cur) != 0) do_slant (a, fm_slant (fm_cur) * 1E-3); if (fm_extend (fm_cur) != 0) do_extend (a, fm_extend (fm_cur) * 1E-3); for (i = 0; i < 6; i++) { sprintf (r, "%g ", a[i]); r = strend (r); } if (c == '[') { while (*p != ']' && *p != 0) p++; } else { while (*p != '}' && *p != 0) p++; } if (*p == 0) { remove_eol (p, t1_line_array); pdftex_fail ("FontMatrix: cannot find the corresponding character to '%c': `%s'", c, t1_line_array); } strcpy (r, p); strcpy (t1_line_array, t1_buf_array); t1_line_ptr = eol (t1_line_array); } static void t1_modify_italic (void) { float a; char *p, *r; if (fm_slant (fm_cur) == 0) return; p = strchr (t1_line_array, ' '); strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array + 1)); a = t1_scan_num (p + 1, &r); a -= atan (fm_slant (fm_cur) * 1E-3) * (180 / M_PI); sprintf (t1_buf_array + (p - t1_line_array + 1), "%g", a); strcpy (strend (t1_buf_array), r); strcpy (t1_line_array, t1_buf_array); t1_line_ptr = eol (t1_line_array); font_keys[ITALIC_ANGLE_CODE].value = round (a); font_keys[ITALIC_ANGLE_CODE].valid = true; } #else static void t1_modify_fm (void) { // t1_line_ptr = eol (t1_line_array); } static void t1_modify_italic (void) { // t1_line_ptr = eol (t1_line_array); } #endif /* pdfTeX */ key_entry font_keys[FONT_KEYS_NUM] = { {"Ascent", "Ascender", 0, false}, {"CapHeight", "CapHeight", 0, false}, {"Descent", "Descender", 0, false}, {"FontName", "FontName", 0, false}, {"ItalicAngle", "ItalicAngle", 0, false}, {"StemV", "StdVW", 0, false}, {"XHeight", "XHeight", 0, false}, {"FontBBox", "FontBBox", 0, false}, {"", "", 0, false}, {"", "", 0, false}, {"", "", 0, false} }; static void t1_scan_keys (int tex_font,fm_entry *fm_cur) { int i, k; char *p, *r; key_entry *key; if (fm_extend (fm_cur) != 0 || fm_slant (fm_cur) != 0) { if (t1_prefix ("/FontMatrix")) { t1_modify_fm (); return; } if (t1_prefix ("/ItalicAngle")) { t1_modify_italic (); return; } } if (t1_prefix ("/FontType")) { p = t1_line_array + strlen ("FontType") + 1; if ((i = t1_scan_num (p, 0)) != 1) pdftex_fail ("Type%d fonts unsupported by metapost", i); return; } for (key = font_keys; key - font_keys < MAX_KEY_CODE; key++) if (str_prefix (t1_line_array + 1, key->t1name)) break; if (key - font_keys == MAX_KEY_CODE) return; key->valid = true; p = t1_line_array + strlen (key->t1name) + 1; skip (p, ' '); if ((k = key - font_keys) == FONTNAME_CODE) { if (*p != '/') { remove_eol (p, t1_line_array); pdftex_fail ("a name expected: `%s'", t1_line_array); } r = ++p; /* skip the slash */ if (is_included (fm_cur)) { /* save the fontname */ strncpy (fontname_buf, p, FONTNAME_BUF_SIZE); for (i=0; fontname_buf[i] != 10; i++); fontname_buf[i]=0; if(is_subsetted (fm_cur)) { if (fm_cur->encoding!=NULL && fm_cur->encoding->glyph_names!=NULL) make_subset_tag (fm_cur, fm_cur->encoding->glyph_names, tex_font); else make_subset_tag (fm_cur, t1_builtin_glyph_names, tex_font); alloc_array (t1_line, (r-t1_line_array+6+1+strlen(fontname_buf)+1), T1_BUF_SIZE); strncpy (r, fm_cur->subset_tag , 6); *(r+6) = '-'; strncpy (r+7, fontname_buf, strlen(fontname_buf)+1); t1_line_ptr = eol (r); } else { /* for (q = p; *q != ' ' && *q != 10; *q++);*/ /**q = 0;*/ t1_line_ptr = eol (r); } } return; } if ((k == STEMV_CODE || k == FONTBBOX1_CODE) && (*p == '[' || *p == '{')) p++; if (k == FONTBBOX1_CODE) { for (i = 0; i < 4; i++) { key[i].value = t1_scan_num (p, &r); p = r; } return; } key->value = t1_scan_num (p, 0); } static void t1_scan_param (int tex_font,fm_entry *fm_cur) { static const char *lenIV = "/lenIV"; if (!t1_scan || *t1_line_array != '/') return; if (t1_prefix (lenIV)) { t1_lenIV = t1_scan_num (t1_line_array + strlen (lenIV), 0); return; } t1_scan_keys (tex_font,fm_cur); } static void copy_glyph_names (char **glyph_names, int a, int b) { if (glyph_names[b] != notdef) { free (glyph_names[b]); glyph_names[b] = (char *) notdef; } if (glyph_names[a] != notdef) { glyph_names[b] = xstrdup (glyph_names[a]); } } static void t1_builtin_enc (void) { int i, a, b, c, counter = 0; char *r, *p; /* * At this moment "/Encoding" is the prefix of t1_line_array */ if (t1_suffix ("def")) { /* predefined encoding */ sscanf (t1_line_array + strlen ("/Encoding"), "%256s", t1_buf_array); if (strcmp (t1_buf_array, "StandardEncoding") == 0) { for (i = 0; i < 256; i++) if (standard_glyph_names[i] == notdef) t1_builtin_glyph_names[i] = (char *) notdef; else t1_builtin_glyph_names[i] = xstrdup (standard_glyph_names[i]); t1_encoding = ENC_STANDARD; } else pdftex_fail ("cannot subset font (unknown predefined encoding `%s')", t1_buf_array); return; } else t1_encoding = ENC_BUILTIN; /* * At this moment "/Encoding" is the prefix of t1_line_array, and the encoding is * not a predefined encoding * * We have two possible forms of Encoding vector. The first case is * * /Encoding [/a /b /c...] readonly def * * and the second case can look like * * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for * dup 0 /x put * dup 1 /y put * ... * readonly def */ for (i = 0; i < 256; i++) t1_builtin_glyph_names[i] = (char *) notdef; if (t1_prefix ("/Encoding [") || t1_prefix ("/Encoding[")) { /* the first case */ r = strchr (t1_line_array, '[') + 1; skip (r, ' '); for (;;) { while (*r == '/') { for (p = t1_buf_array, r++; *r != 32 && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++); *p = 0; skip (r, ' '); if (counter > 255) pdftex_fail ("encoding vector contains more than 256 names"); if (strcmp (t1_buf_array, notdef) != 0) t1_builtin_glyph_names[counter] = xstrdup (t1_buf_array); counter++; } if (*r != 10 && *r != '%') { if (str_prefix (r, "] def") || str_prefix (r, "] readonly def")) break; else { remove_eol (r, t1_line_array); pdftex_fail ("a name or `] def' or `] readonly def' expected: `%s'", t1_line_array); } } t1_getline (); r = t1_line_array; } } else { /* the second case */ p = strchr (t1_line_array, 10); for (;;) { if (*p == 10) { t1_getline (); p = t1_line_array; } /* check for `dup put' */ if (sscanf (p, "dup %i%256s put", &i, t1_buf_array) == 2 && *t1_buf_array == '/' && valid_code (i)) { if (strcmp (t1_buf_array + 1, notdef) != 0) t1_builtin_glyph_names[i] = xstrdup (t1_buf_array + 1); p = strstr (p, " put") + strlen (" put"); skip (p, ' '); } /* check for `dup dup exch get put' */ else if (sscanf (p, "dup dup %i exch %i get put", &b, &a) == 2 && valid_code (a) && valid_code (b)) { copy_glyph_names (t1_builtin_glyph_names, a, b); p = strstr (p, " get put") + strlen (" get put"); skip (p, ' '); } /* check for `dup dup getinterval exch putinterval' */ else if (sscanf (p, "dup dup %i %i getinterval %i exch putinterval", &a, &c, &b) == 3 && valid_code (a) && valid_code (b) && valid_code (c)) { for (i = 0; i < c; i++) copy_glyph_names (t1_builtin_glyph_names, a + i, b + i); p = strstr (p, " putinterval") + strlen (" putinterval"); skip (p, ' '); } /* check for `def' or `readonly def' */ else if ((p == t1_line_array || (p > t1_line_array && p[-1] == ' ')) && strcmp (p, "def\n") == 0) return; /* skip an unrecognizable word */ else { while (*p != ' ' && *p != 10) p++; skip (p, ' '); } } } } static void t1_check_end (void) { if (t1_eof ()) return; t1_getline (); if (t1_prefix ("{restore}")) t1_putline (); } static boolean t1_open_fontfile (fm_entry *fm_cur,const char *open_name_prefix) { ff_entry *ff; ff = check_ff_exist (fm_cur); if (ff->ff_path != NULL) t1_file = xfopen (cur_file_name = ff->ff_path, FOPEN_RBIN_MODE); else { set_cur_file_name (fm_cur->ff_name); pdftex_warn ("cannot open Type 1 font file for reading"); return false; } t1_init_params (open_name_prefix); fontfile_found = true; return true; } static void t1_scan_only (int tex_font, fm_entry *fm_cur) { do { t1_getline (); t1_scan_param (tex_font, fm_cur); } while (t1_in_eexec == 0); t1_start_eexec (fm_cur); do { t1_getline (); t1_scan_param (tex_font, fm_cur); } while (!(t1_charstrings () || t1_subrs ())); } static void t1_include (int tex_font, fm_entry *fm_cur) { do { t1_getline (); t1_scan_param (tex_font, fm_cur); t1_putline (); } while (t1_in_eexec == 0); t1_start_eexec (fm_cur); do { t1_getline (); t1_scan_param (tex_font, fm_cur); t1_putline (); } while (!(t1_charstrings () || t1_subrs ())); t1_cs = true; do { t1_getline (); t1_putline (); } while (!t1_end_eexec ()); t1_stop_eexec (fm_cur); if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */ do { t1_getline (); t1_putline (); } while (!t1_cleartomark ()); t1_check_end (); /* write "{restore}if" if found */ } get_length3 (); } #define check_subr(subr) \ if (subr >= subr_size || subr < 0) \ pdftex_fail("Subrs array: entry index out of range (%i)", subr); static const char **check_cs_token_pair () { const char **p = (const char **) cs_token_pairs_list; for (; p[0] != NULL; ++p) if (t1_buf_prefix (p[0]) && t1_buf_suffix (p[1])) return p; return NULL; } static void cs_store (boolean is_subr) { char *p; cs_entry *ptr; int subr; for (p = t1_line_array, t1_buf_ptr = t1_buf_array; *p != ' '; *t1_buf_ptr++ = *p++); *t1_buf_ptr = 0; if (is_subr) { subr = t1_scan_num (p + 1, 0); check_subr (subr); ptr = subr_tab + subr; } else { ptr = cs_ptr++; if (cs_ptr - cs_tab > cs_size) pdftex_fail ("CharStrings dict: more entries than dict size (%i)", cs_size); if (strcmp (t1_buf_array + 1, notdef) == 0) /* skip the slash */ ptr->name = (char *) notdef; else ptr->name = xstrdup (t1_buf_array + 1); } /* copy " RD " + cs data to t1_buf_array */ memcpy (t1_buf_array, t1_line_array + cs_start - 4, (unsigned) (t1_cslen + 4)); /* copy the end of cs data to t1_buf_array */ for (p = t1_line_array + cs_start + t1_cslen, t1_buf_ptr = t1_buf_array + t1_cslen + 4; *p != 10; *t1_buf_ptr++ = *p++); *t1_buf_ptr++ = 10; if (is_subr && cs_token_pair == NULL) cs_token_pair = check_cs_token_pair (); ptr->len = t1_buf_ptr - t1_buf_array; ptr->cslen = t1_cslen; ptr->data = xtalloc (ptr->len, byte); memcpy (ptr->data, t1_buf_array, ptr->len); ptr->valid = true; } #define store_subr() cs_store(true) #define store_cs() cs_store(false) #define CC_STACK_SIZE 24 static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack; static cc_entry cc_tab[CS_MAX]; static boolean is_cc_init = false; #define cc_pop(N) \ if (stack_ptr - cc_stack < (N)) \ stack_error(N); \ stack_ptr -= N #define stack_error(N) { \ pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \ (int) N, (int)(stack_ptr - cc_stack)); \ goto cs_error; \ } /* static integer cc_get(integer index) { if (index < 0) { if (stack_ptr + index < cc_stack ) stack_error(stack_ptr - cc_stack + index); return *(stack_ptr + index); } else { if (cc_stack + index >= stack_ptr) stack_error(index); return cc_stack[index]; } } */ #define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N))) #define cc_push(V) *stack_ptr++ = V #define cc_clear() stack_ptr = cc_stack #define set_cc(N, B, A, C) \ cc_tab[N].nargs = A; \ cc_tab[N].bottom = B; \ cc_tab[N].clear = C; \ cc_tab[N].valid = true static void cc_init (void) { int i; if (is_cc_init) return; for (i = 0; i < CS_MAX; i++) cc_tab[i].valid = false; set_cc (CS_HSTEM, true, 2, true); set_cc (CS_VSTEM, true, 2, true); set_cc (CS_VMOVETO, true, 1, true); set_cc (CS_RLINETO, true, 2, true); set_cc (CS_HLINETO, true, 1, true); set_cc (CS_VLINETO, true, 1, true); set_cc (CS_RRCURVETO, true, 6, true); set_cc (CS_CLOSEPATH, false, 0, true); set_cc (CS_CALLSUBR, false, 1, false); set_cc (CS_RETURN, false, 0, false); /* set_cc(CS_ESCAPE, false, 0, false); */ set_cc (CS_HSBW, true, 2, true); set_cc (CS_ENDCHAR, false, 0, true); set_cc (CS_RMOVETO, true, 2, true); set_cc (CS_HMOVETO, true, 1, true); set_cc (CS_VHCURVETO, true, 4, true); set_cc (CS_HVCURVETO, true, 4, true); set_cc (CS_DOTSECTION, false, 0, true); set_cc (CS_VSTEM3, true, 6, true); set_cc (CS_HSTEM3, true, 6, true); set_cc (CS_SEAC, true, 5, true); set_cc (CS_SBW, true, 4, true); set_cc (CS_DIV, false, 2, false); set_cc (CS_CALLOTHERSUBR, false, 0, false); set_cc (CS_POP, false, 0, false); set_cc (CS_SETCURRENTPOINT, true, 2, true); is_cc_init = true; } #define cs_getchar() cdecrypt(*data++, &cr) #define mark_subr(n) cs_mark(0, n) #define mark_cs(s) cs_mark(s, 0) static void cs_warn (const char *cs_name, int subr, const char *fmt, ...) { char buf[SMALL_BUF_SIZE]; va_list args; va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); if (cs_name == NULL) pdftex_warn ("Subr (%i): %s", (int) subr, buf); else pdftex_warn ("CharString (/%s): %s", cs_name, buf); } static void cs_mark (const char *cs_name, int subr) { byte *data; int i, b, cs_len; integer a, a1, a2; unsigned short cr; static integer lastargOtherSubr3 = 3; /* the argument of last call to OtherSubrs[3] */ cs_entry *ptr; cc_entry *cc; if (cs_name == NULL) { check_subr (subr); ptr = subr_tab + subr; if (!ptr->valid) return; } else { if (cs_notdef != NULL && (cs_name == notdef || strcmp (cs_name, notdef) == 0)) ptr = cs_notdef; else { for (ptr = cs_tab; ptr < cs_ptr; ptr++) if (strcmp (ptr->name, cs_name) == 0) break; if (ptr == cs_ptr) { pdftex_warn ("glyph `%s' undefined", cs_name); return; } if (ptr->name == notdef) cs_notdef = ptr; } } /* only marked CharString entries and invalid entries can be skipped; valid marked subrs must be parsed to keep the stack in sync */ if (!ptr->valid || (ptr->used && cs_name != NULL)) return; ptr->used = true; cr = 4330; cs_len = ptr->cslen; data = ptr->data + 4; for (i = 0; i < t1_lenIV; i++, cs_len--) cs_getchar (); while (cs_len > 0) { --cs_len; b = cs_getchar (); if (b >= 32) { if (b <= 246) a = b - 139; else if (b <= 250) { --cs_len; a = ((b - 247) << 8) + 108 + cs_getchar (); } else if (b <= 254) { --cs_len; a = -((b - 251) << 8) - 108 - cs_getchar (); } else { cs_len -= 4; a = (cs_getchar () & 0xff) << 24; a |= (cs_getchar () & 0xff) << 16; a |= (cs_getchar () & 0xff) << 8; a |= (cs_getchar () & 0xff) << 0; if (sizeof (integer) > 4 && (a & 0x80000000)) a |= ~0x7FFFFFFF; } cc_push (a); } else { if (b == CS_ESCAPE) { b = cs_getchar () + CS_1BYTE_MAX; cs_len--; } if (b >= CS_MAX) { cs_warn (cs_name, subr, "command value out of range: %i", (int) b); goto cs_error; } cc = cc_tab + b; if (!cc->valid) { cs_warn (cs_name, subr, "command not valid: %i", (int) b); goto cs_error; } if (cc->bottom) { if (stack_ptr - cc_stack < cc->nargs) cs_warn (cs_name, subr, "less arguments on stack (%i) than required (%i)", (int) (stack_ptr - cc_stack), (int) cc->nargs); else if (stack_ptr - cc_stack > cc->nargs) cs_warn (cs_name, subr, "more arguments on stack (%i) than required (%i)", (int) (stack_ptr - cc_stack), (int) cc->nargs); } switch (cc - cc_tab) { case CS_CALLSUBR: a1 = cc_get (-1); cc_pop (1); mark_subr (a1); if (!subr_tab[a1].valid) { cs_warn (cs_name, subr, "cannot call subr (%i)", (int) a1); goto cs_error; } break; case CS_DIV: cc_pop (2); cc_push (0); break; case CS_CALLOTHERSUBR: if (cc_get (-1) == 3) lastargOtherSubr3 = cc_get (-3); a1 = cc_get (-2) + 2; cc_pop (a1); break; case CS_POP: cc_push (lastargOtherSubr3); /* the only case when we care about the value being pushed onto stack is when POP follows CALLOTHERSUBR (changing hints by OtherSubrs[3]) */ break; case CS_SEAC: a1 = cc_get (3); a2 = cc_get (4); cc_clear (); mark_cs (standard_glyph_names[a1]); mark_cs (standard_glyph_names[a2]); break; default: if (cc->clear) cc_clear (); } } } return; cs_error: /* an error occured during parsing */ cc_clear (); ptr->valid = false; ptr->used = false; } static void t1_subset_ascii_part (int tex_font, fm_entry *fm_cur) { int i, j; t1_getline (); while (!t1_prefix ("/Encoding")) { t1_scan_param (tex_font, fm_cur); t1_putline (); t1_getline (); } t1_builtin_enc (); if (is_reencoded (fm_cur)) t1_glyph_names = external_enc (); else t1_glyph_names = t1_builtin_glyph_names; /* if (is_included (fm_cur) && is_subsetted (fm_cur)) { make_subset_tag (fm_cur, t1_glyph_names, tex_font); update_subset_tag (); } */ if ((!is_subsetted (fm_cur)) && t1_encoding == ENC_STANDARD) t1_puts ("/Encoding StandardEncoding def\n"); else { t1_puts ("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n"); for (i = 0, j = 0; i < 256; i++) { if (is_used_char (i) && t1_glyph_names[i] != notdef) { j++; t1_printf ("dup %i /%s put\n", (int) t1_char (i), t1_glyph_names[i]); } } /* We didn't mark anything for the Encoding array. */ /* We add "dup 0 /.notdef put" for compatibility */ /* with Acrobat 5.0. */ if (j == 0) t1_puts ("dup 0 /.notdef put\n"); t1_puts ("readonly def\n"); } do { t1_getline (); t1_scan_param (tex_font, fm_cur); if (!t1_prefix ("/UniqueID")) /* ignore UniqueID for subsetted fonts */ t1_putline (); } while (t1_in_eexec == 0); } #define t1_subr_flush() t1_flush_cs(true) #define t1_cs_flush() t1_flush_cs(false) static void t1_flush_cs (boolean); static void cs_init (void) { cs_ptr = cs_tab = NULL; cs_dict_start = cs_dict_end = NULL; cs_count = cs_size = cs_size_pos = 0; cs_token_pair = NULL; subr_tab = NULL; subr_array_start = subr_array_end = NULL; subr_max = subr_size = subr_size_pos = 0; } static void init_cs_entry (cs_entry * cs) { cs->data = NULL; cs->name = NULL; cs->len = 0; cs->cslen = 0; cs->used = false; cs->valid = false; } static void t1_mark_glyphs (int tex_font); static void t1_read_subrs (int tex_font, fm_entry *fm_cur) { int i, s; cs_entry *ptr; t1_getline (); while (!(t1_charstrings () || t1_subrs ())) { t1_scan_param (tex_font, fm_cur); t1_putline (); t1_getline (); } found: t1_cs = true; t1_scan = false; if (!t1_subrs ()) return; subr_size_pos = strlen ("/Subrs") + 1; /* subr_size_pos points to the number indicating dict size after "/Subrs" */ subr_size = t1_scan_num (t1_line_array + subr_size_pos, 0); if (subr_size == 0) { while (!t1_charstrings ()) t1_getline (); return; } // subr_tab = xtalloc (subr_size, cs_entry); subr_tab = (cs_entry *)malloc (subr_size*sizeof (cs_entry)); for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++) init_cs_entry (ptr); subr_array_start = xstrdup (t1_line_array); t1_getline (); while (t1_cslen) { store_subr (); t1_getline (); } /* mark the first four entries without parsing */ for (i = 0; i < subr_size && i < 4; i++) subr_tab[i].used = true; /* the end of the Subrs array might have more than one line so we need to concatnate them to subr_array_end. Unfortunately some fonts don't have the Subrs array followed by the CharStrings dict immediately (synthetic fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then we will treat the font as synthetic and ignore everything until next Subrs is found */ #define POST_SUBRS_SCAN 5 s = 0; *t1_buf_array = 0; for (i = 0; i < POST_SUBRS_SCAN; i++) { if (t1_charstrings ()) break; s += t1_line_ptr - t1_line_array; alloc_array (t1_buf, s, T1_BUF_SIZE); strcat (t1_buf_array, t1_line_array); t1_getline (); } subr_array_end = xstrdup (t1_buf_array); if (i == POST_SUBRS_SCAN) { /* CharStrings not found; suppose synthetic font */ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++) if (ptr->valid) xfree (ptr->data); xfree (subr_tab); xfree (subr_array_start); xfree (subr_array_end); cs_init (); t1_cs = false; t1_synthetic = true; while (!(t1_charstrings () || t1_subrs ())) t1_getline (); goto found; } } static void t1_flush_cs (boolean is_subr) { char *p; byte *r, *return_cs = NULL; cs_entry *tab, *end_tab, *ptr; char *start_line, *line_end; int count, size_pos; unsigned short cr, cs_len = 0; /* to avoid warning about uninitialized use of cs_len */ if (is_subr) { start_line = subr_array_start; line_end = subr_array_end; size_pos = subr_size_pos; tab = subr_tab; count = subr_max + 1; end_tab = subr_tab + count; } else { start_line = cs_dict_start; line_end = cs_dict_end; size_pos = cs_size_pos; tab = cs_tab; end_tab = cs_ptr; count = cs_count; } t1_line_ptr = t1_line_array; for (p = start_line; p - start_line < size_pos;) *t1_line_ptr++ = *p++; while (isdigit (*p)) p++; sprintf (t1_line_ptr, "%u", count); strcat (t1_line_ptr, p); t1_line_ptr = eol (t1_line_array); t1_putline (); /* create return_cs to replace unsused subr's */ if (is_subr) { cr = 4330; cs_len = 0; return_cs = xtalloc (t1_lenIV + 1, byte); if (t1_lenIV > 0) { for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++) *r = cencrypt (0x00, &cr); *r = cencrypt (CS_RETURN, &cr); } else { *return_cs = CS_RETURN; } cs_len++; } for (ptr = tab; ptr < end_tab; ptr++) { if (ptr->used) { if (is_subr) sprintf (t1_line_array, "dup %i %u", (int) (ptr - tab), ptr->cslen); else sprintf (t1_line_array, "/%s %u", ptr->name, ptr->cslen); p = strend (t1_line_array); memcpy (p, ptr->data, ptr->len); t1_line_ptr = p + ptr->len; t1_putline (); } else { /* replace unsused subr's by return_cs */ if (is_subr) { sprintf (t1_line_array, "dup %i %u%s ", (int) (ptr - tab), cs_len, cs_token_pair[0]); p = strend (t1_line_array); memcpy (p, return_cs, cs_len); t1_line_ptr = p + cs_len; t1_putline (); sprintf (t1_line_array, " %s", cs_token_pair[1]); t1_line_ptr = eol (t1_line_array); t1_putline (); } } xfree (ptr->data); if (ptr->name != notdef) xfree (ptr->name); } sprintf (t1_line_array, "%s", line_end); t1_line_ptr = eol (t1_line_array); t1_putline (); if (is_subr) xfree (return_cs); xfree (tab); xfree (start_line); xfree (line_end); } static void t1_mark_glyphs (int tex_font) { int i; char *charset = extra_charset (); char *g, *s, *r; cs_entry *ptr; if (t1_synthetic || embed_all_glyphs (tex_font)) { /* mark everything */ if (cs_tab != NULL) for (ptr = cs_tab; ptr < cs_ptr; ptr++) if (ptr->valid) ptr->used = true; if (subr_tab != NULL) { for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++) if (ptr->valid) ptr->used = true; subr_max = subr_size - 1; } return; } mark_cs (notdef); for (i = 0; i < 256; i++) if (is_used_char (i)) { if (t1_glyph_names[i] == notdef) pdftex_warn ("character %i is mapped to %s", i, notdef); else mark_cs (t1_glyph_names[i]); } if (charset == NULL) goto set_subr_max; g = s = charset + 1; /* skip the first '/' */ r = strend (g); while (g < r) { while (*s != '/' && s < r) s++; *s = 0; /* terminate g by rewriting '/' to 0 */ mark_cs (g); g = s + 1; } set_subr_max: if (subr_tab != NULL) for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++) if (ptr->used && ptr - subr_tab > subr_max) subr_max = ptr - subr_tab; } static void t1_subset_charstrings (int tex_font) { cs_entry *ptr; cs_size_pos = strstr (t1_line_array, charstringname) + strlen (charstringname) - t1_line_array + 1; /* cs_size_pos points to the number indicating dict size after "/CharStrings" */ cs_size = t1_scan_num (t1_line_array + cs_size_pos, 0); cs_ptr = cs_tab = xtalloc (cs_size, cs_entry); for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++) init_cs_entry (ptr); cs_notdef = NULL; cs_dict_start = xstrdup (t1_line_array); t1_getline (); while (t1_cslen) { store_cs (); t1_getline (); } cs_dict_end = xstrdup (t1_line_array); t1_mark_glyphs (tex_font); if (subr_tab != NULL) { if (cs_token_pair == NULL) pdftex_fail ("This Type 1 font uses mismatched subroutine begin/end token pairs."); t1_subr_flush (); } for (cs_count = 0, ptr = cs_tab; ptr < cs_ptr; ptr++) if (ptr->used) cs_count++; t1_cs_flush (); } static void t1_subset_end (fm_entry *fm_cur) { if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */ while (!strstr (t1_line_array, "definefont")) { t1_getline (); t1_putline (); } while (!t1_end_eexec ()) t1_getline (); /* ignore the rest */ t1_putline (); /* write "mark currentfile closefile" */ } else while (!t1_end_eexec ()) { /* copy to "mark currentfile closefile" */ t1_getline (); t1_putline (); } t1_stop_eexec (fm_cur); if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */ while (!t1_cleartomark ()) { t1_getline (); t1_putline (); } if (!t1_synthetic) /* don't check "{restore}if" for synthetic fonts */ t1_check_end (); /* write "{restore}if" if found */ } get_length3 (); } int t1_updatefm (int f, fm_entry *fm) { char *s, *p; read_encoding_only = true; if (!t1_open_fontfile (fm,NULL)) { return 0; } t1_scan_only (f, fm); s = xstrdup(fontname_buf); for (p=s;*p != ' ' && *p != 0; p++); *p=0; fm->ps_name = s; t1_close_font_file (""); return 1; } void writet1 (int tex_font, fm_entry *fm_cur) { read_encoding_only = false; if (!is_included (fm_cur)) { /* scan parameters from font file */ if (!t1_open_fontfile (fm_cur,"{")) return; t1_scan_only (tex_font, fm_cur); t1_close_font_file ("}"); return; } if (!is_subsetted (fm_cur)) { /* include entire font */ if (!t1_open_fontfile (fm_cur,"<<")) return; t1_include (tex_font,fm_cur); t1_close_font_file (">>"); return; } /* partial downloading */ if (!t1_open_fontfile (fm_cur,"<")) return; t1_subset_ascii_part (tex_font,fm_cur); t1_start_eexec (fm_cur); cc_init (); cs_init (); t1_read_subrs (tex_font, fm_cur); t1_subset_charstrings (tex_font); t1_subset_end (fm_cur); t1_close_font_file (">"); } void t1_free () { xfree (t1_line_array); xfree (t1_buf_array); }