[pdftex] writet1, part n for large n

Tom Kacvinsky tjk at ams.org
Tue Jun 26 14:36:56 CEST 2001


OK,

Some testing by Hans Hagen and Tom Kiffe pointed out a bug in the
patch I had submitted.  So here is a new one that fixes the problem.
This time, I am sure the patch works right... :)

Hans' test files points out another bug in Acrobat 5.0.  The problem is
when one uses pdftex to include another PDF file.  The font resources
are scanned over, and sometimes a Type 1 font is written into the PDF
file with an encoding array that looks like this:

/Enoding 256 array
0 1 255 {1 index /.notdef exch put} for
readonly def

Acrobat 5.0 does not like this.  I will try to come up with a fix this
weekend.

Tom
-------------- next part --------------
--- writet1.c	2001/06/15 22:54:57	1.1
+++ writet1.c	2001/06/22 14:40:39	1.7
@@ -199,7 +199,8 @@
 
 static unsigned short t1_dr, t1_er;
 static unsigned short t1_c1 = 52845, t1_c2 = 22719;
-static unsigned short t1_cslen, t1_lenIV;
+static unsigned short t1_cslen;
+static short t1_lenIV;
 static char t1_line[T1_BUF_SIZE], t1_buf[T1_BUF_SIZE], *t1_line_ptr;
 static char enc_line[ENC_BUF_SIZE];
 
@@ -213,6 +214,19 @@
 static char *subr_array_start, *subr_array_end;
 static int subr_max, subr_size, subr_size_pos;
 
+/* This array contains the begin/end tokens commonly used in the */
+/* /Subrs array of a Type 1 font.                                */
+static char *cs_token_pairs[4][2] = {
+  {"RD", "NP"},
+  {"-|", "|"},
+  {"RD", "noaccess put"},
+  {"-|", "noaccess put"}
+};
+
+/* Which begin/end token set do we use for the font? */
+static int     cs_token_choice = -1;
+static boolean cs_tokens_found = false;
+
 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;
@@ -222,6 +236,7 @@
 
 #define str_prefix(s1, s2)  (strncmp(s1, s2, strlen(s2)) == 0)
 #define t1_prefix(s)        str_prefix(t1_line, s)
+#define t1_buf_prefix(s)    str_prefix(t1_buf, s)
 #define t1_charstrings()    strstr(t1_line, "/CharStrings")
 #define t1_subrs()          t1_prefix("/Subrs")
 #define t1_end_eexec()      t1_suffix("mark currentfile closefile")
@@ -417,6 +432,13 @@
     return cipher;
 }
 
+static byte cencrypt(byte plain, unsigned short *cr)
+{
+    byte cipher = (plain^(*cr >> 8));
+    *cr = (cipher + *cr)*t1_c1 + t1_c2;
+    return cipher;
+}
+
 static char *eol(char *s)
 {
     char *p = strend(s);
@@ -456,6 +478,19 @@
     return s1 >= t1_line - 1;
 }
 
+static boolean t1_buf_suffix(char *s, char *r)
+{
+    char *s1 = r - 1,
+         *s2 = strend(s) - 1;
+    if (*s1 == 10)
+        s1--;
+    while (s1 >= t1_buf && s2 >= s) {
+        if (*s1-- != *s2--)
+            return false;
+    }
+    return s1 >= t1_buf - 1;
+}
+
 static void t1_getline(void) 
 {
     int c, l, eexec_scan;
@@ -1055,10 +1090,22 @@
         else
             ptr->name = xstrdup(t1_buf + 1); 
     }
-    memcpy(t1_buf, cs_start - 4, (unsigned)(t1_cslen + 4)); /* copy " RD " + cs data to t1_buf */
-    for (p = cs_start + t1_cslen, q = t1_buf + t1_cslen + 4; *p != 10; *q++ = *p++);
+    /* copy " RD " + cs data to t1_buf */
+    memcpy(t1_buf, cs_start - 4, (unsigned)(t1_cslen + 4));
     /* copy the end of cs data to t1_buf */
-    *q++ = 10; 
+    for (p = cs_start + t1_cslen, q = t1_buf + t1_cslen + 4; *p != 10; *q++ = *p++);
+    *q++ = 10;
+    /* get the begin/end token pairs.  Modify this as necessary for other token pairs. */
+    if (is_subr && !cs_tokens_found) {
+        if (t1_buf_prefix(" RD") && t1_buf_suffix("NP", q))
+            { cs_token_choice = 0; cs_tokens_found = true; }
+        else if (t1_buf_prefix(" -|") && t1_buf_suffix("|", q))
+            { cs_token_choice = 1; cs_tokens_found = true; }
+        else if (t1_buf_prefix(" RD") && t1_buf_suffix("noaccess put", q))
+            { cs_token_choice = 2; cs_tokens_found = true; }
+        else if (t1_buf_prefix(" -|") && t1_buf_suffix("noaccess put", q))
+            { cs_token_choice = 3; cs_tokens_found = true; }
+    }
     ptr->len = q - t1_buf;
     ptr->cslen = t1_cslen;
     ptr->data = xtalloc(ptr->len, byte);
@@ -1447,16 +1494,18 @@
 static void t1_flush_cs(boolean is_subr)
 {
     char *p;
+    byte *r, return_cs[T1_BUF_SIZE];
     cs_entry *tab, *end_tab, *ptr;
     char *start_line, *line_end;
     int count, size_pos;
+    unsigned short cr, cs_len;
     if (is_subr) {
         start_line = subr_array_start;
         line_end = subr_array_end;
         size_pos = subr_size_pos;
         tab = subr_tab;
-        end_tab = subr_tab + subr_size;
         count = subr_max + 1;
+        end_tab = subr_tab + count;
     }
     else {
         start_line = cs_dict_start;
@@ -1475,7 +1524,23 @@
     strcat(t1_line_ptr, p);
     t1_line_ptr = eol(t1_line);
     t1_putline();
+
+    if (is_subr) {
+        cr = 4330;
+        cs_len = 0;
+        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, "dup %u %u", ptr - tab, ptr->cslen);
@@ -1486,6 +1551,19 @@
             t1_line_ptr = p + ptr->len;
             t1_putline();
         }
+        else {
+            if (is_subr) {
+                sprintf(t1_line, "dup %u %u %s ", ptr - tab, cs_len,
+                        cs_token_pairs[cs_token_choice][0]);
+                p = strend(t1_line);
+                memcpy(p, return_cs, cs_len);
+                t1_line_ptr = p + cs_len;
+                t1_putline();
+                sprintf(t1_line, " %s", cs_token_pairs[cs_token_choice][1]);
+                t1_line_ptr = eol(t1_line);
+                t1_putline();
+            }
+        }
         xfree(ptr->data);
         if (ptr->name != 0 && ptr->name != notdef)
             xfree(ptr->name);
@@ -1493,6 +1571,10 @@
     sprintf(t1_line, "%s", line_end);
     t1_line_ptr = eol(t1_line);
     t1_putline();
+    if (is_subr) {
+        cs_token_choice = -1;
+        cs_tokens_found = false;
+    }
     xfree(tab);
     xfree(start_line);
     xfree(line_end);
@@ -1563,8 +1645,11 @@
     }
     cs_dict_end = xstrdup(t1_line);
     t1_mark_glyphs();
-    if (subr_tab != 0)
+    if (subr_tab != 0) {
+        if (cs_token_choice == -1)
+            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++;


More information about the pdftex mailing list