[pdftex] Yet another patch [long]

Tom Kacvinsky tjk at ams.org
Wed Jun 20 19:35:22 CEST 2001


Hi all,

My last message got truncated.  Since I lost the msssage and don't feel
like retyping it (it was long), I will write this instead:

The new patch adds support for 4 begin/end token pairs:

RD, NP
-|, |
RD, noaccess put
-|, noaccess put

It also forces pdftex to fail if it cannot match any of the four token
pairs listed above.  Also, the being/end token parsing happens only once,
instead of for each subroutine.  The erroe message emitted by pdftex when
it cannot match a begin/end token pair is:

   This Type 1 font uses an unknown subroutine begin/end token pair.

The error message includes which Type 1 font caused the problem, so error
reporting specific to this patch will be meaningful.

If there is a Type 1 font that uses unknown begin/end token pairs, I suggest
you fie yourself away to:

    http://www.lcdf.org/type/#t1utils

And use those tools to fix the fonts.

Tom

P.S.  Fabrice, sorry for sending you the new writet1.c, and then changing
the error message.  That is all that changed...


On Wed, 20 Jun 2001, Tom Kacvinsky wrote:

> Hi all,
>
> And yet another patch.
>
> OK, here is a little more information.  The file that Tom Kiffe sent me used
> an *old* Type 1 font -- so old, it came out before the Type 1 specification was
> published.  This font had a Subrs array that looked like:
>
> /Subrs 30 array
>

-------------- next part --------------
--- writet1.c	2001/06/15 22:54:57	1.1
+++ writet1.c	2001/06/20 21:53:20	1.6
@@ -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 = 0;
+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,24 @@
         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; }
+        else
+            { cs_token_choice = -1; cs_tokens_found = false; }
+    }
     ptr->len = q - t1_buf;
     ptr->cslen = t1_cslen;
     ptr->data = xtalloc(ptr->len, byte);
@@ -1447,16 +1496,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 +1526,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 +1553,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);
@@ -1563,8 +1643,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 an unknown subroutine begin/end token pair.");
         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