remove old description text
[PyX/mjg.git] / pyx / t1strip / writet1.c
blobff74701b8d26598276158853e5eae249e6b77bdc
1 /*
2 Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
4 This file is part of pdfTeX.
5 It was adapted for the use in PyX by André Wobst.
7 pdfTeX is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 pdfTeX is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with pdfTeX; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "pyxadapt.h" /* PyX */
24 #ifdef pdfTeX /* writet1 used with pdfTeX */
25 #include "ptexlib.h"
26 #define t1_log(s) tex_printf(s)
27 #define t1_open() \
28 open_input(&t1_file, kpse_type1_format, FOPEN_RBIN_MODE)
29 #define enc_open() \
30 open_input(&enc_file, kpse_tex_ps_header_format, FOPEN_RBIN_MODE)
31 #define external_enc() enc_tab[fm_cur->encoding].glyph_names
32 #define full_file_name() (char*)nameoffile + 1
33 #define get_length1() t1_length1 = t1_offset() - t1_save_offset
34 #define get_length2() t1_length2 = t1_offset() - t1_save_offset
35 #define get_length3() t1_length3 = t1_offset() - t1_save_offset
36 #define is_used_char(c) pdfcharmarked(tex_font, c)
37 #define t1_putchar ff_putchar
38 #define t1_offset ff_offset
39 #define out_eexec_char t1_putchar
40 #define save_offset() t1_save_offset = t1_offset()
41 #define end_last_eexec_line() \
42 t1_eexec_encrypt = false
43 #define update_builtin_enc(font, glyph_names) update_enc(font, glyph_names)
44 #define t1_char(c) c
45 #define embed_all_glyphs(tex_font) fm_cur->all_glyphs
46 #define extra_charset() fm_cur->charset
47 integer t1_length1, t1_length2, t1_length3;
48 static integer t1_save_offset;
49 static integer t1_fontname_offset;
51 #else /* writet1 used with dvips */
52 /* #include "ptexmac.h" PyX */
53 /* #include "dvips.h" PyX */
54 #undef fm_extend
55 #define fm_extend(f) 0
56 #undef fm_slant
57 #define fm_slant(f) 0
58 #undef is_reencoded
59 #define is_reencoded(f) (cur_enc_name != 0)
60 #undef is_subsetted
61 #define is_subsetted(f) true
62 #undef is_included
63 #define is_included(f) true
64 #undef set_cur_file_name
65 #define set_cur_file_name(s) cur_file_name = s
66 #define t1_open() \
67 ((t1_file = search(headerpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
68 #define enc_open() \
69 ((enc_file = search(headerpath, cur_file_name, FOPEN_RBIN_MODE)) != NULL)
70 #define external_enc() ext_glyph_names
71 #define full_file_name() cur_file_name
72 #define get_length1()
73 #define get_length2()
74 #define get_length3()
75 #define is_used_char(c) (grid[c] == 1)
76 #define out_eexec_char t1_outhex
77 #define save_offset()
78 #define end_last_eexec_line() \
79 hexline_length = HEXLINE_WIDTH; \
80 end_hexline(); \
81 t1_eexec_encrypt = false
82 #define t1_log(s)
83 #define t1_scan_only()
84 #define t1_include()
85 #define t1_putchar(c) fputc(c, bitfile)
86 #define t1_scan_keys()
87 #define update_builtin_enc(font, glyph_names)
88 #define embed_all_glyphs(tex_font) false
89 #undef pdfmovechars
90 #ifdef SHIFTLOWCHARS
91 #define t1_char(c) T1Char(c)
92 #define pdfmovechars 1
93 #else /* SHIFTLOWCHARS */
94 #define t1_char(c) c
95 #define pdfmovechars 0
96 #endif /* SHIFTLOWCHARS */
97 #define extra_charset() dvips_extra_charset
98 #define make_subset_tag(a, b)
99 static char *dvips_extra_charset ;
100 extern FILE *bitfile ;
101 /* extern FILE *search(); PyX */
102 static char *cur_file_name;
103 static char *cur_enc_name;
104 static unsigned char *grid;
105 static char *ext_glyph_names[MAX_CHAR_CODE + 1];
106 static char print_buf[PRINTF_BUF_SIZE];
107 static int hexline_length;
108 static char notdef[] = ".notdef";
109 #endif /* pdfTeX */
111 /* #include <kpathsea/c-vararg.h> PyX */
112 /* #include <kpathsea/c-proto.h> PyX */
114 #define t1_getchar() getc(t1_file)
115 #define t1_ungetchar(c) ungetc(c, t1_file)
116 #define t1_eof() feof(t1_file)
117 #define t1_close() xfclose(t1_file, cur_file_name)
119 #define enc_getchar() getc(enc_file)
120 #define enc_eof() feof(enc_file)
121 #define enc_close() xfclose(enc_file, cur_file_name)
123 #define valid_code(c) (c >= 0 && c <= MAX_CHAR_CODE)
125 static const char *standard_glyph_names[MAX_CHAR_CODE + 1] = {
126 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
127 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
128 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
129 notdef, notdef, notdef, notdef, notdef, "space", "exclam", "quotedbl",
130 "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft",
131 "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
132 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
133 "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at",
134 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
135 "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
136 "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a",
137 "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
138 "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
139 "braceright", "asciitilde", notdef, notdef, notdef, notdef, notdef, notdef,
140 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
141 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
142 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
143 notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
144 "section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
145 "guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash", "dagger",
146 "daggerdbl", "periodcentered", notdef, "paragraph", "bullet",
147 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
148 "ellipsis", "perthousand", notdef, "questiondown", notdef, "grave", "acute",
149 "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", notdef,
150 "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash",
151 notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
152 notdef, notdef, notdef, notdef, notdef, notdef, notdef, "AE", notdef,
153 "ordfeminine", notdef, notdef, notdef, notdef, "Lslash", "Oslash", "OE",
154 "ordmasculine", notdef, notdef, notdef, notdef, notdef, "ae", notdef, notdef,
155 notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe", "germandbls",
156 notdef, notdef, notdef, notdef
159 char **t1_glyph_names;
160 char *t1_builtin_glyph_names[MAX_CHAR_CODE + 1];
161 static boolean read_encoding_only;
162 static int t1_encoding;
165 typedef char *extra_glyphs_entry;
166 static char **extra_glyphs_ptr, **extra_glyphs_tab;
167 static int extra_glyphs_max;
170 #define T1_BUF_SIZE 0x4000
171 #define ENC_BUF_SIZE 1024
173 #define ENC_STANDARD 0
174 #define ENC_BUILTIN 1
176 #define CS_HSTEM 1
177 #define CS_VSTEM 3
178 #define CS_VMOVETO 4
179 #define CS_RLINETO 5
180 #define CS_HLINETO 6
181 #define CS_VLINETO 7
182 #define CS_RRCURVETO 8
183 #define CS_CLOSEPATH 9
184 #define CS_CALLSUBR 10
185 #define CS_RETURN 11
186 #define CS_ESCAPE 12
187 #define CS_HSBW 13
188 #define CS_ENDCHAR 14
189 #define CS_RMOVETO 21
190 #define CS_HMOVETO 22
191 #define CS_VHCURVETO 30
192 #define CS_HVCURVETO 31
193 #define CS_1BYTE_MAX (CS_HVCURVETO + 1)
195 #define CS_DOTSECTION CS_1BYTE_MAX + 0
196 #define CS_VSTEM3 CS_1BYTE_MAX + 1
197 #define CS_HSTEM3 CS_1BYTE_MAX + 2
198 #define CS_SEAC CS_1BYTE_MAX + 6
199 #define CS_SBW CS_1BYTE_MAX + 7
200 #define CS_DIV CS_1BYTE_MAX + 12
201 #define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16
202 #define CS_POP CS_1BYTE_MAX + 17
203 #define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33
204 #define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1)
205 #define CS_MAX CS_2BYTE_MAX
207 typedef unsigned char byte;
209 typedef struct {
210 byte nargs; /* number of arguments */
211 boolean bottom; /* take arguments from bottom of stack? */
212 boolean clear; /* clear stack? */
213 boolean valid;
214 } cc_entry; /* CharString Command */
216 typedef struct {
217 char *name; /* glyph name (or notdef for Subrs entry) */
218 byte *data;
219 unsigned short len; /* length of the whole string */
220 unsigned short cslen; /* length of the encoded part of the string */
221 boolean used;
222 boolean valid;
223 } cs_entry;
225 static unsigned short t1_dr, t1_er;
226 static unsigned short t1_c1 = 52845, t1_c2 = 22719;
227 static unsigned short t1_cslen;
228 static short t1_lenIV;
229 static char t1_line[T1_BUF_SIZE], t1_buf[T1_BUF_SIZE], *t1_line_ptr;
230 static char enc_line[ENC_BUF_SIZE];
232 static char *cs_start;
234 static cs_entry *cs_tab, *cs_ptr, *cs_notdef;
235 static char *cs_dict_start, *cs_dict_end;
236 static int cs_count, cs_size, cs_size_pos;
238 static cs_entry *subr_tab;
239 static char *subr_array_start, *subr_array_end;
240 static int subr_max, subr_size, subr_size_pos;
242 /* This array contains the begin/end tokens commonly used in the */
243 /* /Subrs array of a Type 1 font. */
244 static const char *cs_token_pairs[4][2] = {
245 {"RD", "NP"},
246 {"-|", "|"},
247 {"RD", "noaccess put"},
248 {"-|", "noaccess put"}
251 /* Which begin/end token set do we use for the font? */
252 static int cs_token_choice = -1;
253 static boolean cs_tokens_found = false;
255 static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
256 static int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
257 static long t1_block_length;
258 static int last_hexbyte;
259 static FILE *t1_file;
260 static FILE *enc_file;
262 #define str_prefix(s1, s2) (strncmp(s1, s2, strlen(s2)) == 0)
263 #define t1_prefix(s) str_prefix(t1_line, s)
264 #define t1_buf_prefix(s) str_prefix(t1_buf, s)
265 #define t1_charstrings() strstr(t1_line, "/CharStrings")
266 #define t1_subrs() t1_prefix("/Subrs")
267 #define t1_end_eexec() t1_suffix("mark currentfile closefile")
268 #define t1_cleartomark() t1_prefix("cleartomark")
270 #ifndef pdfTeX
271 static void pdftex_fail(char *fmt,...)
273 va_list args;
274 va_start(args, fmt);
275 fputs("\nError: module writet1", stderr);
276 if (cur_file_name)
277 fprintf(stderr, " (file %s)", cur_file_name);
278 fputs(": ", stderr);
279 vsprintf(print_buf, fmt, args);
280 fputs(print_buf, stderr);
281 fputs("\n ==> Fatal error occurred, the output PDF file is not finished!\n", stderr);
282 va_end(args);
283 exit(-1);
286 static void pdftex_warn(char *fmt,...)
288 va_list args;
289 va_start(args, fmt);
290 fputs("\nWarning: module writet1 of dvips", stderr);
291 if (cur_file_name)
292 fprintf(stderr, " (file %s)", cur_file_name);
293 fputs(": ", stderr);
294 vsprintf(print_buf, fmt, args);
295 fputs(print_buf, stderr);
296 fputs("\n", stderr);
297 va_end(args);
300 #define HEXLINE_WIDTH 64
302 static void end_hexline()
304 if (hexline_length == HEXLINE_WIDTH) {
305 fputs("\n", bitfile);
306 hexline_length = 0;
310 static void t1_outhex(byte b)
312 static char *hexdigits = "0123456789ABCDEF";
313 t1_putchar(hexdigits[b/16]);
314 t1_putchar(hexdigits[b%16]);
315 hexline_length += 2;
316 end_hexline();
318 #endif /* pdfTeX */
321 static void enc_getline(void)
323 char *p;
324 int c;
325 restart:
326 if (enc_eof())
327 pdftex_fail("unexpected end of file");
328 p = enc_line;
329 do {
330 c = enc_getchar();
331 append_char_to_buf(c, p, enc_line, ENC_BUF_SIZE);
332 } while (c != 10);
333 append_eol(p, enc_line, ENC_BUF_SIZE);
334 if (p - enc_line <= 2 || *enc_line == '%')
335 goto restart;
338 void load_enc(char *enc_name, char **glyph_names)
340 char buf[ENC_BUF_SIZE], *p, *r;
341 int names_count;
342 set_cur_file_name(enc_name);
343 if (!enc_open()) {
344 pdftex_warn("cannot open encoding file for reading");
345 cur_file_name = 0;
346 return;
348 t1_log("{");
349 t1_log(cur_file_name = full_file_name());
350 enc_getline();
351 if (*enc_line != '/' || (r = strchr(enc_line, '[')) == NULL) {
352 remove_eol(r, enc_line);
353 pdftex_fail("invalid encoding vector (a name or `[' missing): `%s'", enc_line);
355 names_count = 0;
356 r++; /* skip '[' */
357 skip(r, ' ');
358 for (;;) {
359 while (*r == '/') {
360 for (p = buf, r++; *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
361 *p = 0;
362 skip(r, ' ');
363 if (names_count > MAX_CHAR_CODE)
364 pdftex_fail("encoding vector contains more than %i names",
365 (int)(MAX_CHAR_CODE + 1));
366 if (strcmp(buf, notdef) != 0)
367 glyph_names[names_count] = xstrdup(buf);
368 names_count++;
370 if (*r != 10 && *r != '%') {
371 if (strncmp(r, "] def", strlen("] def")) == 0)
372 goto done;
373 else {
374 remove_eol(r, enc_line);
375 pdftex_fail("invalid encoding vector: a name or `] def' expected: `%s'", enc_line);
378 enc_getline();
379 r = enc_line;
381 done:
382 enc_close();
383 t1_log("}");
384 cur_file_name = 0;
387 static void t1_check_pfa(void)
389 int c = t1_getchar();
390 if (c != 128)
391 t1_pfa = true;
392 else
393 t1_pfa = false;
394 t1_ungetchar(c);
397 static int t1_getbyte(void)
399 int c = t1_getchar();
400 if (t1_pfa)
401 return c;
402 if (t1_block_length == 0) {
403 if (c != 128)
404 pdftex_fail("invalid marker");
405 c = t1_getchar();
406 if (c == 3) {
407 while (!t1_eof())
408 t1_getchar();
409 return EOF;
411 t1_block_length = t1_getchar() & 0xff;
412 t1_block_length |= (t1_getchar() & 0xff) << 8;
413 t1_block_length |= (t1_getchar() & 0xff) << 16;
414 t1_block_length |= (t1_getchar() & 0xff) << 24;
415 c = t1_getchar();
417 t1_block_length--;
418 return c;
421 static int hexval(int c)
423 if (c >= 'A' && c <= 'F')
424 return c - 'A' + 10;
425 else if (c >= 'a' && c <= 'f')
426 return c - 'a' + 10;
427 else if (c >= '0' && c <= '9')
428 return c - '0';
429 else
430 return -1;
433 static byte edecrypt(byte cipher)
435 byte plain;
436 if (t1_pfa) {
437 while (cipher == 10 || cipher == 13)
438 cipher = t1_getbyte();
439 last_hexbyte = cipher = (hexval(cipher) << 4) + hexval(t1_getbyte());
441 plain = (cipher^(t1_dr >> 8));
442 t1_dr = (cipher + t1_dr)*t1_c1 + t1_c2;
443 return plain;
446 static byte cdecrypt(byte cipher, unsigned short *cr)
448 byte plain = (cipher^(*cr >> 8));
449 *cr = (cipher + *cr)*t1_c1 + t1_c2;
450 return plain;
453 static byte eencrypt(byte plain)
455 byte cipher = (plain^(t1_er >> 8));
456 t1_er = (cipher + t1_er)*t1_c1 + t1_c2;
457 return cipher;
460 static byte cencrypt(byte plain, unsigned short *cr)
462 byte cipher = (plain^(*cr >> 8));
463 *cr = (cipher + *cr)*t1_c1 + t1_c2;
464 return cipher;
467 static char *eol(char *s)
469 char *p = strend(s);
470 if (p - s > 1 && p[-1] != 10) {
471 *p++ = 10;
472 *p = 0;
474 return p;
477 static float t1_scan_num(char *p, char **r)
479 float f;
480 skip(p, ' ');
481 if (sscanf(p, "%g", &f) != 1) {
482 remove_eol(p, t1_line);
483 pdftex_fail("a number expected: `%s'", t1_line);
485 if (r != 0) {
486 for (; isdigit(*p) || *p == '.' ||
487 *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
488 *r = p;
490 return f;
493 static boolean t1_suffix(const char *s)
495 char *s1 = t1_line_ptr - 1,
496 *s2 = strend(s) - 1;
497 if (*s1 == 10)
498 s1--;
499 while (s1 >= t1_line && s2 >= s) {
500 if (*s1-- != *s2--)
501 return false;
503 return s1 >= t1_line - 1;
506 static boolean t1_buf_suffix(const char *s, char *r)
508 char *s1 = r - 1,
509 *s2 = strend(s) - 1;
510 if (*s1 == 10)
511 s1--;
512 while (s1 >= t1_buf && s2 >= s) {
513 if (*s1-- != *s2--)
514 return false;
516 return s1 >= t1_buf - 1;
519 static void t1_getline(void)
521 int c, l, eexec_scan;
522 char *p;
523 static char eexec_str[] = "currentfile eexec";
524 static int eexec_len = 17; /* strlen(eexec_str) */
525 restart:
526 if (t1_eof())
527 pdftex_fail("unexpected end of file");
528 t1_line_ptr = t1_line;
529 t1_cslen = 0;
530 eexec_scan = 0;
531 c = t1_getbyte();
532 if (c == EOF)
533 return;
534 while (!t1_eof()) {
535 if (t1_in_eexec == 1)
536 c = edecrypt(c);
537 append_char_to_buf(c, t1_line_ptr, t1_line, T1_BUF_SIZE);
538 if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
539 if (t1_line[eexec_scan] == eexec_str[eexec_scan])
540 eexec_scan++;
541 else
542 eexec_scan = -1;
544 if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32))
545 break;
546 if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line > 4) &&
547 (t1_suffix(" RD ") || t1_suffix(" -| "))) {
548 p = t1_line_ptr - 5;
549 while (*p != ' ')
550 p--;
551 t1_cslen = l = t1_scan_num(p + 1, 0);
552 cs_start = t1_line_ptr;
553 check_buf(t1_line_ptr - t1_line + l, T1_BUF_SIZE);
554 while (l-- > 0)
555 *t1_line_ptr++ = edecrypt(t1_getbyte());
557 c = t1_getbyte();
559 append_eol(t1_line_ptr, t1_line, T1_BUF_SIZE);
560 if (t1_line_ptr - t1_line <= 1)
561 goto restart;
562 if (eexec_scan == eexec_len)
563 t1_in_eexec = 1;
566 static void t1_putline(void)
568 char *p = t1_line;
569 if (t1_line_ptr - t1_line <= 1)
570 return;
571 if (t1_eexec_encrypt) {
572 while (p < t1_line_ptr)
573 out_eexec_char(eencrypt(*p++));
575 else
576 while (p < t1_line_ptr)
577 t1_putchar(*p++);
580 static void t1_puts(const char *s)
582 if (s != t1_line)
583 strcpy(t1_line, s);
584 t1_line_ptr = strend(t1_line);
585 t1_putline();
588 static void t1_printf(const char *fmt,...)
590 va_list args;
591 va_start(args, fmt);
592 vsprintf(t1_line, fmt, args);
593 t1_puts(t1_line);
594 va_end(args);
597 static void t1_init_params(const char *open_name_prefix)
599 t1_log(open_name_prefix);
600 t1_log(cur_file_name);
601 t1_lenIV = 4;
602 t1_dr = 55665;
603 t1_er = 55665;
604 t1_in_eexec = 0;
605 t1_cs = false;
606 t1_scan = true;
607 t1_synthetic = false;
608 t1_eexec_encrypt = false;
609 t1_block_length = 0;
610 t1_check_pfa();
613 static void t1_close_font_file(const char *close_name_suffix)
615 t1_log(close_name_suffix);
616 t1_close();
617 cur_file_name = 0;
620 static void t1_check_block_len(boolean decrypt)
622 int l, c;
623 if (t1_block_length == 0)
624 return;
625 c = t1_getbyte();
626 if (decrypt)
627 c = edecrypt(c);
628 l = t1_block_length;
629 if (!(l == 0 && (c == 10 || c == 13))) {
630 pdftex_warn("%i bytes more than expected were ignored", l + 1);
631 while (l-- > 0)
632 t1_getbyte();
636 static void t1_start_eexec(void)
638 int i;
639 if (is_included(fm_cur)) {
640 get_length1();
641 save_offset();
643 if (!t1_pfa)
644 t1_check_block_len(false);
645 for (t1_line_ptr = t1_line, i = 0; i < 4; i++) {
646 edecrypt(t1_getbyte());
647 *t1_line_ptr++ = 0;
649 t1_eexec_encrypt = true;
650 if (is_included(fm_cur))
651 t1_putline(); /* to put the first four bytes */
654 static void t1_stop_eexec(void)
656 int c;
657 if (is_included(fm_cur)) {
658 get_length2();
659 save_offset();
661 end_last_eexec_line();
662 if (!t1_pfa)
663 t1_check_block_len(true);
664 else {
665 c = edecrypt(t1_getbyte());
666 if (!(c == 10 || c == 13)) {
667 if (last_hexbyte == 0)
668 t1_puts("00");
669 else
670 pdftex_warn("unexpected data after eexec");
673 t1_cs = false;
674 t1_in_eexec = 2;
677 #ifdef pdfTeX
678 static void t1_modify_fm(void)
681 * font matrix is given as six numbers a0..a5, which stands for the matrix
683 * a0 a1 0
684 * M = a2 a3 0
685 * a4 a5 1
687 * ExtendFont is given as
689 * e 0 0
690 * E = 0 1 0
691 * 0 0 1
693 * SlantFont is given as
695 * 1 0 0
696 * S = s 1 0
697 * 0 0 1
699 * and the final transformation is
701 * e*a0 e*a1 0
702 * F = E.S.M = s*e*a0+a2 s*e*a1+a3 0
703 * a4 a5 1
705 float e, s, a[6], b[6];
706 int i, c;
707 char *p, *q, *r;
708 if ((p = strchr(t1_line, '[')) == 0)
709 if ((p = strchr(t1_line, '{')) == 0) {
710 remove_eol(p, t1_line);
711 pdftex_fail("FontMatrix: an array expected: `%s'", t1_line);
713 c = *p++; /* save the character '[' resp. '{' */
714 strncpy(t1_buf, t1_line, (unsigned)(p - t1_line));
715 r = t1_buf + (p - t1_line);
716 for (i = 0; i < 6; i++) {
717 a[i] = t1_scan_num(p, &q);
718 p = q;
720 if (fm_extend(fm_cur) != 0)
721 e = fm_extend(fm_cur)*1E-3;
722 else
723 e = 1;
724 s = fm_slant(fm_cur)*1E-3;
725 b[0] = e*a[0];
726 b[1] = e*a[1];
727 b[2] = s*e*a[0] + a[2];
728 b[3] = s*e*a[1] + a[3];
729 b[4] = a[4];
730 b[5] = a[5];
731 for (i = 0; i < 6; i++) {
732 sprintf(r, "%G ", b[i]);
733 r = strend(r);
735 if (c == '[') {
736 while (*p != ']' && *p != 0)
737 p++;
739 else {
740 while (*p != '}' && *p != 0)
741 p++;
743 if (*p == 0) {
744 remove_eol(p, t1_line);
745 pdftex_fail("FontMatrix: cannot find the corresponding character to '%c': `%s'", c, t1_line);
747 strcpy(r, p);
748 strcpy(t1_line, t1_buf);
749 t1_line_ptr = eol(t1_line);
752 static void t1_modify_italic(void)
754 float a;
755 char *p, *r;
756 if (fm_slant(fm_cur) == 0)
757 return;
758 p = strchr(t1_line, ' ');
759 strncpy(t1_buf, t1_line, (unsigned)(p - t1_line + 1));
760 a = t1_scan_num(p + 1, &r);
761 a -= atan(fm_slant(fm_cur)*1E-3)*(180/M_PI);
762 sprintf(t1_buf + (p - t1_line + 1), "%.2g", a);
763 strcpy(strend(t1_buf), r);
764 strcpy(t1_line, t1_buf);
765 t1_line_ptr = eol(t1_line);
766 font_keys[ITALIC_ANGLE_CODE].value.num = round(a);
767 font_keys[ITALIC_ANGLE_CODE].valid = true;
770 static void t1_scan_keys(void)
772 int i, k;
773 char *p, *q, *r;
774 key_entry *key;
775 if (fm_extend(fm_cur) != 0 || fm_slant(fm_cur) != 0) {
776 if (strncmp(t1_line + 1, "FontMatrix", strlen("FontMatrix")) == 0) {
777 t1_modify_fm();
778 return;
780 if (strncmp(t1_line + 1, "ItalicAngle", strlen("ItalicAngle")) == 0) {
781 t1_modify_italic();
782 return;
785 for (key = font_keys; key - font_keys < MAX_KEY_CODE; key++)
786 if (strncmp(t1_line + 1, key->t1name, strlen(key->t1name)) == 0)
787 break;
788 if (key - font_keys == MAX_KEY_CODE)
789 return;
790 key->valid = true;
791 p = t1_line + strlen(key->t1name) + 1;
792 skip(p, ' ');
793 if ((k = key - font_keys) == FONTNAME_CODE) {
794 if (*p != '/') {
795 remove_eol(p, t1_line);
796 pdftex_fail("a name expected: `%s'", t1_line);
798 r = ++p; /* skip the slash */
799 for (q = t1_buf; *p != ' ' && *p != 10; *q++ = *p++);
800 *q = 0;
801 if (fm_extend(fm_cur) != 0) {
802 sprintf(q, "-Extend_%i", (int)fm_extend(fm_cur));
804 if (fm_slant(fm_cur) != 0) {
805 sprintf(q, "-Slant_%i", (int)fm_slant(fm_cur));
807 key->value.string = xstrdup(t1_buf);
808 if (is_included(fm_cur) && is_subsetted(fm_cur)) {
809 t1_fontname_offset = ff_offset() + (r - t1_line);
810 strcpy(t1_buf, p);
811 sprintf(r, "******+%s%s", key->value.string, t1_buf);
812 t1_line_ptr = eol(r);
814 return;
816 if ((k == STEMV_CODE || k == FONTBBOX1_CODE) &&
817 (*p == '[' || *p == '{'))
818 p++;
819 if (k == FONTBBOX1_CODE) {
820 for (i = 0; i < 4; i++) {
821 key[i].value.num = t1_scan_num(p, &r);
822 p = r;
824 return;
826 key->value.num = t1_scan_num(p, 0);
829 #endif /* pdfTeX */
831 static void t1_scan_param(void)
833 static const char *lenIV = "/lenIV";
834 if (!t1_scan || *t1_line != '/')
835 return;
836 if (t1_prefix(lenIV)) {
837 t1_lenIV = t1_scan_num(t1_line + strlen(lenIV), 0);
838 return;
840 t1_scan_keys();
843 static void copy_glyph_names(char **glyph_names, int a, int b)
845 if (glyph_names[b] != notdef) {
846 free(glyph_names[b]);
847 glyph_names[b] = xstrdup(notdef);
849 if (glyph_names[a] != notdef) {
850 glyph_names[b] = xstrdup(glyph_names[a]);
854 static void t1_builtin_enc(void)
856 int i, a, b, c, counter = 0;
857 char *r, *p;
859 * At this moment "/Encoding" is the prefix of t1_line
861 if (t1_suffix("def")) { /* predefined encoding */
862 sscanf(t1_line + strlen("/Encoding"), "%256s", t1_buf);
863 if (strcmp(t1_buf, "StandardEncoding") == 0) {
864 for (i = 0; i <= MAX_CHAR_CODE; i++)
865 if (standard_glyph_names[i] == notdef)
866 t1_builtin_glyph_names[i] = xstrdup(notdef);
867 else
868 t1_builtin_glyph_names[i] = xstrdup(standard_glyph_names[i]);
869 t1_encoding = ENC_STANDARD;
871 else
872 pdftex_fail("cannot subset font (unknown predefined encoding `%s')",
873 t1_buf);
874 return;
876 t1_encoding = ENC_BUILTIN;
878 * At this moment "/Encoding" is the prefix of t1_line, and the encoding is
879 * not a predefined encoding
881 * We have two possible forms of Encoding vector. The first case is
883 * /Encoding [/a /b /c...] readonly def
885 * and the second case can look like
887 * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
888 * dup 0 /x put
889 * dup 1 /y put
890 * ...
891 * readonly def
893 for (i = 0; i <= MAX_CHAR_CODE; i++)
894 t1_builtin_glyph_names[i] = xstrdup(notdef);
895 if (t1_prefix("/Encoding [") || t1_prefix("/Encoding[")) { /* the first case */
896 r = strchr(t1_line, '[') + 1;
897 skip(r, ' ');
898 for(;;) {
899 while (*r == '/') {
900 for (p = t1_buf, r++;
901 *r != 32 && *r != 10 && *r != ']' && *r != '/';
902 *p++ = *r++);
903 *p = 0;
904 skip(r, ' ');
905 if (counter > MAX_CHAR_CODE)
906 pdftex_fail("encoding vector contains more than %i names",
907 (int)(MAX_CHAR_CODE + 1));
908 if (strcmp(t1_buf, notdef) != 0)
909 t1_builtin_glyph_names[counter] = xstrdup(t1_buf);
910 counter++;
912 if (*r != 10 && *r != '%') {
913 if (str_prefix(r, "] def") || str_prefix(r, "] readonly def"))
914 break;
915 else {
916 remove_eol(r, t1_line);
917 pdftex_fail("a name or `] def' or `] readonly def' expected: `%s'",
918 t1_line);
921 t1_getline();
922 r = t1_line;
925 else { /* the second case */
926 p = strchr(t1_line, 10);
927 for (;;) {
928 if (*p == 10) {
929 t1_getline();
930 p = t1_line;
933 check for `dup <index> <glyph> put'
935 if (sscanf(p, "dup %i%256s put", &i, t1_buf) == 2 &&
936 *t1_buf == '/' && valid_code(i)) {
937 if (strcmp(t1_buf + 1, notdef) != 0)
938 t1_builtin_glyph_names[i] = xstrdup(t1_buf + 1);
939 p = strstr(p, " put") + strlen(" put");
940 skip(p, ' ');
943 check for `dup dup <to> exch <from> get put'
945 else if (sscanf(p, "dup dup %i exch %i get put", &b, &a) == 2 &&
946 valid_code(a) && valid_code(b)) {
947 copy_glyph_names(t1_builtin_glyph_names, a, b);
948 p = strstr(p, " get put") + strlen(" get put");
949 skip(p, ' ');
952 check for `dup dup <from> <size> getinterval <to> exch putinterval'
954 else if (sscanf(p, "dup dup %i %i getinterval %i exch putinterval",
955 &a, &c, &b) == 3 &&
956 valid_code(a) && valid_code(b) && valid_code(c)) {
957 for (i = 0; i < c; i++)
958 copy_glyph_names(t1_builtin_glyph_names, a + i, b + i);
959 p = strstr(p, " putinterval") + strlen(" putinterval");
960 skip(p, ' ');
963 check for `def' or `readonly def'
965 else if ((p == t1_line || (p > t1_line && p[-1] == ' ')) &&
966 strcmp(p, "def\n") == 0)
967 return;
969 skip an unrecognizable word
971 else {
972 while (*p != ' ' && *p != 10)
973 p++;
974 skip(p, ' ');
980 static void t1_check_end(void)
982 if (t1_eof())
983 return;
984 t1_getline();
985 if (t1_prefix("{restore}"))
986 t1_putline();
989 #ifdef pdfTeX
990 static boolean t1_open_fontfile(const char *open_name_prefix)
992 char *ex_ffname = 0;
993 if (fm_cur->expansion != 0) {
994 ex_ffname = mk_exname(fm_cur->ff_name, fm_cur->expansion);
995 set_cur_file_name(ex_ffname);
996 if (t1_open()) { /* found mm instance */
997 cur_file_name = full_file_name();
998 goto open_ok;
1001 if (fm_cur->found)
1002 t1_file = xfopen(cur_file_name = fm_cur->ff_name, FOPEN_RBIN_MODE);
1003 else {
1004 set_cur_file_name(fm_cur->ff_name);
1005 if (!t1_open()) {
1006 pdftex_warn("cannot open Type 1 font file for reading");
1007 return false;
1009 fix_ffname(fm_cur, cur_file_name = full_file_name());
1011 if (fm_cur->expansion != 0 && is_included(fm_cur)) { /* use ExtendFont to simulate MM instance */
1012 if (fm_extend(fm_cur) == 0)
1013 fm_extend(fm_cur) = 1000;
1014 fm_extend(fm_cur) =
1015 roundxnoverd(fm_extend(fm_cur), 1000 + fm_cur->expansion, 1000);
1017 open_ok:
1018 t1_init_params(open_name_prefix);
1019 fontfile_found = true;
1020 xfree(ex_ffname);
1021 return true;
1024 boolean t1_read_enc(fm_entry *fm)
1026 read_encoding_only = true;
1027 fm_cur = fm;
1028 if (!t1_open_fontfile("{"))
1029 return false;
1030 fix_ffname(fm_cur, cur_file_name = full_file_name());
1031 while (!t1_prefix("/Encoding"))
1032 t1_getline();
1033 t1_builtin_enc();
1034 t1_close_font_file("}");
1035 return true;
1038 static void t1_scan_only(void)
1040 do {
1041 t1_getline();
1042 t1_scan_param();
1043 } while (t1_in_eexec == 0);
1044 t1_start_eexec();
1045 do {
1046 t1_getline();
1047 t1_scan_param();
1048 } while (!(t1_charstrings() || t1_subrs()));
1051 static void t1_include(void)
1053 save_offset();
1054 do {
1055 t1_getline();
1056 t1_scan_param();
1057 t1_putline();
1058 } while (t1_in_eexec == 0);
1059 t1_start_eexec();
1060 do {
1061 t1_getline();
1062 t1_scan_param();
1063 t1_putline();
1064 } while (!(t1_charstrings() || t1_subrs()));
1065 t1_cs = true;
1066 do {
1067 t1_getline();
1068 t1_putline();
1069 } while (!t1_end_eexec());
1070 t1_stop_eexec();
1071 do {
1072 t1_getline();
1073 t1_putline();
1074 } while (!t1_cleartomark());
1075 t1_check_end(); /* write "{restore}if" if found */
1076 get_length3();
1079 #else /* not pdfTeX */
1080 static boolean t1_open_fontfile(char *open_name_prefix)
1082 if (!t1_open())
1083 return false;
1084 t1_init_params(open_name_prefix);
1085 return true;
1087 #endif /* pdfTeX */
1089 #define check_subr(subr) \
1090 if (subr >= subr_size || subr < 0) \
1091 pdftex_fail("Subrs array: entry index out of range (%i)", subr);
1093 static void cs_store(boolean is_subr)
1095 char *p, *q;
1096 cs_entry *ptr;
1097 int subr;
1098 for (p = t1_line, q = t1_buf; *p != ' '; *q++ = *p++);
1099 *q = 0;
1100 if (is_subr) {
1101 subr = t1_scan_num(p + 1, 0);
1102 check_subr(subr);
1103 ptr = subr_tab + subr;
1105 else {
1106 ptr = cs_ptr++;
1107 if (cs_ptr - cs_tab > cs_size)
1108 pdftex_fail("CharStrings dict: more entries than dict size (%i)", cs_size);
1109 if (strcmp(t1_buf + 1, notdef) == 0) /* skip the slash */
1110 ptr->name = xstrdup(notdef);
1111 else
1112 ptr->name = xstrdup(t1_buf + 1);
1114 /* copy " RD " + cs data to t1_buf */
1115 memcpy(t1_buf, cs_start - 4, (unsigned)(t1_cslen + 4));
1116 /* copy the end of cs data to t1_buf */
1117 for (p = cs_start + t1_cslen, q = t1_buf + t1_cslen + 4; *p != 10; *q++ = *p++);
1118 *q++ = 10;
1119 /* get the begin/end token pairs. Modify this as necessary for other token pairs. */
1120 if (is_subr && !cs_tokens_found) {
1121 if (t1_buf_prefix(" RD") && t1_buf_suffix("NP", q))
1122 { cs_token_choice = 0; cs_tokens_found = true; }
1123 else if (t1_buf_prefix(" -|") && t1_buf_suffix("|", q))
1124 { cs_token_choice = 1; cs_tokens_found = true; }
1125 else if (t1_buf_prefix(" RD") && t1_buf_suffix("noaccess put", q))
1126 { cs_token_choice = 2; cs_tokens_found = true; }
1127 else if (t1_buf_prefix(" -|") && t1_buf_suffix("noaccess put", q))
1128 { cs_token_choice = 3; cs_tokens_found = true; }
1130 ptr->len = q - t1_buf;
1131 ptr->cslen = t1_cslen;
1132 ptr->data = xtalloc(ptr->len, byte);
1133 memcpy(ptr->data, t1_buf, ptr->len);
1134 ptr->valid = true;
1137 #define store_subr() cs_store(true)
1138 #define store_cs() cs_store(false)
1140 #define CC_STACK_SIZE 24
1142 static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
1143 static cc_entry cc_tab[CS_MAX];
1144 static boolean is_cc_init = false;
1147 #define cc_pop(N) \
1148 if (stack_ptr - cc_stack < (N)) \
1149 stack_error(N); \
1150 stack_ptr -= N
1152 #define stack_error(N) { \
1153 pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \
1154 N, stack_ptr - cc_stack); \
1155 goto cs_error; \
1159 static integer cc_get(integer index)
1161 if (index < 0) {
1162 if (stack_ptr + index < cc_stack )
1163 stack_error(stack_ptr - cc_stack + index);
1164 return *(stack_ptr + index);
1166 else {
1167 if (cc_stack + index >= stack_ptr)
1168 stack_error(index);
1169 return cc_stack[index];
1174 #define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
1176 #define cc_push(V) *stack_ptr++ = V
1177 #define cc_clear() stack_ptr = cc_stack
1179 #define set_cc(N, B, A, C) \
1180 cc_tab[N].nargs = A; \
1181 cc_tab[N].bottom = B; \
1182 cc_tab[N].clear = C; \
1183 cc_tab[N].valid = true
1185 static void cc_init(void)
1187 int i;
1188 if (is_cc_init)
1189 return;
1190 for (i = 0; i < CS_MAX; i++)
1191 cc_tab[i].valid = false;
1192 set_cc(CS_HSTEM, true, 2, true);
1193 set_cc(CS_VSTEM, true, 2, true);
1194 set_cc(CS_VMOVETO, true, 1, true);
1195 set_cc(CS_RLINETO, true, 2, true);
1196 set_cc(CS_HLINETO, true, 1, true);
1197 set_cc(CS_VLINETO, true, 1, true);
1198 set_cc(CS_RRCURVETO, true, 6, true);
1199 set_cc(CS_CLOSEPATH, false, 0, true);
1200 set_cc(CS_CALLSUBR, false, 1, false);
1201 set_cc(CS_RETURN, false, 0, false);
1203 set_cc(CS_ESCAPE, false, 0, false);
1205 set_cc(CS_HSBW, true, 2, true);
1206 set_cc(CS_ENDCHAR, false, 0, true);
1207 set_cc(CS_RMOVETO, true, 2, true);
1208 set_cc(CS_HMOVETO, true, 1, true);
1209 set_cc(CS_VHCURVETO, true, 4, true);
1210 set_cc(CS_HVCURVETO, true, 4, true);
1211 set_cc(CS_DOTSECTION, false, 0, true);
1212 set_cc(CS_VSTEM3, true, 6, true);
1213 set_cc(CS_HSTEM3, true, 6, true);
1214 set_cc(CS_SEAC, true, 5, true);
1215 set_cc(CS_SBW, true, 4, true);
1216 set_cc(CS_DIV, false, 2, false);
1217 set_cc(CS_CALLOTHERSUBR, false, 0, false);
1218 set_cc(CS_POP, false, 0, false);
1219 set_cc(CS_SETCURRENTPOINT, true, 2, true);
1220 is_cc_init = true;
1223 #define cs_getchar() cdecrypt(*data++, &cr)
1225 #define mark_subr(n) cs_mark(0, n)
1226 #define mark_cs(s) cs_mark(s, 0)
1228 static void cs_warn(const char *cs_name, int subr, const char *fmt,...)
1230 char buf[SMALL_BUF_SIZE];
1231 va_list args;
1232 va_start(args, fmt);
1233 vsprintf(buf, fmt, args);
1234 va_end(args);
1235 if (cs_name == 0)
1236 pdftex_warn("Subr (%i): %s", (int)subr, buf);
1237 else
1238 pdftex_warn("CharString (/%s): %s", cs_name, buf);
1241 static void cs_mark(const char *cs_name, int subr)
1243 byte *data;
1244 int i, b, cs_len;
1245 integer a, a1, a2;
1246 unsigned short cr;
1247 static integer lastargOtherSubr3 = 3; /* the argument of last call to
1248 OtherSubrs[3] */
1249 cs_entry *ptr;
1250 cc_entry *cc;
1251 if (cs_name == 0) {
1252 check_subr(subr);
1253 ptr = subr_tab + subr;
1254 if (!ptr->valid)
1255 return;
1257 else {
1258 if (cs_notdef != 0 &&
1259 (cs_name == notdef || strcmp(cs_name, notdef) == 0))
1260 ptr = cs_notdef;
1261 else {
1262 for (ptr = cs_tab; ptr < cs_ptr; ptr++)
1263 if (strcmp(ptr->name, cs_name) == 0)
1264 break;
1265 if (ptr == cs_ptr) {
1266 pdftex_warn("glyph `%s' undefined", cs_name);
1267 return;
1269 if (ptr->name == notdef)
1270 cs_notdef = ptr;
1273 /* only marked CharString entries and invalid entries can be skipped;
1274 valid marked subrs must be parsed to keep the stack */
1275 if (!ptr->valid || (ptr->used && cs_name != 0))
1276 return;
1277 ptr->used = true;
1278 cr = 4330;
1279 cs_len = ptr->cslen;
1280 data = ptr->data + 4;
1281 for (i = 0; i < t1_lenIV; i++, cs_len--)
1282 cs_getchar();
1283 while (cs_len > 0) {
1284 --cs_len;
1285 b = cs_getchar();
1286 if (b >= 32) {
1287 if (b <= 246)
1288 a = b - 139;
1289 else if (b <= 250) {
1290 --cs_len;
1291 a = ((b - 247) << 8) + 108 + cs_getchar();
1293 else if (b <= 254) {
1294 --cs_len;
1295 a = -((b - 251) << 8) - 108 - cs_getchar();
1297 else {
1298 cs_len -= 4;
1299 a = (cs_getchar() & 0xff) << 24;
1300 a |= (cs_getchar() & 0xff) << 16;
1301 a |= (cs_getchar() & 0xff) << 8;
1302 a |= (cs_getchar() & 0xff) << 0;
1303 if (sizeof(integer) > 4 && (a & 0x80000000))
1304 a |= ~0x7FFFFFFF;
1306 cc_push(a);
1308 else {
1309 if (b == CS_ESCAPE) {
1310 b = cs_getchar() + CS_1BYTE_MAX;
1311 cs_len--;
1313 if (b >= CS_MAX) {
1314 cs_warn(cs_name, subr, "command value out of range: %i", (int)b);
1315 goto cs_error;
1317 cc = cc_tab + b;
1318 if (!cc->valid) {
1319 cs_warn(cs_name, subr, "command not valid: %i", (int)b);
1320 goto cs_error;
1322 if (cc->bottom) {
1323 if (stack_ptr - cc_stack < cc->nargs)
1324 cs_warn(cs_name, subr,
1325 "less arguments on stack (%i) than required (%i)",
1326 (int)(stack_ptr - cc_stack), (int)cc->nargs);
1327 else if (stack_ptr - cc_stack > cc->nargs)
1328 cs_warn(cs_name, subr,
1329 "more arguments on stack (%i) than required (%i)",
1330 (int)(stack_ptr - cc_stack), (int)cc->nargs);
1332 switch (cc - cc_tab) {
1333 case CS_CALLSUBR:
1334 a1 = cc_get(-1);
1335 cc_pop(1);
1336 mark_subr(a1);
1337 if (!subr_tab[a1].valid) {
1338 cs_warn(cs_name, subr,
1339 "cannot call subr (%i)", (int)a1);
1340 goto cs_error;
1342 break;
1343 case CS_DIV:
1344 cc_pop(2);
1345 cc_push(0);
1346 break;
1347 case CS_CALLOTHERSUBR:
1348 if (cc_get(-1) == 3)
1349 lastargOtherSubr3 = cc_get(-3);
1350 a1 = cc_get(-2) + 2;
1351 cc_pop(a1);
1352 break;
1353 case CS_POP:
1354 cc_push(lastargOtherSubr3);
1355 /* the only case when we care about the value being pushed onto
1356 stack is when POP follows CALLOTHERSUBR (changing hints by
1357 OtherSubrs[3])
1359 break;
1360 case CS_SEAC:
1361 a1 = cc_get(3);
1362 a2 = cc_get(4);
1363 cc_clear();
1364 mark_cs(standard_glyph_names[a1]);
1365 mark_cs(standard_glyph_names[a2]);
1366 break;
1367 default:
1368 if (cc->clear)
1369 cc_clear();
1373 return;
1374 cs_error: /* an error occured during parsing */
1375 cc_clear();
1376 ptr->valid = false;
1377 ptr->used = false;
1380 static void t1_subset_ascii_part(void)
1382 int i, j;
1383 save_offset();
1384 t1_getline();
1385 while (!t1_prefix("/Encoding")) {
1386 t1_scan_param();
1387 t1_putline();
1388 t1_getline();
1390 t1_builtin_enc();
1391 if (is_reencoded(fm_cur))
1392 t1_glyph_names = external_enc();
1393 else {
1394 t1_glyph_names = t1_builtin_glyph_names;
1395 update_builtin_enc(tex_font, t1_glyph_names);
1397 if (is_included(fm_cur) && is_subsetted(fm_cur))
1398 make_subset_tag(fm_cur, t1_fontname_offset);
1399 if (pdfmovechars == 0 && t1_encoding == ENC_STANDARD)
1400 t1_puts("/Encoding StandardEncoding def\n");
1401 else {
1402 t1_puts("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
1403 for (i = 0, j = 0; i <= MAX_CHAR_CODE; i++) {
1404 if (is_used_char(i) && t1_glyph_names[i] != notdef) {
1405 j++;
1406 t1_printf("dup %i /%s put\n", (int)t1_char(i), t1_glyph_names[i]);
1409 /* We didn't mark anything for the Encoding array. */
1410 /* We add "dup 0 /.notdef put" for compatibility */
1411 /* with Acrobat 5.0. */
1412 if (j == 0)
1413 t1_puts("dup 0 /.notdef put\n");
1414 t1_puts("readonly def\n");
1416 do {
1417 t1_getline();
1418 t1_scan_param();
1419 t1_putline();
1420 } while (t1_in_eexec == 0);
1423 #define t1_subr_flush() t1_flush_cs(true)
1424 #define t1_cs_flush() t1_flush_cs(false)
1426 static void t1_flush_cs(boolean);
1428 static void cs_init(void)
1430 cs_ptr = cs_tab = 0;
1431 cs_dict_start = cs_dict_end = 0;
1432 cs_count = cs_size = cs_size_pos = 0;
1433 subr_tab = 0;
1434 subr_array_start = subr_array_end = 0;
1435 subr_max = subr_size = subr_size_pos = 0;
1438 static void init_cs_entry(cs_entry *cs)
1440 cs->data = 0;
1441 cs->name = 0;
1442 cs->len = 0;
1443 cs->cslen = 0;
1444 cs->used = false;
1445 cs->valid = false;
1448 static void t1_mark_glyphs(void);
1450 static void t1_read_subrs(void)
1452 int i;
1453 char *s;
1454 cs_entry *ptr;
1455 t1_getline();
1456 while (!(t1_charstrings() || t1_subrs())) {
1457 t1_scan_param();
1458 t1_putline();
1459 t1_getline();
1461 found:
1462 t1_cs = true;
1463 t1_scan = false;
1464 if (!t1_subrs())
1465 return;
1466 subr_size_pos = strlen("/Subrs") + 1;
1467 /* subr_size_pos points to the number indicating dict size after "/Subrs" */
1468 subr_size = t1_scan_num(t1_line + subr_size_pos, 0);
1469 if (subr_size == 0) {
1470 while (!t1_charstrings())
1471 t1_getline();
1472 return;
1474 subr_tab = xtalloc(subr_size, cs_entry);
1475 for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
1476 init_cs_entry(ptr);
1477 subr_array_start = xstrdup(t1_line);
1478 t1_getline();
1479 while (t1_cslen) {
1480 store_subr();
1481 t1_getline();
1483 /* mark the first four entries without parsing */
1484 for (i = 0; i < subr_size && i < 4; i++)
1485 subr_tab[i].used = true;
1486 /* the end of the Subrs array might have more than one line so we need to
1487 concatnate them to subr_array_end. Unfortunately some fonts don't have
1488 the Subrs array followed by the CharStrings dict immediately (synthetic
1489 fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then
1490 we will treat the font as synthetic and ignore everything until next
1491 Subrs is found
1493 #define POST_SUBRS_SCAN 5
1494 s = t1_buf;
1495 *t1_buf = 0;
1496 for (i = 0; i < POST_SUBRS_SCAN; i++) {
1497 if (t1_charstrings())
1498 break;
1499 check_buf((t1_line_ptr - t1_line) + (s - t1_buf), T1_BUF_SIZE);
1500 strcat(t1_buf, t1_line);
1501 s += t1_line_ptr - t1_line;
1502 t1_getline();
1504 subr_array_end = xstrdup(t1_buf);
1505 if (i == POST_SUBRS_SCAN) { /* CharStrings not found;
1506 suppose synthetic font */
1507 for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
1508 if (ptr->valid)
1509 xfree(ptr->data);
1510 xfree(subr_tab);
1511 xfree(subr_array_start);
1512 xfree(subr_array_end);
1513 cs_init();
1514 t1_cs = false;
1515 t1_synthetic = true;
1516 while (!(t1_charstrings() || t1_subrs()))
1517 t1_getline();
1518 goto found;
1522 static void t1_flush_cs(boolean is_subr)
1524 char *p;
1525 byte *r, return_cs[T1_BUF_SIZE];
1526 cs_entry *tab, *end_tab, *ptr;
1527 char *start_line, *line_end;
1528 int count, size_pos;
1529 unsigned short cr, cs_len;
1530 if (is_subr) {
1531 start_line = subr_array_start;
1532 line_end = subr_array_end;
1533 size_pos = subr_size_pos;
1534 tab = subr_tab;
1535 count = subr_max + 1;
1536 end_tab = subr_tab + count;
1538 else {
1539 start_line = cs_dict_start;
1540 line_end = cs_dict_end;
1541 size_pos = cs_size_pos;
1542 tab = cs_tab;
1543 end_tab = cs_ptr;
1544 count = cs_count;
1546 t1_line_ptr = t1_line;
1547 for (p = start_line; p - start_line < size_pos;)
1548 *t1_line_ptr++ = *p++;
1549 while (isdigit(*p))
1550 p++;
1551 sprintf(t1_line_ptr, "%u", count);
1552 strcat(t1_line_ptr, p);
1553 t1_line_ptr = eol(t1_line);
1554 t1_putline();
1556 if (is_subr) {
1557 cr = 4330;
1558 cs_len = 0;
1559 if (t1_lenIV >= 0) {
1560 for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++)
1561 *r = cencrypt(0x00, &cr);
1562 *r = cencrypt(CS_RETURN, &cr);
1564 else {
1565 *return_cs = CS_RETURN;
1567 cs_len++;
1570 for (ptr = tab; ptr < end_tab; ptr++) {
1572 if (ptr->used) {
1573 if (is_subr)
1574 sprintf(t1_line, "dup %u %u", ptr - tab, ptr->cslen);
1575 else
1576 sprintf(t1_line, "/%s %u", ptr->name, ptr->cslen);
1577 p = strend(t1_line);
1578 memcpy(p, ptr->data, ptr->len);
1579 t1_line_ptr = p + ptr->len;
1580 t1_putline();
1582 else {
1583 if (is_subr) {
1584 sprintf(t1_line, "dup %u %u %s ", ptr - tab, cs_len,
1585 cs_token_pairs[cs_token_choice][0]);
1586 p = strend(t1_line);
1587 memcpy(p, return_cs, cs_len);
1588 t1_line_ptr = p + cs_len;
1589 t1_putline();
1590 sprintf(t1_line, " %s", cs_token_pairs[cs_token_choice][1]);
1591 t1_line_ptr = eol(t1_line);
1592 t1_putline();
1595 xfree(ptr->data);
1596 if (ptr->name != 0 && ptr->name != notdef)
1597 xfree(ptr->name);
1599 sprintf(t1_line, "%s", line_end);
1600 t1_line_ptr = eol(t1_line);
1601 t1_putline();
1602 if (is_subr) {
1603 cs_token_choice = -1;
1604 cs_tokens_found = false;
1606 xfree(tab);
1607 xfree(start_line);
1608 xfree(line_end);
1611 static void t1_mark_glyphs(void)
1613 int i;
1614 char *charset = extra_charset();
1615 char *g, *s, *r;
1616 cs_entry *ptr;
1617 if (t1_synthetic || embed_all_glyphs(tex_font)) { /* mark everything */
1618 if (cs_tab != 0)
1619 for (ptr = cs_tab; ptr < cs_ptr; ptr++)
1620 if (ptr->valid)
1621 ptr->used = true;
1622 if (subr_tab != 0) {
1623 for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
1624 if (ptr->valid)
1625 ptr->used = true;
1626 subr_max = subr_size - 1;
1628 return;
1630 mark_cs(notdef);
1631 for (i = 0; i <= MAX_CHAR_CODE; i++)
1632 if (is_used_char(i)) {
1633 if (t1_glyph_names[i] == notdef)
1634 pdftex_warn("character %i is mapped to %s", i, notdef);
1635 else
1636 mark_cs(t1_glyph_names[i]);
1638 if (charset == 0)
1639 goto set_subr_max;
1640 g = s = charset + 1; /* skip the first '/' */
1641 r = strend(g);
1642 while (g < r) {
1643 while (*s != '/' && s < r)
1644 s++;
1645 *s = 0; /* terminate g by rewriting '/' to 0 */
1646 mark_cs(g);
1647 g = s + 1;
1649 set_subr_max:
1650 if (subr_tab != 0)
1651 for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
1652 if (ptr->used && ptr - subr_tab > subr_max)
1653 subr_max = ptr - subr_tab;
1656 static void t1_subset_charstrings(void)
1658 cs_entry *ptr;
1659 cs_size_pos = strstr(t1_line, "/CharStrings") + strlen("/CharStrings")
1660 - t1_line + 1;
1661 /* cs_size_pos points to the number indicating
1662 dict size after "/CharStrings" */
1663 cs_size = t1_scan_num(t1_line + cs_size_pos, 0);
1664 cs_ptr = cs_tab = xtalloc(cs_size, cs_entry);
1665 for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++)
1666 init_cs_entry(ptr);
1667 cs_notdef = 0;
1668 cs_dict_start = xstrdup(t1_line);
1669 t1_getline();
1670 while (t1_cslen) {
1671 store_cs();
1672 t1_getline();
1674 cs_dict_end = xstrdup(t1_line);
1675 t1_mark_glyphs();
1676 if (subr_tab != 0) {
1677 if (cs_token_choice == -1)
1678 pdftex_fail("This Type 1 font uses mismatched subroutine begin/end token pairs.");
1679 t1_subr_flush();
1681 for (cs_count = 0, ptr = cs_tab; ptr < cs_ptr; ptr++)
1682 if (ptr->used)
1683 cs_count++;
1684 t1_cs_flush();
1687 static void t1_subset_end(void)
1689 if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
1690 while (!strstr(t1_line, "definefont")) {
1691 t1_getline();
1692 t1_putline();
1694 while (!t1_end_eexec())
1695 t1_getline(); /* ignore the rest */
1696 t1_putline(); /* write "mark currentfile closefile" */
1698 else while (!t1_end_eexec()) { /* copy to "mark currentfile closefile" */
1699 t1_getline();
1700 t1_putline();
1702 t1_stop_eexec();
1703 while (!t1_cleartomark()) {
1704 t1_getline();
1705 t1_putline();
1707 if (!t1_synthetic) /* don't check "{restore}if" for synthetic fonts */
1708 t1_check_end(); /* write "{restore}if" if found */
1709 get_length3();
1712 void writet1(void)
1714 read_encoding_only = false;
1715 #ifdef pdfTeX
1716 if (strcasecmp(strend(fm_fontfile(fm_cur)) - 4, ".otf") == 0) {
1717 if (!is_included(fm_cur) || is_subsetted(fm_cur))
1718 pdftex_fail("OTF fonts must be included entirely");
1719 writeotf();
1720 is_otf_font = true;
1721 return;
1723 #endif
1724 if (!is_included(fm_cur)) { /* scan parameters from font file */
1725 if (!t1_open_fontfile("{"))
1726 return;
1727 t1_scan_only();
1728 t1_close_font_file("}");
1729 return;
1731 if (!is_subsetted(fm_cur)) { /* include entire font */
1732 if (!t1_open_fontfile("<<"))
1733 return;
1734 t1_include();
1735 t1_close_font_file(">>");
1736 return;
1738 /* partial downloading */
1739 if (!t1_open_fontfile("<"))
1740 return;
1741 t1_subset_ascii_part();
1742 t1_start_eexec();
1743 cc_init();
1744 cs_init();
1745 t1_read_subrs();
1746 t1_subset_charstrings();
1747 t1_subset_end();
1748 t1_close_font_file(">");
1751 #ifndef pdfTeX
1752 boolean t1_subset(char *fontfile, char *encfile, unsigned char *g)
1754 int i;
1755 cur_enc_name = encfile;
1756 for (i = 0; i <= MAX_CHAR_CODE; i++)
1757 ext_glyph_names[i] = notdef;
1758 if (cur_enc_name != 0)
1759 load_enc(cur_enc_name, ext_glyph_names);
1760 grid = g;
1761 cur_file_name = fontfile;
1762 hexline_length = 0;
1763 writet1();
1764 for (i = 0; i <= MAX_CHAR_CODE; i++)
1765 if (ext_glyph_names[i] != notdef)
1766 free(ext_glyph_names[i]);
1767 return 1 ; /* note: there *is* no unsuccessful return */
1769 boolean t1_subset_2(char *fontfile, unsigned char *g, char *extraGlyphs)
1771 int i;
1772 cur_enc_name = 0; /* PyX */
1773 for (i = 0; i <= MAX_CHAR_CODE; i++)
1774 ext_glyph_names[i] = notdef;
1775 grid = g;
1776 cur_file_name = fontfile;
1777 hexline_length = 0;
1778 dvips_extra_charset = extraGlyphs ;
1779 writet1();
1780 for (i = 0; i <= MAX_CHAR_CODE; i++)
1781 if (ext_glyph_names[i] != notdef)
1782 free(ext_glyph_names[i]);
1783 return 1 ; /* note: there *is* no unsuccessful return */
1785 #endif /* not pdfTeX */