texlive[55945] Build/source/texk/dvipdfm-x: Place static variables

commits+kakuto at tug.org commits+kakuto at tug.org
Sun Jul 26 00:06:35 CEST 2020


Revision: 55945
          http://tug.org/svn/texlive?view=revision&revision=55945
Author:   kakuto
Date:     2020-07-26 00:06:35 +0200 (Sun, 26 Jul 2020)
Log Message:
-----------
Place static variables into a single struct. Various minor improvements (S. Hirata).

Modified Paths:
--------------
    trunk/Build/source/texk/dvipdfm-x/ChangeLog
    trunk/Build/source/texk/dvipdfm-x/cmap_write.c
    trunk/Build/source/texk/dvipdfm-x/configure
    trunk/Build/source/texk/dvipdfm-x/configure.ac
    trunk/Build/source/texk/dvipdfm-x/dpxconf.c
    trunk/Build/source/texk/dvipdfm-x/dpxconf.h
    trunk/Build/source/texk/dvipdfm-x/dpxutil.c
    trunk/Build/source/texk/dvipdfm-x/dpxutil.h
    trunk/Build/source/texk/dvipdfm-x/dvi.c
    trunk/Build/source/texk/dvipdfm-x/dvipdfmx.c
    trunk/Build/source/texk/dvipdfm-x/pdfdev.c
    trunk/Build/source/texk/dvipdfm-x/pdfdev.h
    trunk/Build/source/texk/dvipdfm-x/pdfdoc.c
    trunk/Build/source/texk/dvipdfm-x/pdfdoc.h
    trunk/Build/source/texk/dvipdfm-x/pdfencrypt.c
    trunk/Build/source/texk/dvipdfm-x/pdfencrypt.h
    trunk/Build/source/texk/dvipdfm-x/pdfobj.c
    trunk/Build/source/texk/dvipdfm-x/pdfobj.h
    trunk/Build/source/texk/dvipdfm-x/pdfparse.c
    trunk/Build/source/texk/dvipdfm-x/pdfparse.h
    trunk/Build/source/texk/dvipdfm-x/pdfximage.c
    trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c
    trunk/Build/source/texk/dvipdfm-x/xbb.c

Modified: trunk/Build/source/texk/dvipdfm-x/ChangeLog
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/ChangeLog	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/ChangeLog	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,3 +1,19 @@
+2020-07-26  Shunsaku Hirata  <shunsaku.hirata74 at gmail.com>
+
+	* cmap_write.c: Change ariable names.
+	* dvipdfmx.c: Remove unused variables. Modify init sequence.
+	Page size specified as a command line option overwrites
+	settings specified by pagesize specials.
+	* pdfdev.[ch], pdfdoc.[ch], pdfencrypt.[ch], pdfobj.[ch]:
+	File static variables are now placed in a single struct.
+	* pdfparse.[ch], spc_pdfm.c: PDF parse object function is
+	called with a callback function to be called when an object of
+	unknown type is encountered.
+	* pdfximage.c: Do not include an unnecessary file.
+	* dpxconf.[ch], xbb.c: Add is_xbb in dpx_conf.
+	* dpxutil.[ch], dvi.c, dvipdfmx.c: Add dpx_util_read_length().
+	* configure.ac: Version 20200726.
+
 2020-07-24  Shunsaku Hirata  <shunsaku.hirata74 at gmail.com>
 
 	* cidtype0.c: Fix a bug introduced in rev.37144 that generated

Modified: trunk/Build/source/texk/dvipdfm-x/cmap_write.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/cmap_write.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/cmap_write.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2019 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
 
     This program is free software; you can redistribute it and/or modify
@@ -240,14 +240,14 @@
 
 /* duplicated from pdfobj.c */
 static void
-write_string (char **outptr, char *endptr, const char *strptr)
+write_string (char **outptr, char *endptr, const char *string_data)
 {
+  char       *p;
   const char *s;
-  char       *p;
   int         i, length;
 
-  s      = strptr;
-  length = strptr ? strlen(strptr) : 0;
+  s      = string_data;
+  length = string_data ? strlen(string_data) : 0;
   p      = *outptr;
 
   *p++ = '(';
@@ -275,14 +275,14 @@
 }
 
 static void
-write_name (char **outptr, char *endptr, const char *name)
+write_name (char **outptr, char *endptr, const char *name_data)
 {
+  char       *p;
   const char *s;
-  char       *p;
   int         i, length;
 
-  s      = name;
-  length = name ? strlen(name) : 0;
+  s      = name_data;
+  length = name_data ? strlen(name_data) : 0;
   p      = *outptr;
 #ifndef is_delim
   /* Avoid '{' and '}' for PostScript compatibility? */

Modified: trunk/Build/source/texk/dvipdfm-x/configure
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/configure	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/configure	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dvipdfm-x (TeX Live) 20200721.
+# Generated by GNU Autoconf 2.69 for dvipdfm-x (TeX Live) 20200726.
 #
 # Report bugs to <dvipdfmx at tug.org>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='dvipdfm-x (TeX Live)'
 PACKAGE_TARNAME='dvipdfm-x--tex-live-'
-PACKAGE_VERSION='20200721'
-PACKAGE_STRING='dvipdfm-x (TeX Live) 20200721'
+PACKAGE_VERSION='20200726'
+PACKAGE_STRING='dvipdfm-x (TeX Live) 20200726'
 PACKAGE_BUGREPORT='dvipdfmx at tug.org'
 PACKAGE_URL=''
 
@@ -1350,7 +1350,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dvipdfm-x (TeX Live) 20200721 to adapt to many kinds of systems.
+\`configure' configures dvipdfm-x (TeX Live) 20200726 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1421,7 +1421,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dvipdfm-x (TeX Live) 20200721:";;
+     short | recursive ) echo "Configuration of dvipdfm-x (TeX Live) 20200726:";;
    esac
   cat <<\_ACEOF
 
@@ -1551,7 +1551,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dvipdfm-x (TeX Live) configure 20200721
+dvipdfm-x (TeX Live) configure 20200726
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2390,7 +2390,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dvipdfm-x (TeX Live) $as_me 20200721, which was
+It was created by dvipdfm-x (TeX Live) $as_me 20200726, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -8077,7 +8077,7 @@
 
 # Define the identity of the package.
  PACKAGE='dvipdfm-x--tex-live-'
- VERSION='20200721'
+ VERSION='20200726'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -14746,7 +14746,7 @@
 Report bugs to <bug-libtool at gnu.org>."
 
 lt_cl_version="\
-dvipdfm-x (TeX Live) config.lt 20200721
+dvipdfm-x (TeX Live) config.lt 20200726
 configured by $0, generated by GNU Autoconf 2.69.
 
 Copyright (C) 2011 Free Software Foundation, Inc.
@@ -16636,7 +16636,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dvipdfm-x (TeX Live) $as_me 20200721, which was
+This file was extended by dvipdfm-x (TeX Live) $as_me 20200726, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16706,7 +16706,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dvipdfm-x (TeX Live) config.status 20200721
+dvipdfm-x (TeX Live) config.status 20200726
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 

Modified: trunk/Build/source/texk/dvipdfm-x/configure.ac
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/configure.ac	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/configure.ac	2020-07-25 22:06:35 UTC (rev 55945)
@@ -8,7 +8,7 @@
 dnl   gives unlimited permission to copy and/or distribute it,
 dnl   with or without modifications, as long as this notice is preserved.
 dnl
-AC_INIT([dvipdfm-x (TeX Live)], [20200721], [dvipdfmx at tug.org])
+AC_INIT([dvipdfm-x (TeX Live)], [20200726], [dvipdfmx at tug.org])
 AC_PREREQ([2.65])
 AC_CONFIG_SRCDIR([agl.c])
 AC_CONFIG_AUX_DIR([../../build-aux])

Modified: trunk/Build/source/texk/dvipdfm-x/dpxconf.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dpxconf.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dpxconf.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is DVIPDFMx, an eXtended version of DVIPDFM by Mark A. Wicks.
 
-    Copyright (C) 2002-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -30,7 +30,7 @@
 
 #include "dpxconf.h"
 
-struct _dpx_conf dpx_conf = {0, dpx_mode_normal_mode, 0, {0}};
+struct _dpx_conf dpx_conf = {0, 0, dpx_mode_normal_mode, 0, {0}};
 
 #ifndef  HAVE_LIBPAPER
 const struct paper paperspecs[] = {

Modified: trunk/Build/source/texk/dvipdfm-x/dpxconf.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dpxconf.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dpxconf.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is DVIPDFMx, an eXtended version of DVIPDFM by Mark A. Wicks.
 
-    Copyright (C) 2002-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -31,6 +31,7 @@
 };
 
 extern struct _dpx_conf {
+  int            is_xbb;
   int            verbose_level;
   enum dpx_mode  compat_mode;
   int            ignore_font_license;

Modified: trunk/Build/source/texk/dvipdfm-x/dpxutil.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dpxutil.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dpxutil.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2019 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
 
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -69,7 +69,93 @@
   return v;
 }
 
+/* Duplicate from pdfparse.c */
+static void
+skip_white (const char **pp, const char *endptr)
+{
+  while (*pp < endptr &&
+         (**pp == ' '  || **pp == '\t' || **pp == '\f' ||
+          **pp == '\r' || **pp == '\n' || **pp == '\0')) {
+    (*pp)++;
+  }
+}
 
+/* This need to allow 'true' prefix for unit and length value must be divided
+ * by current magnification.
+ */
+int
+dpx_util_read_length (double *vp, double mag, const char **pp, const char *endptr)
+{
+  char   *q;
+  const char *p = *pp;
+  double  v, u = 1.0;
+  const char *_ukeys[] = {
+#define K_UNIT__PT  0
+#define K_UNIT__IN  1
+#define K_UNIT__CM  2
+#define K_UNIT__MM  3
+#define K_UNIT__BP  4
+#define K_UNIT__PC  5
+#define K_UNIT__DD  6
+#define K_UNIT__CC  7
+#define K_UNIT__SP  8
+    "pt", "in", "cm", "mm", "bp", "pc", "dd", "cc", "sp",
+     NULL
+  };
+  int     k, error = 0;
+
+  q = parse_float_decimal(&p, endptr);
+  if (!q) {
+    *vp = 0.0; *pp = p;
+    return  -1;
+  }
+
+  v = atof(q);
+  RELEASE(q);
+
+  skip_white(&p, endptr);
+  q = parse_c_ident(&p, endptr);
+  if (q) {
+    char *qq = q; /* remember this for RELEASE, because q may be advanced */
+    if (strlen(q) >= strlen("true") &&
+        !memcmp(q, "true", strlen("true"))) {
+      u /= mag != 0.0 ? mag : 1.0; /* inverse magnify */
+      q += strlen("true");
+    }
+    if (strlen(q) == 0) { /* "true" was a separate word from the units */
+      RELEASE(qq);
+      skip_white(&p, endptr);
+      qq = q = parse_c_ident(&p, endptr);
+    }
+    if (q) {
+      for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++);
+      switch (k) {
+      case K_UNIT__PT: u *= 72.0 / 72.27; break;
+      case K_UNIT__IN: u *= 72.0; break;
+      case K_UNIT__CM: u *= 72.0 / 2.54 ; break;
+      case K_UNIT__MM: u *= 72.0 / 25.4 ; break;
+      case K_UNIT__BP: u *= 1.0 ; break;
+      case K_UNIT__PC: u *= 12.0 * 72.0 / 72.27 ; break;
+      case K_UNIT__DD: u *= 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
+      case K_UNIT__CC: u *= 12.0 * 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
+      case K_UNIT__SP: u *= 72.0 / (72.27 * 65536) ; break;
+      default:
+        WARN("Unknown unit of measure: %s", q);
+        error = -1;
+        break;
+      }
+      RELEASE(qq);
+    }
+    else {
+      WARN("Missing unit of measure after \"true\"");
+      error = -1;
+    }
+  }
+
+  *vp = v * u; *pp = p;
+  return  error;
+}
+
 #if defined(_MSC_VER)
 #define strtoll _strtoi64
 #endif

Modified: trunk/Build/source/texk/dvipdfm-x/dpxutil.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dpxutil.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dpxutil.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
 
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -35,6 +35,9 @@
 extern double min4(double v1, double v2, double v3, double v4);
 extern double max4(double v1, double v2, double v3, double v4);
 
+extern int dpx_util_read_length (double *vp, double mag,
+                                 const char **curptr, const char *endptr);
+
 #define INVALID_EPOCH_VALUE ((time_t)-1)
 extern time_t dpx_util_get_unique_time_if_given (void);
 extern int    dpx_util_format_asn_date (char *date_string, int need_timezone);

Modified: trunk/Build/source/texk/dvipdfm-x/dvi.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dvi.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dvi.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -2249,83 +2249,7 @@
 
 /* Scan various specials */
 #include "dpxutil.h"
-
-/* This need to allow 'true' prefix for unit and
- * length value must be divided by current magnification.
- */
-static int
-read_length (double *vp, double mag, const char **pp, const char *endptr)
-{
-  char   *q;
-  const char *p = *pp;
-  double  v, u = 1.0;
-  const char *_ukeys[] = {
-#define K_UNIT__PT  0
-#define K_UNIT__IN  1
-#define K_UNIT__CM  2
-#define K_UNIT__MM  3
-#define K_UNIT__BP  4
-#define K_UNIT__PC  5
-#define K_UNIT__DD  6
-#define K_UNIT__CC  7
-#define K_UNIT__SP  8
-    "pt", "in", "cm", "mm", "bp", "pc", "dd", "cc", "sp",
-     NULL
-  };
-  int     k, error = 0;
-
-  q = parse_float_decimal(&p, endptr);
-  if (!q) {
-    *vp = 0.0; *pp = p;
-    return  -1;
-  }
-
-  v = atof(q);
-  RELEASE(q);
-
-  skip_white(&p, endptr);
-  q = parse_c_ident(&p, endptr);
-  if (q) {
-    char *qq = q; /* remember this for RELEASE, because q may be advanced */
-    if (strlen(q) >= strlen("true") &&
-        !memcmp(q, "true", strlen("true"))) {
-      u /= mag != 0.0 ? mag : 1.0; /* inverse magnify */
-      q += strlen("true");
-    }
-    if (strlen(q) == 0) { /* "true" was a separate word from the units */
-      RELEASE(qq);
-      skip_white(&p, endptr);
-      qq = q = parse_c_ident(&p, endptr);
-    }
-    if (q) {
-      for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++);
-      switch (k) {
-      case K_UNIT__PT: u *= 72.0 / 72.27; break;
-      case K_UNIT__IN: u *= 72.0; break;
-      case K_UNIT__CM: u *= 72.0 / 2.54 ; break;
-      case K_UNIT__MM: u *= 72.0 / 25.4 ; break;
-      case K_UNIT__BP: u *= 1.0 ; break;
-      case K_UNIT__PC: u *= 12.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__DD: u *= 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__CC: u *= 12.0 * 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__SP: u *= 72.0 / (72.27 * 65536) ; break;
-      default:
-        WARN("Unknown unit of measure: %s", q);
-        error = -1;
-        break;
-      }
-      RELEASE(qq);
-    }
-    else {
-      WARN("Missing unit of measure after \"true\"");
-      error = -1;
-    }
-  }
-
-  *vp = v * u; *pp = p;
-  return  error;
-}
-
+/* For MAX_PWD_LEN */
 #include "pdfencrypt.h"
 
 static int
@@ -2486,19 +2410,19 @@
         else {
           skip_white(&p, endptr);
           if (!strcmp(kp, "width")) {
-            error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
+            error = dpx_util_read_length(&tmp, dvi_tell_mag(), &p, endptr);
             if (!error)
               *wd = tmp * dvi_tell_mag();
           } else if (!strcmp(kp, "height")) {
-            error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
+            error = dpx_util_read_length(&tmp, dvi_tell_mag(), &p, endptr);
             if (!error)
               *ht = tmp * dvi_tell_mag();
           } else if (!strcmp(kp, "xoffset")) {
-            error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
+            error = dpx_util_read_length(&tmp, dvi_tell_mag(), &p, endptr);
             if (!error)
               *xo = tmp * dvi_tell_mag();
           } else if (!strcmp(kp, "yoffset")) {
-            error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
+            error = dpx_util_read_length(&tmp, dvi_tell_mag(), &p, endptr);
             if (!error)
               *yo = tmp * dvi_tell_mag();
           } else if (!strcmp(kp, "default")) {
@@ -2519,7 +2443,7 @@
         qchr = *p; p++;
         skip_white(&p, endptr);
       }
-      error = read_length(&tmp, 1.0, &p, endptr);
+      error = dpx_util_read_length(&tmp, 1.0, &p, endptr);
       if (!error) {
         double tmp1;
 
@@ -2527,7 +2451,7 @@
         if (p < endptr && *p == ',') {
           p++; skip_white(&p, endptr);
         }
-        error = read_length(&tmp1, 1.0, &p, endptr);
+        error = dpx_util_read_length(&tmp1, 1.0, &p, endptr);
         if (!error) {
           *wd = tmp;
           *ht = tmp1;

Modified: trunk/Build/source/texk/dvipdfm-x/dvipdfmx.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/dvipdfmx.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/dvipdfmx.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -2,7 +2,7 @@
 
     DVIPDFMx, an eXtended version of DVIPDFM by Mark A. Wicks.
 
-    Copyright (C) 2002-2020 by Jin-Hwan Cho, Matthias Franz, Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata,
     the DVIPDFMx project team.
     
     Copyright (c) 2006 SIL. (xdvipdfmx extensions for XeTeX support)
@@ -70,8 +70,11 @@
 const char *my_name;
 #endif /* LIBDPX */
 
-static int    verbose   = 0;
+/* Verbosity level */
+static int    verbose          = 0;
+static int    really_quiet     = 0;
 
+/* Compatibility option flags */
 static int    opt_flags = 0;
 #define OPT_TPIC_TRANSPARENT_FILL (1 << 1)
 #define OPT_CIDFONT_FIXEDPITCH    (1 << 2)
@@ -80,54 +83,54 @@
 #define OPT_PDFOBJ_NO_PREDICTOR   (1 << 5)
 #define OPT_PDFOBJ_NO_OBJSTM      (1 << 6)
 
+/* Basic PDF output settings */
 static int    pdf_version_major = 1;
 static int    pdf_version_minor = 5;
 static int    compression_level = 9;
 
-static char   ignore_colors    = 0;
-static double annot_grow       = 0.0;
-static int    bookmark_open    = 0;
-static double mag              = 1.0;
-static int    font_dpi         = 600;
-static int    enable_thumbnail = 0;
-static int    really_quiet     = 0;
-/*
- * Precision is essentially limited to 0.01pt.
- * See, dev_set_string() in pdfdev.c.
- */
+/* PDF document navigation feature settings */
+static double annot_grow        = 0.0;
+static int    bookmark_open     = 0;
+static double mag               = 1.0;
+static int    enable_thumbnail  = 0;
+
+static int    font_dpi          = 600;
+
+/* PDF output device settings */
 static int    pdfdecimaldigits  = 3;
+static char   ignore_colors     = 0;
 
-/* Image cache life in hours */
-/*  0 means erase all old images and leave new images */
-/* -1 means erase all old images and also erase new images */
-/* -2 means ignore image cache (default) */
+/* Image cache life in hours
+ *  0 means erase all old images and leave new images
+ * -1 means erase all old images and also erase new images
+ * -2 means ignore image cache (default)
+ */
 static int     image_cache_life = -2;
 /* Image format conversion filter template */
 static char   *filter_template  = NULL;
 
 /* Encryption */
-static int     do_encryption = 0;
-static int     key_bits      = 40;
-static int32_t permission    = 0x003C;
+static int     do_encryption    = 0;
+static int     key_bits         = 40;
+static int32_t permission       = 0x003C;
 
 /* Page device */
-double paper_width  = 595.0;
-double paper_height = 842.0;
-static double x_offset = 72.0;
-static double y_offset = 72.0;
-int    landscape_mode  = 0;
-static int    translate_origin = 0;
+double paper_width              = 595.0;
+double paper_height             = 842.0;
+static double x_offset          = 72.0;
+static double y_offset          = 72.0;
+int    landscape_mode           = 0;
+static int    translate_origin  = 0;
 
-/* Command line option takes precedence */
-static int     has_paper_option   = 0;
-static int     has_encrypt_option = 0;
+static int has_paper_option = 0;
 
-char *dvi_filename = NULL, *pdf_filename = NULL;
+/* Input and output filenames */
+static char *dvi_filename = NULL, *pdf_filename = NULL;
 
 static void read_config_file (const char *config);
 
 static void
-set_default_pdf_filename(void)
+set_default_pdf_filename (void)
 {
   const char *dvi_base;
   const char *suffix;
@@ -251,79 +254,6 @@
   exit(1);
 }
 
-
-static int
-read_length (double *vp, const char **pp, const char *endptr)
-{
-  char   *q;
-  const char *p = *pp;
-  double  v, u = 1.0;
-  const char *_ukeys[] = {
-#define K_UNIT__PT  0
-#define K_UNIT__IN  1
-#define K_UNIT__CM  2
-#define K_UNIT__MM  3
-#define K_UNIT__BP  4
-#define K_UNIT__PC  5
-#define K_UNIT__DD  6
-#define K_UNIT__CC  7
-#define K_UNIT__SP  8
-    "pt", "in", "cm", "mm", "bp", "pc", "dd", "cc", "sp",
-     NULL
-  };
-  int     k, error = 0;
-
-  q = parse_float_decimal(&p, endptr);
-  if (!q) {
-    *vp = 0.0; *pp = p;
-    return  -1;
-  }
-
-  v = atof(q);
-  RELEASE(q);
-
-  skip_white(&p, endptr);
-  q = parse_c_ident(&p, endptr);
-  if (q) {
-    char *qq = q;
-    if (strlen(q) >= strlen("true") &&
-        !memcmp(q, "true", strlen("true"))) {
-      q += strlen("true"); /* just skip "true" */
-    }
-    if (strlen(q) == 0) {
-      RELEASE(qq);
-      skip_white(&p, endptr);
-      qq = q = parse_c_ident(&p, endptr);
-    }
-    if (q) {
-      for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++);
-      switch (k) {
-      case K_UNIT__PT: u *= 72.0 / 72.27; break;
-      case K_UNIT__IN: u *= 72.0; break;
-      case K_UNIT__CM: u *= 72.0 / 2.54 ; break;
-      case K_UNIT__MM: u *= 72.0 / 25.4 ; break;
-      case K_UNIT__BP: u *= 1.0 ; break;
-      case K_UNIT__PC: u *= 12.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__DD: u *= 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__CC: u *= 12.0 * 1238.0 / 1157.0 * 72.0 / 72.27 ; break;
-      case K_UNIT__SP: u *= 72.0 / (72.27 * 65536) ; break;
-      default:
-        WARN("Unknown unit of measure: %s", q);
-        error = -1;
-        break;
-      }
-      RELEASE(qq);
-    }
-    else {
-      WARN("Missing unit of measure after \"true\"");
-      error = -1;
-    }
-  }
-
-  *vp = v * u; *pp = p;
-  return  error;
-}
-
 static void
 select_paper (const char *paperspec)
 {
@@ -340,9 +270,9 @@
     endptr = p + strlen(p);
     if (!comma)
       ERROR("Unrecognized paper format: %s", paperspec);
-    error = read_length(&paper_width,  &p, comma);
+    error = dpx_util_read_length(&paper_width, 1.0, &p, comma);
     p = comma + 1;
-    error = read_length(&paper_height, &p, endptr);
+    error = dpx_util_read_length(&paper_height, 1.0, &p, endptr);
   }
   if (error || paper_width <= 0.0 || paper_height <= 0.0)
     ERROR("Invalid paper size: %s (%.2fx%.2f)", paperspec, paper_width, paper_height);
@@ -618,17 +548,17 @@
 
     case 'g':
       nnextptr = nextptr = optarg;
-      read_length(&annot_grow, &nnextptr, nextptr + strlen(nextptr));
+      dpx_util_read_length(&annot_grow, 1.0, &nnextptr, nextptr + strlen(nextptr));
       break;
 
     case 'x':
       nnextptr = nextptr = optarg;
-      read_length(&x_offset, &nnextptr, nextptr + strlen(nextptr));
+      dpx_util_read_length(&x_offset, 1.0, &nnextptr, nextptr + strlen(nextptr));
       break;
 
     case 'y':
       nnextptr = nextptr = optarg;
-      read_length(&y_offset, &nnextptr, nextptr + strlen(nextptr));
+      dpx_util_read_length(&y_offset, 1.0, &nnextptr, nextptr + strlen(nextptr));
       break;
 
     case 'o':
@@ -699,7 +629,6 @@
 
     case 'S':
       do_encryption = 1;
-      has_encrypt_option = 1;
       break;
 
     case 'K':
@@ -935,20 +864,34 @@
         int    lm;
 
         MESG("[%d", page_no+1);
-        /* Users want to change page size even after page is started! */
+        /* FIXME: incompatibility here.... In older versions of dvipdfmx page sizes
+         * are inherited from the previous page but in the current implementation
+         * pagesize special only takes effect to the current page.
+         * The following line resets page sizes to the paper size...
+         */
         page_width = paper_width; page_height = paper_height;
         w = page_width; h = page_height; lm = landscape_mode;
         xo = x_offset; yo = y_offset;
         dvi_scan_specials(page_no,
                           &w, &h, &xo, &yo, &lm,
-                          NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-        if (lm != landscape_mode) { /* already swapped for the first page */
+                          /* No need for encryption options */
+                          NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                          /* No trailer IDs */
+                          NULL, NULL, NULL);
+        if (lm != landscape_mode) {
+          /* The first page was already scanned once and SWAP() was applied there.
+           * Do not apply SWAP() twice!
+           * FIXME: SWAP() not applied to paper_width and paper_height. Why?
+           */
           SWAP(w, h);
           landscape_mode = lm;
         }
-        if (page_width  != w || page_height != h) {
-          page_width  = w;
-          page_height = h;
+        /* Specified as a command line option */
+        if (!has_paper_option) {
+          if (page_width  != w || page_height != h) {
+            page_width  = w;
+            page_height = h;
+          }
         }
         if (x_offset != xo || y_offset != yo) {
           x_offset = xo;
@@ -1095,27 +1038,26 @@
                 STREQ (argv[1], "--ebb"))) {
     argc--;
     base = argv++[1]+2;
-  } else
+  } else {
     base = kpse_program_basename (argv[0]);
-  
+  }
+
   if (FILESTRCASEEQ (base, "extractbb") || FILESTRCASEEQ (base, "xbb")) {
     my_name = "extractbb";
     return extractbb (argc, argv);
-  }
-  if (FILESTRCASEEQ (base, "ebb")) {
+  } else if (FILESTRCASEEQ (base, "ebb")) {
     my_name = "ebb";
     dpx_conf.compat_mode = dpx_mode_compat_mode;
     return extractbb (argc, argv);
-  }
-  if (FILESTRCASEEQ (base, "dvipdfm"))
+  } else if (FILESTRCASEEQ (base, "dvipdfm")) {
     dpx_conf.compat_mode = dpx_mode_compat_mode;
-  if (FILESTRCASEEQ (base, "dvipdfmx"))
+  } else if (FILESTRCASEEQ (base, "dvipdfmx")) {
     my_name = "dvipdfmx";
-  else
+  } else {
     my_name = "xdvipdfmx";
-  
+  }
+
   opterr = 0;
-
   /* Special-case single option --mvorigin, --help, --showpaper, or --version,
    * to avoid possible diagnostics about config files, etc.
    * Also handle -q and -v that cannot be set in config file.
@@ -1130,6 +1072,12 @@
 
   read_config_file(DPX_CONFIG_FILE);
 
+  /* Current implementation seems to be assuming that paper size read from config
+   * is for "default" and explicitly specified one via command-line option must be
+   * used for all pages regardless of papersize specials.
+   */
+  has_paper_option = 0;
+
 #ifndef MIKTEX
   kpse_init_prog("", font_dpi, NULL, NULL);
   kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf);
@@ -1157,7 +1105,6 @@
     y_offset = 0.0;
     dvi2pts  = 0.01; /* dvi2pts controls accuracy. */
   } else {
-    /* Dependency between DVI and PDF side is rather complicated... */
     dvi2pts = dvi_init(dvi_filename, mag);
     if (dvi2pts == 0.0)
       ERROR("dvi_init() failed!");
@@ -1180,9 +1127,24 @@
     }
   }
 
-/* moved to here because image caching was not effective */
+  /* moved to here because image caching was not effective */
   dpx_delete_old_cache(image_cache_life);
 
+  /* Setup Options */
+  settings.ver_major = pdf_version_major;
+  settings.ver_minor = pdf_version_minor;
+
+  /* PDF trailer ID. */
+  if (!has_id) {
+#define PRODUCER \
+"%s-%s, Copyright 2002-2020 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata"
+    char producer[256];
+    
+    sprintf(producer, PRODUCER, my_name, VERSION);
+    compute_id_string(id1, producer, dvi_filename, pdf_filename);
+    memcpy(id2, id1, 16);
+  }
+
   /* Encryption and Other Settings */
   {
     memset(&settings.encrypt, 0, sizeof(struct pdf_enc_setting));
@@ -1195,6 +1157,8 @@
     settings.encrypt.oplain     = oplain;
   }
 
+  /* PDF object settings */
+  settings.object.compression_level = compression_level;
   if (opt_flags & OPT_PDFOBJ_NO_OBJSTM) {
     settings.object.enable_objstm = 0;
   } else {
@@ -1205,7 +1169,9 @@
   } else {
     settings.object.enable_predictor = 1;
   }
-  /* Set default paper size here so that all page's can inherite it.
+
+  /* PDF document settings
+   * Set default paper size here so that all page's can inherite it.
    * annot_grow:    Margin of annotation.
    * bookmark_open: Miximal depth of open bookmarks.
    */
@@ -1217,33 +1183,15 @@
   settings.annot_grow_amount  = annot_grow;
   settings.outline_open_depth = bookmark_open;
   settings.check_gotos        = !(opt_flags & OPT_PDFDOC_NO_DEST_REMOVE);
+  settings.enable_manual_thumb = enable_thumbnail;
 
+  /* PDF page output settings */
   settings.device.dvi2pts     = dvi2pts;
   settings.device.precision   = pdfdecimaldigits;
   settings.device.ignore_colors = ignore_colors;
 
   set_distiller_template(filter_template);
-  /* This must come before pdf_open_document where initialization
-   * of pdf_enc takes place.
-   */
-  {
-    int version = pdf_version_major * 10 + pdf_version_minor;
-    pdf_set_version(version);
-  }
-  pdf_set_compression(compression_level);
-  if (enable_thumbnail)
-    pdf_doc_enable_manual_thumbnails();
 
-  if (!has_id) {
-#define PRODUCER \
-"%s-%s, Copyright 2002-2015 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata"
-    char producer[256];
-    
-    sprintf(producer, PRODUCER, my_name, VERSION);
-    compute_id_string(id1, producer, dvi_filename, pdf_filename);
-    memcpy(id2, id1, 16);
-  }
-
   /* Initialize PDF document creation routine. */
   pdf_open_document(pdf_filename, creator, id1, id2, settings);
 

Modified: trunk/Build/source/texk/dvipdfm-x/pdfdev.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfdev.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfdev.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -53,35 +53,247 @@
 
 #include "pdfdev.h"
 
-/* Not working yet... */
-double
-pdf_dev_scale (void)
+struct dev_param
 {
-  return 1.0;
-}
+  /* Text composition (direction) mode is ignored (always same
+   * as font's writing mode) if autorotate is unset (value zero).
+   */
+  int    autorotate;
 
+  /*
+   * Ignore color migrated to here. This is device's capacity.
+   * colormode 0 for ignore colors
+   */
+  int    colormode;
+
+};
+
 /*
+ * Text handling routines.
+ */
+
+/* Motion state:
+ *  GRAPHICS_MODE  Initial state (not within BT/ET block nor in string)
+ *  TEXT_MODE      Text section is started via BT operator but not
+ *                 in string.
+ *  STRING_MODE    In string. A string or array of strings are currently
+ *                 in process. May started '[', '<' or '('.
+ */
+#define GRAPHICS_MODE  1
+#define TEXT_MODE      2
+#define STRING_MODE    3
+
+/*
+ * In PDF, vertical text positioning is always applied when current font
+ * is vertical font. While ASCII pTeX manages current writing direction
+ * and font's WMode separately.
+ *
+ * 000/101 WMODE_HH/VV  h(v) font, h(v) direction.
+ * 001    WMODE_HV    -90 deg. rotated  
+ * 100    WMODE_VH    +90 deg. rotated
+ * 011    WMODE_HD    +90 deg. rotated
+ * 111    WMODE_VD    180 deg. rotated
+
+ * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode
+ * is applied.
+ */
+#define TEXT_WMODE_HH 0
+#define TEXT_WMODE_HV 1
+#define TEXT_WMODE_VH 4
+#define TEXT_WMODE_VV 5
+#define TEXT_WMODE_HD 3
+#define TEXT_WMODE_VD 7
+
+#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1)
+#define ROTATE_TEXT(m)       ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV)
+
+struct text_state {
+
+  /* Current font.
+   * This is index within dev_fonts.
+   */
+  int       font_id;
+
+  /* Dvipdfmx does compression of text by doing text positioning
+   * in relative motion and uses string array [(foo) -250 (bar)]
+   * with kerning (negative kern is used for white space as suited
+   * for TeX). This is offset within current string.
+   */
+  spt_t     offset;
+
+  /* This is reference point of strings.
+   * It may include error correction induced by rounding.
+   */
+  spt_t     ref_x;
+  spt_t     ref_y;
+
+  /* Using text raise and leading is highly recommended for
+   * text extraction to work properly. But not implemented yet.
+   * We can't do consice output for \TeX without this.
+   */
+  spt_t     raise;    /* unused */
+  spt_t     leading;  /* unused */
+
+  /* This is not always text matrix but rather font matrix.
+   * We do not use horizontal scaling in PDF text state parameter
+   * since they always apply scaling in fixed direction regardless
+   * of writing mode.
+   */
+  struct {
+    double  slant;
+    double  extend;
+    int     rotate; /* TEXT_WMODE_XX */
+  } matrix;
+
+  /* Fake bold parameter:
+   * If bold_param is positive, use text rendering mode
+   * fill-then-stroke with stroking line width specified
+   * by bold_param.
+   */
+  double    bold_param;
+
+  /* Text composition (direction) mode. */
+  int       dir_mode;
+
+  /* internal */
+
+  /* Flag indicating text matrix to be forcibly reset.
+   * Enabled if synthetic font features (slant, extend, etc)
+   * are used for current font or when text rotation mode
+   * changes.
+   */
+  int       force_reset;
+
+  /* This information is duplicated from dev[font_id].format.
+   * Set to 1 if font is composite (Type0) font.
+   */
+  int       is_mb;
+};
+
+#define PDF_FONTTYPE_SIMPLE    1
+#define PDF_FONTTYPE_BITMAP    2
+#define PDF_FONTTYPE_COMPOSITE 3
+
+struct dev_font {
+  /* Needs to be big enough to hold name "Fxxx"
+   * where xxx is number of largest font
+   */
+  char     short_name[7];      /* Resource name */
+  int      used_on_this_page;
+
+  char    *tex_name;  /* String identifier of this font */
+  spt_t    sptsize;   /* Point size */
+
+  /* Returned values from font/encoding layer:
+   *
+   * The font_id and enc_id is font and encoding (CMap) identifier
+   * used in pdf_font or encoding/cmap layer.
+   * The PDF object "resource" is an indirect reference object
+   * pointing font resource of this font. The used_chars is somewhat
+   * misleading, this is actually used_glyphs in CIDFont for Type0
+   * and is 65536/8 bytes binary data with each bits representing
+   * whether the glyph is in-use or not. It is 256 char array for
+   * simple font.
+   */
+  int      font_id;
+  int      enc_id;
+
+  /* if >= 0, index of a dev_font that really has the resource and used_chars */
+  int      real_font_index;
+
+  pdf_obj *resource;
+  char    *used_chars;
+
+  /* Font format:
+   * simple, composite or bitmap.
+   */
+  int      format;
+
+  /* Writing mode:
+   * Non-zero for vertical. Duplicated from CMap.
+   */
+  int      wmode;
+
+  /* Syntetic Font:
+   *
+   * We use text matrix for creating extended or slanted font,
+   * but not with font's FontMatrix since TrueType and Type0
+   * font don't support them.
+   */
+  double   extend;
+  double   slant;
+  double   bold;  /* Boldness prameter */
+
+  /* Compatibility */
+  int      mapc;  /* Nasty workaround for Omega */
+
+  /* There are no font metric format supporting four-bytes
+   * charcter code. So we should provide an option to specify
+   * UCS group and plane.
+   */
+  int      ucs_group;
+  int      ucs_plane;
+
+  int      is_unicode;
+};
+
+/*
  * Unit conversion, formatting and others.
  */
 
 #define TEX_ONE_HUNDRED_BP 6578176
-static struct {
-  double dvi2pts;
+struct dev_unit {
+  double dvi2pts;    /* multiplier for DVI unit to bpt conversion           */
   int    min_bp_val; /* Shortest resolvable distance in the output PDF.     */
   int    precision;  /* Number of decimal digits (in fractional part) kept. */
-} dev_unit = {
-  0.0,
-  658,
-  2
 };
 
+#define FORMAT_BUF_SIZE 4096
+struct pdf_dev {
+  int               motion_state;
+  struct dev_param  param;
+  struct dev_unit   unit;
+  struct text_state text_state;
+  struct dev_font  *fonts;
+  int               num_dev_fonts;
+  int               max_dev_fonts;
+  int               num_phys_fonts;
+  char              format_buffer[FORMAT_BUF_SIZE+1];
 
-double
-dev_unit_dviunit (void)
+  /* Just to support pdf:bcontent special...
+   * Text position adjustment inside the pdf:bcontent and pdf:econtent.
+   */
+  pdf_coord        *dev_coords;
+  int               num_dev_coords;
+  int               max_dev_coords;
+};
+
+/*
+ * For a moment declare as static variable here
+ * 2020/07/23 Most of the static variables put into single struct pdev
+ */
+static pdf_dev pdev;
+
+static pdf_dev *
+current_device (void)
 {
-  return (1.0/dev_unit.dvi2pts);
+  return &pdev;
 }
 
+static void
+dev_out (pdf_dev *p, const char *str, size_t len)
+{
+  pdf_doc_add_page_content(str, len);
+}
+
+static double
+pdf_dev_unit_dviunit (pdf_dev *p)
+{
+  ASSERT(p);
+
+  return (1.0 / p->unit.dvi2pts);
+}
+
 #define DEV_PRECISION_MAX  8
 static uint32_t ten_pow[10] = {
   1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u
@@ -91,8 +303,8 @@
   1.0, 0.1,  0.01,  0.001,  0.0001,  0.00001,  0.000001,  0.0000001,  0.00000001,  0.000000001
 };
 
-#define bpt2spt(b) ( (spt_t) round( (b) / dev_unit.dvi2pts  ) )
-#define spt2bpt(s) ( (s) * dev_unit.dvi2pts )
+#define bpt2spt(p, b) ( (spt_t) round( (b) / (p)->unit.dvi2pts  ) )
+#define spt2bpt(p, s) ( (s) * (p)->unit.dvi2pts )
 #define dround_at(v,p) (ROUND( (v), ten_pow_inv[(p)] ))
 
 static int
@@ -194,16 +406,20 @@
 }
 
 static int
-dev_sprint_bp (char *buf, spt_t value, spt_t *error)
+dev_sprint_bp (pdf_dev *p, char *buf, spt_t value, spt_t *error)
 {
   double  value_in_bp;
   double  error_in_bp;
-  int     prec = dev_unit.precision;
+  int     prec;
+  
+  ASSERT(p);
+  
+  prec = p->unit.precision;
 
-  value_in_bp = spt2bpt(value);
+  value_in_bp = spt2bpt(p, value);
   if (error) {
     error_in_bp = value_in_bp - dround_at(value_in_bp, prec);
-    *error = bpt2spt(error_in_bp);
+    *error = bpt2spt(p, error_in_bp);
   }
 
   return  p_dtoa(value_in_bp, prec, buf);
@@ -210,13 +426,17 @@
 }
 
 /* They are affected by precision (set at device initialization). */
-int
-pdf_sprint_matrix (char *buf, const pdf_tmatrix *M)
+static size_t
+pdf_dev_sprint_matrix (pdf_dev *p, char *buf, const pdf_tmatrix *M)
 {
-  int  len;
-  int  prec2 = MIN(dev_unit.precision + 2, DEV_PRECISION_MAX);
-  int  prec0 = MAX(dev_unit.precision, 2);
+  size_t  len;
+  int     prec0, prec2;
 
+  ASSERT(p);
+
+  prec2 = MIN(p->unit.precision + 2, DEV_PRECISION_MAX);
+  prec0 = MAX(p->unit.precision, 2);
+
   len  = p_dtoa(M->a, prec2, buf);
   buf[len++] = ' ';
   len += p_dtoa(M->b, prec2, buf+len);
@@ -233,53 +453,60 @@
   return  len;
 }
 
-int
-pdf_sprint_rect (char *buf, const pdf_rect *rect)
+static size_t
+pdf_dev_sprint_rect (pdf_dev *p, char *buf, const pdf_rect *rect)
 {
-  int  len;
+  size_t  len;
 
-  len  = p_dtoa(rect->llx, dev_unit.precision, buf);
+  ASSERT(p);
+
+  len  = p_dtoa(rect->llx, p->unit.precision, buf);
   buf[len++] = ' ';
-  len += p_dtoa(rect->lly, dev_unit.precision, buf+len);
+  len += p_dtoa(rect->lly, p->unit.precision, buf+len);
   buf[len++] = ' ';
-  len += p_dtoa(rect->urx, dev_unit.precision, buf+len);
+  len += p_dtoa(rect->urx, p->unit.precision, buf+len);
   buf[len++] = ' ';
-  len += p_dtoa(rect->ury, dev_unit.precision, buf+len);
+  len += p_dtoa(rect->ury, p->unit.precision, buf+len);
   buf[len]   = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
 
   return  len;
 }
 
-int
-pdf_sprint_coord (char *buf, const pdf_coord *p)
+static size_t
+pdf_dev_sprint_coord (pdf_dev *p, char *buf, const pdf_coord *c)
 {
-  int  len;
+  size_t  len;
 
-  len  = p_dtoa(p->x, dev_unit.precision, buf);
+  ASSERT(p);
+
+  len  = p_dtoa(c->x, p->unit.precision, buf);
   buf[len++] = ' ';
-  len += p_dtoa(p->y, dev_unit.precision, buf+len);
+  len += p_dtoa(c->y, p->unit.precision, buf+len);
   buf[len]   = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
 
   return  len;
 }
 
-int
-pdf_sprint_length (char *buf, double value)
+static size_t
+pdf_dev_sprint_length (pdf_dev *p, char *buf, double value)
 {
-  int  len;
+  size_t  len;
 
-  len = p_dtoa(value, dev_unit.precision, buf);
+  ASSERT(p);
+
+  len = p_dtoa(value, p->unit.precision, buf);
   buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
 
   return  len;
 }
 
-
-int
-pdf_sprint_number (char *buf, double value)
+static size_t
+pdf_dev_sprint_number (pdf_dev *p, char *buf, double value)
 {
-  int  len;
+  size_t  len;
 
+  ASSERT(p);
+
   len = p_dtoa(value, DEV_PRECISION_MAX, buf);
   buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
 
@@ -286,228 +513,21 @@
   return  len;
 }
 
+/* Text handling */
+#define CURRENTFONT(p) (((p)->text_state.font_id < 0) ? \
+  NULL : &((p)->fonts[(p)->text_state.font_id]))
+#define GET_FONT(p, n)   (&((p)->fonts[(n)]))
 
-static struct
-{
-  /* Text composition (direction) mode is ignored (always same
-   * as font's writing mode) if autorotate is unset (value zero).
-   */
-  int    autorotate;
-
-  /*
-   * Ignore color migrated to here. This is device's capacity.
-   * colormode 0 for ignore colors
-   */
-  int    colormode;
-
-} dev_param = {
-  1, /* autorotate */
-  1, /* colormode  */
-};
-
-/*
- * Text handling routines.
- */
-
-/* Motion state:
- *  GRAPHICS_MODE  Initial state (not within BT/ET block nor in string)
- *  TEXT_MODE      Text section is started via BT operator but not
- *                 in string.
- *  STRING_MODE    In string. A string or array of strings are currently
- *                 in process. May started '[', '<' or '('.
- */
-#define GRAPHICS_MODE  1
-#define TEXT_MODE      2
-#define STRING_MODE    3
-
-static int motion_state = GRAPHICS_MODE;
-
-#define FORMAT_BUF_SIZE 4096
-static char format_buffer[FORMAT_BUF_SIZE];
-
-/*
- * In PDF, vertical text positioning is always applied when current font
- * is vertical font. While ASCII pTeX manages current writing direction
- * and font's WMode separately.
- *
- * 000/101 WMODE_HH/VV  h(v) font, h(v) direction.
- * 001    WMODE_HV    -90 deg. rotated  
- * 100    WMODE_VH    +90 deg. rotated
- * 011    WMODE_HD    +90 deg. rotated
- * 111    WMODE_VD    180 deg. rotated
-
- * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode
- * is applied.
- */
-#define TEXT_WMODE_HH 0
-#define TEXT_WMODE_HV 1
-#define TEXT_WMODE_VH 4
-#define TEXT_WMODE_VV 5
-#define TEXT_WMODE_HD 3
-#define TEXT_WMODE_VD 7
-
-#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1)
-#define ROTATE_TEXT(m)       ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV)
-
-static struct {
-
-  /* Current font.
-   * This is index within dev_fonts.
-   */
-  int       font_id;
-
-  /* Dvipdfmx does compression of text by doing text positioning
-   * in relative motion and uses string array [(foo) -250 (bar)]
-   * with kerning (negative kern is used for white space as suited
-   * for TeX). This is offset within current string.
-   */
-  spt_t     offset;
-
-  /* This is reference point of strings.
-   * It may include error correction induced by rounding.
-   */
-  spt_t     ref_x;
-  spt_t     ref_y;
-
-  /* Using text raise and leading is highly recommended for
-   * text extraction to work properly. But not implemented yet.
-   * We can't do consice output for \TeX without this.
-   */
-  spt_t     raise;    /* unused */
-  spt_t     leading;  /* unused */
-
-  /* This is not always text matrix but rather font matrix.
-   * We do not use horizontal scaling in PDF text state parameter
-   * since they always apply scaling in fixed direction regardless
-   * of writing mode.
-   */
-  struct {
-    double  slant;
-    double  extend;
-    int     rotate; /* TEXT_WMODE_XX */
-  } matrix;
-
-  /* Fake bold parameter:
-   * If bold_param is positive, use text rendering mode
-   * fill-then-stroke with stroking line width specified
-   * by bold_param.
-   */
-  double    bold_param;
-
-  /* Text composition (direction) mode. */
-  int       dir_mode;
-
-  /* internal */
-
-  /* Flag indicating text matrix to be forcibly reset.
-   * Enabled if synthetic font features (slant, extend, etc)
-   * are used for current font or when text rotation mode
-   * changes.
-   */
-  int       force_reset;
-
-  /* This information is duplicated from dev[font_id].format.
-   * Set to 1 if font is composite (Type0) font.
-   */
-  int       is_mb;
-} text_state = {
-  -1,            /* font   */
-  0,             /* offset */
-  0, 0,          /* ref_x, ref_y   */
-  0, 0,          /* raise, leading */
-  {0.0, 1.0, 0},
-
-  0.0,  /* Experimental boldness param */
-
-  0,    /* dir_mode      */
-
-  /* internal */
-  0,    /* force_reset   */
-  0     /* is_mb         */
-};
-
-#define PDF_FONTTYPE_SIMPLE    1
-#define PDF_FONTTYPE_BITMAP    2
-#define PDF_FONTTYPE_COMPOSITE 3
-
-struct dev_font {
-  /* Needs to be big enough to hold name "Fxxx"
-   * where xxx is number of largest font
-   */
-  char     short_name[7];      /* Resource name */
-  int      used_on_this_page;
-
-  char    *tex_name;  /* String identifier of this font */
-  spt_t    sptsize;   /* Point size */
-
-  /* Returned values from font/encoding layer:
-   *
-   * The font_id and enc_id is font and encoding (CMap) identifier
-   * used in pdf_font or encoding/cmap layer.
-   * The PDF object "resource" is an indirect reference object
-   * pointing font resource of this font. The used_chars is somewhat
-   * misleading, this is actually used_glyphs in CIDFont for Type0
-   * and is 65536/8 bytes binary data with each bits representing
-   * whether the glyph is in-use or not. It is 256 char array for
-   * simple font.
-   */
-  int      font_id;
-  int      enc_id;
-
-  /* if >= 0, index of a dev_font that really has the resource and used_chars */
-  int      real_font_index;
-
-  pdf_obj *resource;
-  char    *used_chars;
-
-  /* Font format:
-   * simple, composite or bitmap.
-   */
-  int      format;
-
-  /* Writing mode:
-   * Non-zero for vertical. Duplicated from CMap.
-   */
-  int      wmode;
-
-  /* Syntetic Font:
-   *
-   * We use text matrix for creating extended or slanted font,
-   * but not with font's FontMatrix since TrueType and Type0
-   * font don't support them.
-   */
-  double   extend;
-  double   slant;
-  double   bold;  /* Boldness prameter */
-
-  /* Compatibility */
-  int      mapc;  /* Nasty workaround for Omega */
-
-  /* There are no font metric format supporting four-bytes
-   * charcter code. So we should provide an option to specify
-   * UCS group and plane.
-   */
-  int      ucs_group;
-  int      ucs_plane;
-
-  int      is_unicode;
-};
-static struct dev_font *dev_fonts = NULL;
-
-static int num_dev_fonts   = 0;
-static int max_dev_fonts   = 0;
-static int num_phys_fonts  = 0;
-
-#define CURRENTFONT() ((text_state.font_id < 0) ? NULL : &(dev_fonts[text_state.font_id]))
-#define GET_FONT(n)   (&(dev_fonts[(n)]))
-
-
 static void
-dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
+dev_set_text_matrix (pdf_dev *p,
+                     spt_t xpos, spt_t ypos,
+                     double slant, double extend, int rotate)
 {
   pdf_tmatrix tm;
   int         len = 0;
 
+  ASSERT(p);
+
   /* slant is negated for vertical font so that right-side
    * is always lower. */
   switch (rotate) {
@@ -542,22 +562,22 @@
     tm.c =  0.0; tm.d =  -extend;
     break;
   }
-  tm.e = xpos * dev_unit.dvi2pts;
-  tm.f = ypos * dev_unit.dvi2pts;
+  tm.e = xpos * p->unit.dvi2pts;
+  tm.f = ypos * p->unit.dvi2pts;
 
-  format_buffer[len++] = ' ';
-  len += pdf_sprint_matrix(format_buffer+len, &tm);
-  format_buffer[len++] = ' ';
-  format_buffer[len++] = 'T';
-  format_buffer[len++] = 'm';
+  p->format_buffer[len++] = ' ';
+  len += pdf_dev_sprint_matrix(p, p->format_buffer+len, &tm);
+  p->format_buffer[len++] = ' ';
+  p->format_buffer[len++] = 'T';
+  p->format_buffer[len++] = 'm';
 
-  pdf_doc_add_page_content(format_buffer, len);  /* op: Tm */
+  dev_out(p, p->format_buffer, len);  /* op: Tm */
 
-  text_state.ref_x = xpos;
-  text_state.ref_y = ypos;
-  text_state.matrix.slant  = slant;
-  text_state.matrix.extend = extend;
-  text_state.matrix.rotate = rotate;
+  p->text_state.ref_x = xpos;
+  p->text_state.ref_y = ypos;
+  p->text_state.matrix.slant  = slant;
+  p->text_state.matrix.extend = extend;
+  p->text_state.matrix.rotate = rotate;
 }
 
 /*
@@ -566,81 +586,88 @@
  */
 
 static void
-reset_text_state (void)
+reset_text_state (pdf_dev *p)
 {
+  ASSERT(p);
+
   /*
    * We need to reset the line matrix to handle slanted fonts.
    */
-  pdf_doc_add_page_content(" BT", 3);  /* op: BT */
+  dev_out(p, " BT", 3);  /* op: BT */
   /*
    * text_state.matrix is identity at top of page.
    * This sometimes write unnecessary "Tm"s when transition from
    * GRAPHICS_MODE to TEXT_MODE occurs.
    */
-  if (text_state.force_reset ||
-      text_state.matrix.slant  != 0.0 ||
-      text_state.matrix.extend != 1.0 ||
-      ROTATE_TEXT(text_state.matrix.rotate)) {
-    dev_set_text_matrix(0, 0,
-                        text_state.matrix.slant,
-                        text_state.matrix.extend,
-                        text_state.matrix.rotate);
+  if (p->text_state.force_reset ||
+      p->text_state.matrix.slant  != 0.0 ||
+      p->text_state.matrix.extend != 1.0 ||
+      ROTATE_TEXT(p->text_state.matrix.rotate)) {
+    dev_set_text_matrix(p, 0, 0,
+                        p->text_state.matrix.slant,
+                        p->text_state.matrix.extend,
+                        p->text_state.matrix.rotate);
   }
-  text_state.ref_x = 0;
-  text_state.ref_y = 0;
-  text_state.offset   = 0;
-  text_state.force_reset = 0;
+  p->text_state.ref_x = 0;
+  p->text_state.ref_y = 0;
+  p->text_state.offset   = 0;
+  p->text_state.force_reset = 0;
 }
 
 static void
-text_mode (void)
+pdf_dev_text_mode (pdf_dev *p)
 {
-  switch (motion_state) {
+  ASSERT(p);
+
+  switch (p->motion_state) {
   case TEXT_MODE:
     break;
   case STRING_MODE:
-    pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4);  /* op: TJ */
+    dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4);  /* op: TJ */
     break;
   case GRAPHICS_MODE:
-    reset_text_state();
+    reset_text_state(p);
     break;
   }
-  motion_state      = TEXT_MODE;
-  text_state.offset = 0;
+  p->motion_state      = TEXT_MODE;
+  p->text_state.offset = 0;
 }
 
-void
-graphics_mode (void)
+static void
+pdf_dev_graphics_mode (pdf_dev *p)
 {
-  switch (motion_state) {
+  switch (p->motion_state) {
   case GRAPHICS_MODE:
     break;
   case STRING_MODE:
-    pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4);  /* op: TJ */
+    dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4);  /* op: TJ */
     /* continue */
   case TEXT_MODE:
-    if (text_state.bold_param != 0.0) {
+    if (p->text_state.bold_param != 0.0) {
       /* fake-bold "2 Tr" is still active */
-      pdf_doc_add_page_content(" 0 Tr", 5);  /* op: Tr */
-      text_state.bold_param  = 0.0;
-    }
-    pdf_doc_add_page_content(" ET", 3);  /* op: ET */
-    text_state.force_reset =  0;
-    text_state.font_id     = -1;
+      dev_out(p, " 0 Tr", 5);  /* op: Tr */
+      p->text_state.bold_param = 0.0;
+    }  
+    dev_out(p, " ET", 3);  /* op: ET */
+    p->text_state.force_reset =  0;
+    p->text_state.font_id     = -1;
     break;
   }
-  motion_state = GRAPHICS_MODE;
+  p->motion_state = GRAPHICS_MODE;
 }
 
 static void
-start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
+start_string (pdf_dev *p,
+              spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
 {
   spt_t delx, dely, error_delx, error_dely;
   spt_t desired_delx, desired_dely;
   int   len = 0;
 
-  delx = xpos - text_state.ref_x;
-  dely = ypos - text_state.ref_y;
+  ASSERT(p);
+
+  delx = xpos - p->text_state.ref_x;
+  dely = ypos - p->text_state.ref_y;
   /*
    * Precompensating for line transformation matrix.
    *
@@ -697,10 +724,10 @@
      * We must care about rotation here but not extend/slant...
      * The extend and slant actually is font matrix.
      */
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
     error_delx = -error_delx;
     break;
   case TEXT_WMODE_HV:
@@ -716,10 +743,10 @@
     /*
      * e = (e_user_y, -e_user_x)
      */
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
     error_dely = -error_dely;
     break;
   case TEXT_WMODE_HH:
@@ -731,10 +758,10 @@
     desired_delx = (spt_t)((delx - dely*slant)/extend);
     desired_dely = dely;
 
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
     break;
   case TEXT_WMODE_VV:
     /* Vertical font in vertical mode:
@@ -745,10 +772,10 @@
     desired_delx = delx;
     desired_dely = (spt_t)((dely + delx*slant)/extend);
 
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
     break;
   case TEXT_WMODE_HD:
     /* Horizontal font in down-to-up mode: rot = +90
@@ -760,10 +787,10 @@
     desired_delx = -(spt_t)(-(dely + delx*slant)/extend);
     desired_dely = -delx;
 
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
     error_delx = -error_delx;
     error_dely = -error_dely;
    break;
@@ -776,48 +803,50 @@
     desired_delx = -delx;
     desired_dely = -(spt_t)((dely + delx*slant)/extend);
 
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx);
-    format_buffer[len++] = ' ';
-    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
+    p->format_buffer[len++] = ' ';
+    len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
     error_delx = -error_delx;
     error_dely = -error_dely;
     break;
   }
-  pdf_doc_add_page_content(format_buffer, len);  /* op: */
+  dev_out(p, p->format_buffer, len);  /* op: */
   /*
    * dvipdfm wrongly using "TD" in place of "Td".
    * The TD operator set leading, but we are not using T* etc.
    */
-  pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5);  /* op: Td */
+  dev_out(p, p->text_state.is_mb ? " Td[<" : " Td[(", 5);  /* op: Td */
 
   /* Error correction */
-  text_state.ref_x = xpos - error_delx;
-  text_state.ref_y = ypos - error_dely;
+  p->text_state.ref_x = xpos - error_delx;
+  p->text_state.ref_y = ypos - error_dely;
 
-  text_state.offset   = 0;
+  p->text_state.offset   = 0;
 }
 
 static void
-string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
+pdf_dev_string_mode (pdf_dev *p, spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
 {
-  switch (motion_state) {
+  ASSERT(p);
+
+  switch (p->motion_state) {
   case STRING_MODE:
     break;
   case GRAPHICS_MODE:
-    reset_text_state();
+    reset_text_state(p);
     /* continue */
   case TEXT_MODE:
-    if (text_state.force_reset) {
-      dev_set_text_matrix(xpos, ypos, slant, extend, rotate);
-      pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2);  /* op: */
-      text_state.force_reset = 0;
+    if (p->text_state.force_reset) {
+      dev_set_text_matrix(p, xpos, ypos, slant, extend, rotate);
+      dev_out(p, p->text_state.is_mb ? "[<" : "[(", 2);  /* op: */
+      p->text_state.force_reset = 0;
     } else {
-      start_string(xpos, ypos, slant, extend, rotate);
+      start_string(p, xpos, ypos, slant, extend, rotate);
     }
     break;
   }
-  motion_state = STRING_MODE;
+  p->motion_state = STRING_MODE;
 }
 
 /*
@@ -833,7 +862,7 @@
  */
 
 static int
-dev_set_font (int font_id)
+pdf_dev_set_font (pdf_dev *p, int font_id)
 {
   struct dev_font *font;
   struct dev_font *real_font;
@@ -842,35 +871,37 @@
   int    len;
   int    vert_dir, vert_font;
 
+  ASSERT(p);
+
   /* text_mode() must come before text_state.is_mb is changed. */
-  text_mode();
+  pdf_dev_text_mode(p);
 
-  font = GET_FONT(font_id);
+  font = GET_FONT(p, font_id);
   ASSERT(font); /* Caller should check font_id. */
 
   if (font->real_font_index >= 0)
-    real_font = GET_FONT(font->real_font_index);
+    real_font = GET_FONT(p, font->real_font_index);
   else
     real_font = font;
 
-  text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0;
+  p->text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0;
 
   vert_font  = font->wmode ? 1 : 0;
-  if (dev_param.autorotate) {
-    vert_dir = text_state.dir_mode;
+  if (p->param.autorotate) {
+    vert_dir = p->text_state.dir_mode;
   } else {
     vert_dir = vert_font;
   }
   text_rotate = (vert_font << 2)|vert_dir;
 
-  if (font->slant  != text_state.matrix.slant  ||
-      font->extend != text_state.matrix.extend ||
-      ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) {
-    text_state.force_reset = 1;
+  if (font->slant  != p->text_state.matrix.slant  ||
+      font->extend != p->text_state.matrix.extend ||
+      ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
+    p->text_state.force_reset = 1;
   }
-  text_state.matrix.slant  = font->slant;
-  text_state.matrix.extend = font->extend;
-  text_state.matrix.rotate = text_rotate;
+  p->text_state.matrix.slant  = font->slant;
+  p->text_state.matrix.extend = font->extend;
+  p->text_state.matrix.rotate = text_rotate;
 
   if (!real_font->resource) {
     real_font->resource   = pdf_get_font_reference(real_font->font_id);
@@ -884,66 +915,33 @@
     real_font->used_on_this_page = 1;
   }
 
-  font_scale = (double) font->sptsize * dev_unit.dvi2pts;
-  len  = sprintf(format_buffer, " /%s", real_font->short_name); /* space not necessary. */
-  format_buffer[len++] = ' ';
-  len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len);
-  format_buffer[len++] = ' ';
-  format_buffer[len++] = 'T';
-  format_buffer[len++] = 'f';
-  pdf_doc_add_page_content(format_buffer, len);  /* op: Tf */
+  font_scale = (double) font->sptsize * p->unit.dvi2pts;
+  len  = sprintf(p->format_buffer, " /%s", real_font->short_name); /* space not necessary. */
+  p->format_buffer[len++] = ' ';
+  len += p_dtoa(font_scale, MIN(p->unit.precision+1, DEV_PRECISION_MAX),
+                p->format_buffer+len);
+  p->format_buffer[len++] = ' ';
+  p->format_buffer[len++] = 'T';
+  p->format_buffer[len++] = 'f';
+  dev_out(p, p->format_buffer, len);  /* op: Tf */
 
-  if (font->bold > 0.0 || font->bold != text_state.bold_param) {
+  if (font->bold > 0.0 || font->bold != p->text_state.bold_param) {
     if (font->bold <= 0.0)
-      len = sprintf(format_buffer, " 0 Tr");
+      len = sprintf(p->format_buffer, " 0 Tr");
     else
-      len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */
-    pdf_doc_add_page_content(format_buffer, len);  /* op: Tr w */
+      len = sprintf(p->format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */
+    dev_out(p, p->format_buffer, len);  /* op: Tr w */
   }
-  text_state.bold_param = font->bold;
+  p->text_state.bold_param = font->bold;
 
-  text_state.font_id    = font_id;
+  p->text_state.font_id    = font_id;
 
   return  0;
 }
 
-
-/* Access text state parameters.
+/* These tmp buffers can't be removed since the pointer to this can be
+ * used as the return value of handle_multibyte_string(): str_ptr can point these.
  */
-#if 0
-int
-pdf_dev_currentfont (void)
-{
-  return text_state.font_id;
-}
-
-double
-pdf_dev_get_font_ptsize (int font_id)
-{
-  struct dev_font *font;
-
-  font = GET_FONT(font_id);
-  if (font) {
-    return font->sptsize * dev_unit.dvi2pts;
-  }
-
-  return 1.0;
-}
-#endif
-
-int
-pdf_dev_get_font_wmode (int font_id)
-{
-  struct dev_font *font;
-
-  font = GET_FONT(font_id);
-  if (font) {
-    return font->wmode;
-  }
-
-  return 0;
-}
-
 static unsigned char sbuf0[FORMAT_BUF_SIZE];
 static unsigned char sbuf1[FORMAT_BUF_SIZE];
 
@@ -1048,37 +1046,6 @@
   return 0;
 }
 
-
-static pdf_coord *dev_coords = NULL;
-static int num_dev_coords = 0;
-static int max_dev_coords = 0;
-
-void pdf_dev_get_coord(double *xpos, double *ypos)
-{
-  if (num_dev_coords > 0) {
-    *xpos = dev_coords[num_dev_coords-1].x;
-    *ypos = dev_coords[num_dev_coords-1].y;
-  } else {
-    *xpos = *ypos = 0.0;
-  }
-}
-
-void pdf_dev_push_coord(double xpos, double ypos)
-{
-  if (num_dev_coords >= max_dev_coords) {
-    max_dev_coords += 4;
-    dev_coords = RENEW(dev_coords, max_dev_coords, pdf_coord);
-  }
-  dev_coords[num_dev_coords].x = xpos;
-  dev_coords[num_dev_coords].y = ypos;
-  num_dev_coords++;
-}
-
-void pdf_dev_pop_coord(void)
-{
-  if (num_dev_coords > 0) num_dev_coords--;
-}
-
 /*
  * ctype:
  *  -1 input string contains 2-byte Freetype glyph index values
@@ -1097,23 +1064,24 @@
                     spt_t width,
                     int   font_id, int ctype)
 {
-  struct dev_font *font;
-  struct dev_font *real_font;
+  pdf_dev             *p = current_device();
+  struct dev_font     *font;
+  struct dev_font     *real_font;
   const unsigned char *str_ptr; /* Pointer to the reencoded string. */
-  int              length, i, len = 0;
-  spt_t            kern, delh, delv;
-  spt_t            text_xorigin;
-  spt_t            text_yorigin;
+  int                  length, i, len = 0;
+  spt_t                kern, delh, delv;
+  spt_t                text_xorigin;
+  spt_t                text_yorigin;
 
-  if (font_id < 0 || font_id >= num_dev_fonts) {
-    ERROR("Invalid font: %d (%d)", font_id, num_dev_fonts);
+  if (font_id < 0 || font_id >= p->num_dev_fonts) {
+    ERROR("Invalid font: %d (%d)", font_id, p->num_dev_fonts);
     return;
   }
-  if (font_id != text_state.font_id) {
-    dev_set_font(font_id);
+  if (font_id != p->text_state.font_id) {
+    pdf_dev_set_font(p, font_id);
   }
 
-  font = CURRENTFONT();
+  font = CURRENTFONT(p);
   if (!font) {
     ERROR("Currentfont not set.");
     return;
@@ -1120,12 +1088,12 @@
   }
 
   if (font->real_font_index >= 0)
-    real_font = GET_FONT(font->real_font_index);
+    real_font = GET_FONT(p, font->real_font_index);
   else
     real_font = font;
 
-  text_xorigin = text_state.ref_x;
-  text_yorigin = text_state.ref_y;
+  text_xorigin = p->text_state.ref_x;
+  text_yorigin = p->text_state.ref_y;
 
   str_ptr = instr_ptr;
   length  = instr_len;
@@ -1148,9 +1116,9 @@
     }
   }
 
-  if (num_dev_coords > 0) {
-    xpos -= bpt2spt(dev_coords[num_dev_coords-1].x);
-    ypos -= bpt2spt(dev_coords[num_dev_coords-1].y);
+  if (p->num_dev_coords > 0) {
+    xpos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].x);
+    ypos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].y);
   }
 
   /*
@@ -1168,17 +1136,17 @@
    * (in 1000 units per em) but dvipdfmx does not take into account of this...
    */
 
-  if (text_state.dir_mode==0) {
+  if (p->text_state.dir_mode==0) {
     /* Left-to-right */
-    delh = text_xorigin + text_state.offset - xpos;
+    delh = text_xorigin + p->text_state.offset - xpos;
     delv = ypos - text_yorigin;
-  } else if (text_state.dir_mode==1) {
+  } else if (p->text_state.dir_mode==1) {
     /* Top-to-bottom */
-    delh = ypos - text_yorigin + text_state.offset;
+    delh = ypos - text_yorigin + p->text_state.offset;
     delv = xpos - text_xorigin;
   } else {
     /* Bottom-to-top */
-    delh = ypos + text_yorigin + text_state.offset;
+    delh = ypos + text_yorigin + p->text_state.offset;
     delv = xpos + text_xorigin;
   }
 
@@ -1192,10 +1160,10 @@
    */
 #define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize)
 
-  if (text_state.force_reset ||
-      labs(delv) > dev_unit.min_bp_val ||
+  if (p->text_state.force_reset ||
+      labs(delv) > p->unit.min_bp_val ||
       labs(delh) > WORD_SPACE_MAX(font)) {
-    text_mode();
+    pdf_dev_text_mode(p);
     kern = 0;
   } else {
     kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize);
@@ -1205,28 +1173,28 @@
    * single text block. There are point_size/1000 rounding error per character.
    * If you really care about accuracy, you should compensate this here too.
    */
-  if (motion_state != STRING_MODE)
-    string_mode(xpos, ypos,
-                font->slant, font->extend, text_state.matrix.rotate);
+  if (p->motion_state != STRING_MODE)
+    pdf_dev_string_mode(p, xpos, ypos,
+                        font->slant, font->extend, p->text_state.matrix.rotate);
   else if (kern != 0) {
     /*
      * Same issues as earlier. Use floating point for simplicity.
      * This routine needs to be fast, so we don't call sprintf() or strcpy().
      */
-    text_state.offset -= 
+    p->text_state.offset -= 
       (spt_t) (kern * font->extend * (font->sptsize / 1000.0));
-    format_buffer[len++] = text_state.is_mb ? '>' : ')';
+    p->format_buffer[len++] = p->text_state.is_mb ? '>' : ')';
     if (font->wmode)
-      len += p_itoa(-kern, format_buffer + len);
+      len += p_itoa(-kern, p->format_buffer + len);
     else {
-      len += p_itoa( kern, format_buffer + len);
+      len += p_itoa( kern, p->format_buffer + len);
     }
-    format_buffer[len++] = text_state.is_mb ? '<' : '(';
-    pdf_doc_add_page_content(format_buffer, len);  /* op: */
+    p->format_buffer[len++] = p->text_state.is_mb ? '<' : '(';
+    dev_out(p, p->format_buffer, len);  /* op: */
     len = 0;
   }
 
-  if (text_state.is_mb) {
+  if (p->text_state.is_mb) {
     if (FORMAT_BUF_SIZE - len < 2 * length)
       ERROR("Buffer overflow...");
     for (i = 0; i < length; i++) {
@@ -1234,22 +1202,40 @@
 
       first  = (str_ptr[i] >> 4) & 0x0f;
       second = str_ptr[i] & 0x0f;
-      format_buffer[len++] = ((first >= 10)  ? first  + 'W' : first  + '0');
-      format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0');
+      p->format_buffer[len++] = ((first >= 10)  ? first  + 'W' : first  + '0');
+      p->format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0');
     }
   } else {
-    len += pdfobj_escape_str(format_buffer + len,
+    len += pdfobj_escape_str(p->format_buffer + len,
                              FORMAT_BUF_SIZE - len, str_ptr, length);
   }
   /* I think if you really care about speed, you should avoid memcopy here. */
-  pdf_doc_add_page_content(format_buffer, len);  /* op: */
+  dev_out(p, p->format_buffer, len);  /* op: */
 
-  text_state.offset += width;
+  p->text_state.offset += width;
 }
 
 void
 pdf_init_device (double dvi2pts, int precision, int black_and_white)
 {
+  pdf_dev *p = current_device();
+
+  p->motion_state        = GRAPHICS_MODE;
+  p->unit.dvi2pts        = 0.0;
+  p->unit.min_bp_val     = 658;
+  p->unit.precision      = 2;
+  p->param.autorotate    = 1;
+  p->param.colormode     = 1;
+  p->text_state.font_id  = -1;
+  p->text_state.offset   = 0;
+  p->text_state.matrix.slant  = 0;
+  p->text_state.matrix.extend = 0;
+  p->text_state.matrix.rotate = 0;
+  p->text_state.bold_param  = 0;
+  p->text_state.dir_mode    = 0;
+  p->text_state.force_reset = 0;
+  p->text_state.is_mb       = 0;
+
   if (precision < 0 ||
       precision > DEV_PRECISION_MAX)
     WARN("Number of decimal digits out of range [0-%d].",
@@ -1256,46 +1242,54 @@
          DEV_PRECISION_MAX);
 
   if (precision < 0) {
-    dev_unit.precision  = 0;
+    p->unit.precision  = 0;
   } else if (precision > DEV_PRECISION_MAX) {
-    dev_unit.precision  = DEV_PRECISION_MAX;
+    p->unit.precision  = DEV_PRECISION_MAX;
   } else {
-    dev_unit.precision  = precision;
+    p->unit.precision  = precision;
   }
-  dev_unit.dvi2pts      = dvi2pts;
-  dev_unit.min_bp_val   = (int) ROUND(1.0/(ten_pow[dev_unit.precision]*dvi2pts), 1);
-  if (dev_unit.min_bp_val < 0)
-    dev_unit.min_bp_val = -dev_unit.min_bp_val;
+  p->unit.dvi2pts      = dvi2pts;
+  p->unit.min_bp_val   = (int) ROUND(1.0/(ten_pow[p->unit.precision]*dvi2pts), 1);
+  if (p->unit.min_bp_val < 0)
+    p->unit.min_bp_val = -p->unit.min_bp_val;
 
-  dev_param.colormode = (black_and_white ? 0 : 1);
+  p->param.colormode = (black_and_white ? 0 : 1);
 
-  graphics_mode();
+  pdf_dev_graphics_mode(p);
   pdf_color_clear_stack();
   pdf_dev_init_gstates();
 
-  num_dev_fonts  = max_dev_fonts = 0;
-  dev_fonts      = NULL;
-  num_dev_coords = max_dev_coords = 0;
-  dev_coords     = NULL;
+  p->num_dev_fonts  = p->max_dev_fonts = 0;
+  p->fonts          = NULL;
+  p->num_dev_coords = 0;
+  p->max_dev_coords = 0;
+  p->dev_coords     = NULL;
+
+  return;
 }
 
 void
 pdf_close_device (void)
 {
-  if (dev_fonts) {
+  pdf_dev *p = current_device();
+
+  if (p->fonts) {
     int    i;
 
-    for (i = 0; i < num_dev_fonts; i++) {
-      if (dev_fonts[i].tex_name)
-        RELEASE(dev_fonts[i].tex_name);
-      if (dev_fonts[i].resource)
-        pdf_release_obj(dev_fonts[i].resource);
-      dev_fonts[i].tex_name = NULL;
-      dev_fonts[i].resource = NULL;
+    for (i = 0; i < p->num_dev_fonts; i++) {
+      if (p->fonts[i].tex_name)
+        RELEASE(p->fonts[i].tex_name);
+      if (p->fonts[i].resource)
+        pdf_release_obj(p->fonts[i].resource);
+      p->fonts[i].tex_name = NULL;
+      p->fonts[i].resource = NULL;
     }
-    RELEASE(dev_fonts);
+    RELEASE(p->fonts);
+    p->fonts = NULL;
   }
-  if (dev_coords) RELEASE(dev_coords);
+  if (p->dev_coords)
+    RELEASE(p->dev_coords);
+  p->dev_coords = NULL;
   pdf_dev_clear_gstates();
 }
 
@@ -1307,22 +1301,23 @@
 void
 pdf_dev_reset_fonts (int newpage)
 {
-  int  i;
+  pdf_dev *p = current_device();
+  int      i;
 
-  for (i = 0; i < num_dev_fonts; i++) {
-    dev_fonts[i].used_on_this_page = 0;
+  for (i = 0; i < p->num_dev_fonts; i++) {
+    p->fonts[i].used_on_this_page = 0;
   }
 
-  text_state.font_id       = -1;
+  p->text_state.font_id       = -1;
 
-  text_state.matrix.slant  = 0.0;
-  text_state.matrix.extend = 1.0;
-  text_state.matrix.rotate = TEXT_WMODE_HH;
+  p->text_state.matrix.slant  = 0.0;
+  p->text_state.matrix.extend = 1.0;
+  p->text_state.matrix.rotate = TEXT_WMODE_HH;
 
   if (newpage)
-    text_state.bold_param  = 0.0;
+    p->text_state.bold_param  = 0.0;
 
-  text_state.is_mb         = 0;
+  p->text_state.is_mb         = 0;
 }
 
 void
@@ -1335,30 +1330,15 @@
   pdf_dev_set_color(fc, 0x20, force);
 }
 
-#if 0
-/* Not working */
 void
-pdf_dev_set_origin (double phys_x, double phys_y)
+pdf_dev_bop (const pdf_tmatrix *M)
 {
-  pdf_tmatrix M0, M1;
+  pdf_dev *p = current_device();
 
-  pdf_dev_currentmatrix(&M0);
-  pdf_dev_currentmatrix(&M1);
-  pdf_invertmatrix(&M1);
-  M0.e = phys_x; M0.f = phys_y;
-  pdf_concatmatrix(&M1, &M0);
+  pdf_dev_graphics_mode(p);
 
-  pdf_dev_concat(&M1);
-}
-#endif
+  p->text_state.force_reset  = 0;
 
-void
-pdf_dev_bop (const pdf_tmatrix *M)
-{
-  graphics_mode();
-
-  text_state.force_reset  = 0;
-
   pdf_dev_gsave();
   pdf_dev_concat(M);
 
@@ -1370,9 +1350,10 @@
 void
 pdf_dev_eop (void)
 {
-  int  depth;
+  pdf_dev *p = current_device();
+  int      depth;
 
-  graphics_mode();
+  pdf_dev_graphics_mode(p);
 
   depth = pdf_dev_current_depth();
   if (depth != 1) {
@@ -1433,6 +1414,7 @@
 int
 pdf_dev_locate_font (const char *font_name, spt_t ptsize)
 {
+  pdf_dev         *p = current_device();
   int              i;
   fontmap_rec     *mrec;
   struct dev_font *font;
@@ -1445,11 +1427,11 @@
     return -1;
   }
 
-  for (i = 0; i < num_dev_fonts; i++) {
-    if (strcmp(font_name, dev_fonts[i].tex_name) == 0) {
-      if (ptsize == dev_fonts[i].sptsize)
+  for (i = 0; i < p->num_dev_fonts; i++) {
+    if (strcmp(font_name, p->fonts[i].tex_name) == 0) {
+      if (ptsize == p->fonts[i].sptsize)
         return i; /* found a dev_font that matches the request */
-      if (dev_fonts[i].format != PDF_FONTTYPE_BITMAP)
+      if (p->fonts[i].format != PDF_FONTTYPE_BITMAP)
         break; /* new dev_font will share pdf resource with /i/ */
     }
   }
@@ -1458,12 +1440,12 @@
    * Make sure we have room for a new one, even though we may not
    * actually create one.
    */
-  if (num_dev_fonts >= max_dev_fonts) {
-    max_dev_fonts += 16;
-    dev_fonts      = RENEW(dev_fonts, max_dev_fonts, struct dev_font);
+  if (p->num_dev_fonts >= p->max_dev_fonts) {
+    p->max_dev_fonts += 16;
+    p->fonts      = RENEW(p->fonts, p->max_dev_fonts, struct dev_font);
   }
 
-  font = &dev_fonts[num_dev_fonts];
+  font = &p->fonts[p->num_dev_fonts];
 
   /* New font */
   mrec = pdf_lookup_fontmap_record(font_name);
@@ -1471,20 +1453,20 @@
   if (dpx_conf.verbose_level > 1)
     print_fontmap(font_name, mrec);
 
-  font->font_id = pdf_font_findresource(font_name, ptsize * dev_unit.dvi2pts, mrec);
+  font->font_id = pdf_font_findresource(font_name, ptsize * p->unit.dvi2pts, mrec);
   if (font->font_id < 0)
     return  -1;
 
   /* We found device font here. */
-  if (i < num_dev_fonts) {
+  if (i < p->num_dev_fonts) {
     font->real_font_index = i;
-    strcpy(font->short_name, dev_fonts[i].short_name);
+    strcpy(font->short_name, p->fonts[i].short_name);
   }
   else {
     font->real_font_index = -1;
     font->short_name[0] = 'F';
-    p_itoa(num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */
-    num_phys_fonts++;
+    p_itoa(p->num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */
+    p->num_phys_fonts++;
   }
 
   font->used_on_this_page = 0;
@@ -1543,33 +1525,33 @@
     }
   }
 
-  return  num_dev_fonts++;
+  return  p->num_dev_fonts++;
 }
 
 
 /* This does not remember current stroking width. */
 static int
-dev_sprint_line (char *buf, spt_t width,
+dev_sprint_line (pdf_dev *p, char *buf, spt_t width,
                  spt_t p0_x, spt_t p0_y, spt_t p1_x, spt_t p1_y)
 {
   int    len = 0;
   double w;
 
-  w = width * dev_unit.dvi2pts;
+  w = width * p->unit.dvi2pts;
 
-  len += p_dtoa(w, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), buf+len);
+  len += p_dtoa(w, MIN(p->unit.precision+1, DEV_PRECISION_MAX), buf+len);
   buf[len++] = ' ';
   buf[len++] = 'w';
   buf[len++] = ' ';
-  len += dev_sprint_bp(buf+len, p0_x, NULL);
+  len += dev_sprint_bp(p, buf+len, p0_x, NULL);
   buf[len++] = ' ';
-  len += dev_sprint_bp(buf+len, p0_y, NULL);
+  len += dev_sprint_bp(p, buf+len, p0_y, NULL);
   buf[len++] = ' ';
   buf[len++] = 'm';
   buf[len++] = ' ';
-  len += dev_sprint_bp(buf+len, p1_x, NULL);
+  len += dev_sprint_bp(p, buf+len, p1_x, NULL);
   buf[len++] = ' ';
-  len += dev_sprint_bp(buf+len, p1_y, NULL);
+  len += dev_sprint_bp(p, buf+len, p1_y, NULL);
   buf[len++] = ' ';
   buf[len++] = 'l';
   buf[len++] = ' ';
@@ -1583,35 +1565,36 @@
 void
 pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height)
 {
-  int    len = 0;
-  double width_in_bp;
+  pdf_dev *p = current_device();
+  int      len = 0;
+  double   width_in_bp;
 
-  if (num_dev_coords > 0) {
-    xpos -= bpt2spt(dev_coords[num_dev_coords-1].x);
-    ypos -= bpt2spt(dev_coords[num_dev_coords-1].y);
+  if (p->num_dev_coords > 0) {
+    xpos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].x);
+    ypos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].y);
   }
 
-  graphics_mode();
+  pdf_dev_graphics_mode(p);
 
-  format_buffer[len++] = ' ';
-  format_buffer[len++] = 'q';
-  format_buffer[len++] = ' ';
+  p->format_buffer[len++] = ' ';
+  p->format_buffer[len++] = 'q';
+  p->format_buffer[len++] = ' ';
   /* Don't use too thick line. */
-  width_in_bp = ((width < height) ? width : height) * dev_unit.dvi2pts;
+  width_in_bp = ((width < height) ? width : height) * p->unit.dvi2pts;
   if (width_in_bp < 0.0 || /* Shouldn't happen */
       width_in_bp > PDF_LINE_THICKNESS_MAX) {
     pdf_rect rect;
 
-    rect.llx =  dev_unit.dvi2pts * xpos;
-    rect.lly =  dev_unit.dvi2pts * ypos;
-    rect.urx =  dev_unit.dvi2pts * width;
-    rect.ury =  dev_unit.dvi2pts * height;
-    len += pdf_sprint_rect(format_buffer+len, &rect);
-    format_buffer[len++] = ' ';
-    format_buffer[len++] = 'r';
-    format_buffer[len++] = 'e';
-    format_buffer[len++] = ' ';
-    format_buffer[len++] = 'f';
+    rect.llx =  p->unit.dvi2pts * xpos;
+    rect.lly =  p->unit.dvi2pts * ypos;
+    rect.urx =  p->unit.dvi2pts * width;
+    rect.ury =  p->unit.dvi2pts * height;
+    len += pdf_dev_sprint_rect(p, p->format_buffer+len, &rect);
+    p->format_buffer[len++] = ' ';
+    p->format_buffer[len++] = 'r';
+    p->format_buffer[len++] = 'e';
+    p->format_buffer[len++] = ' ';
+    p->format_buffer[len++] = 'f';
   } else {
     if (width > height) {
       /* NOTE:
@@ -1619,11 +1602,11 @@
        *  device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2,
        *  "Details of Graphics State Parameters", p. 185.
        */
-      if (height < dev_unit.min_bp_val) {
+      if (height < p->unit.min_bp_val) {
         WARN("Too thin line: height=%ld (%g bp)", height, width_in_bp);
         WARN("Please consider using \"-d\" option.");
       }
-      len += dev_sprint_line(format_buffer+len,
+      len += dev_sprint_line(p, p->format_buffer+len,
                              height,
                              xpos,
                              ypos + height/2,
@@ -1630,11 +1613,11 @@
                              xpos + width,
                              ypos + height/2);
     } else {
-      if (width < dev_unit.min_bp_val) {
+      if (width < p->unit.min_bp_val) {
         WARN("Too thin line: width=%ld (%g bp)", width, width_in_bp);
         WARN("Please consider using \"-d\" option.");
       }
-      len += dev_sprint_line(format_buffer+len,
+      len += dev_sprint_line(p, p->format_buffer+len,
                              width,
                              xpos + width/2,
                              ypos,
@@ -1642,9 +1625,9 @@
                              ypos + height);
     }
   }
-  format_buffer[len++] = ' ';
-  format_buffer[len++] = 'Q';
-  pdf_doc_add_page_content(format_buffer, len);  /* op: q re f Q */
+  p->format_buffer[len++] = ' ';
+  p->format_buffer[len++] = 'Q';
+  dev_out(p, p->format_buffer, len);  /* op: q re f Q */
 }
 
 /* Rectangle in device space coordinate. */
@@ -1653,16 +1636,17 @@
                   spt_t x_user, spt_t y_user,
                   spt_t width,  spt_t height, spt_t depth)
 {
+  pdf_dev    *p = current_device();
   double      dev_x, dev_y;
   pdf_coord   p0, p1, p2, p3;
   double      min_x, min_y, max_x, max_y;
 
-  dev_x = x_user * dev_unit.dvi2pts;
-  dev_y = y_user * dev_unit.dvi2pts;
-  if (text_state.dir_mode) {
-    p0.x = dev_x - dev_unit.dvi2pts * depth;
-    p0.y = dev_y - dev_unit.dvi2pts * width;
-    p1.x = dev_x + dev_unit.dvi2pts * height;
+  dev_x = x_user * p->unit.dvi2pts;
+  dev_y = y_user * p->unit.dvi2pts;
+  if (p->text_state.dir_mode) {
+    p0.x = dev_x - p->unit.dvi2pts * depth;
+    p0.y = dev_y - p->unit.dvi2pts * width;
+    p1.x = dev_x + p->unit.dvi2pts * height;
     p1.y = p0.y;
     p2.x = p1.x;
     p2.y = dev_y;
@@ -1670,11 +1654,11 @@
     p3.y = p2.y;
   } else {
     p0.x = dev_x;
-    p0.y = dev_y - dev_unit.dvi2pts * depth;
-    p1.x = dev_x + dev_unit.dvi2pts * width;
+    p0.y = dev_y - p->unit.dvi2pts * depth;
+    p1.x = dev_x + p->unit.dvi2pts * width;
     p1.y = p0.y;
     p2.x = p1.x;
-    p2.y = dev_y + dev_unit.dvi2pts * height;
+    p2.y = dev_y + p->unit.dvi2pts * height;
     p3.x = p0.x;
     p3.y = p2.y;
   }
@@ -1711,20 +1695,22 @@
 int
 pdf_dev_get_dirmode (void)
 {
-  return text_state.dir_mode;
+  pdf_dev *p = current_device();
+  return p->text_state.dir_mode;
 }
 
 void
 pdf_dev_set_dirmode (int text_dir)
 {
+  pdf_dev *p = current_device();
   struct dev_font *font;
   int text_rotate;
   int vert_dir, vert_font;
 
-  font = CURRENTFONT();
+  font = CURRENTFONT(p);
 
   vert_font = (font && font->wmode) ? 1 : 0;
-  if (dev_param.autorotate) {
+  if (p->param.autorotate) {
     vert_dir = text_dir;
   } else {
     vert_dir = vert_font;
@@ -1732,48 +1718,51 @@
   text_rotate = (vert_font << 2)|vert_dir;
 
   if (font &&
-      ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) {
-    text_state.force_reset = 1;
+      ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
+    p->text_state.force_reset = 1;
   }
 
-  text_state.matrix.rotate = text_rotate;
-  text_state.dir_mode      = text_dir;
+  p->text_state.matrix.rotate = text_rotate;
+  p->text_state.dir_mode      = text_dir;
 }
 
 static void
-dev_set_param_autorotate (int auto_rotate)
+dev_set_param_autorotate (pdf_dev *p, int auto_rotate)
 {
   struct dev_font *font;
   int    text_rotate, vert_font, vert_dir;
 
-  font = CURRENTFONT();
+  ASSERT(p);
 
+  font = CURRENTFONT(p);
+
   vert_font = (font && font->wmode) ? 1 : 0;
   if (auto_rotate) {
-    vert_dir = text_state.dir_mode;
+    vert_dir = p->text_state.dir_mode;
   } else {
     vert_dir = vert_font;
   }
   text_rotate = (vert_font << 2)|vert_dir;
 
-  if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) {
-    text_state.force_reset = 1;
+  if (ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
+    p->text_state.force_reset = 1;
   }
-  text_state.matrix.rotate = text_rotate;
-  dev_param.autorotate     = auto_rotate;
+  p->text_state.matrix.rotate = text_rotate;
+  p->param.autorotate     = auto_rotate;
 }
 
 int
 pdf_dev_get_param (int param_type)
 {
+  pdf_dev *p = current_device();
   int value = 0;
 
   switch (param_type) {
   case PDF_DEV_PARAM_AUTOROTATE:
-    value = dev_param.autorotate;
+    value = p->param.autorotate;
     break;
   case PDF_DEV_PARAM_COLORMODE:
-    value = dev_param.colormode;
+    value = p->param.colormode;
     break;
   default:
     ERROR("Unknown device parameter: %d", param_type);
@@ -1785,12 +1774,14 @@
 void
 pdf_dev_set_param (int param_type, int value)
 {
+  pdf_dev *p = current_device();
+
   switch (param_type) {
   case PDF_DEV_PARAM_AUTOROTATE:
-    dev_set_param_autorotate(value);
+    dev_set_param_autorotate(p, value);
     break;
   case PDF_DEV_PARAM_COLORMODE:
-    dev_param.colormode = value; /* 0 for B&W */
+    p->param.colormode = value; /* 0 for B&W */
     break;
   default:
     ERROR("Unknown device parameter: %d", param_type);
@@ -1802,57 +1793,53 @@
 
 int
 pdf_dev_put_image (int             id,
-                   transform_info *p,
+                   transform_info *ti,
                    double          ref_x,
                    double          ref_y)
 {
+  pdf_dev     *p = current_device();
   char        *res_name;
   pdf_tmatrix  M, M1;
   pdf_rect     r;
   int          len = 0;
 
-  if (num_dev_coords > 0) {
-    ref_x -= dev_coords[num_dev_coords-1].x;
-    ref_y -= dev_coords[num_dev_coords-1].y;
+  if (p->num_dev_coords > 0) {
+    ref_x -= p->dev_coords[p->num_dev_coords-1].x;
+    ref_y -= p->dev_coords[p->num_dev_coords-1].y;
   }
 
-  pdf_copymatrix(&M, &(p->matrix));
+  pdf_copymatrix(&M, &(ti->matrix));
   M.e += ref_x; M.f += ref_y;
   /* Just rotate by -90, but not tested yet. Any problem if M has scaling? */
-  if (dev_param.autorotate &&
-      text_state.dir_mode) {
+  if (p->param.autorotate &&
+      p->text_state.dir_mode) {
     double tmp;
     tmp = -M.a; M.a = M.b; M.b = tmp;
     tmp = -M.c; M.c = M.d; M.d = tmp;
   }
 
-  graphics_mode();
+  pdf_dev_graphics_mode(p);
   pdf_dev_gsave();
 
-  pdf_ximage_scale_image(id, &M1, &r, p);
+  pdf_ximage_scale_image(id, &M1, &r, ti);
   pdf_concatmatrix(&M, &M1);
   pdf_dev_concat(&M);
 
   /* Clip */
-  if (p->flags & INFO_DO_CLIP) {
-#if  0
-    pdf_dev_newpath();
-    pdf_dev_moveto(r.llx, r.lly);
-    pdf_dev_lineto(r.urx, r.lly);
-    pdf_dev_lineto(r.urx, r.ury);
-    pdf_dev_lineto(r.llx, r.ury);
-    pdf_dev_closepath();
-    pdf_dev_clip();
-    pdf_dev_newpath();
-#else
+  if (ti->flags & INFO_DO_CLIP) {
     pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly);
-#endif
   }
 
   res_name = pdf_ximage_get_resname(id);
-  len = sprintf(work_buffer, " /%s Do", res_name);
-  pdf_doc_add_page_content(work_buffer, len);  /* op: Do */
+  {
+    char *buf;
 
+    buf = NEW(strlen(res_name)+6, char);
+    len = sprintf(buf, " /%s Do", res_name);
+    dev_out(p, buf, len);  /* op: Do */
+    RELEASE(buf);
+  }
+
   pdf_dev_grestore();
 
   pdf_doc_add_page_resource("XObject",
@@ -1861,12 +1848,12 @@
 
   if (dvi_is_tracking_boxes()) {
     pdf_tmatrix P;
-    int i;
-    pdf_rect rect;
-    pdf_coord corner[4];
+    int         i;
+    pdf_rect    rect;
+    pdf_coord   corner[4];
 
     pdf_dev_set_rect(&rect, 65536 * ref_x, 65536 * ref_y,
-	65536 * (r.urx - r.llx), 65536 * (r.ury - r.lly), 0);
+                     65536 * (r.urx - r.llx), 65536 * (r.ury - r.lly), 0);
 
     corner[0].x = rect.llx; corner[0].y = rect.lly;
     corner[1].x = rect.llx; corner[1].y = rect.ury;
@@ -1873,7 +1860,7 @@
     corner[2].x = rect.urx; corner[2].y = rect.ury;
     corner[3].x = rect.urx; corner[3].y = rect.lly;
 
-    pdf_copymatrix(&P, &(p->matrix));
+    pdf_copymatrix(&P, &(ti->matrix));
     for (i = 0; i < 4; ++i) {
       corner[i].x -= rect.llx;
       corner[i].y -= rect.lly;
@@ -1888,13 +1875,13 @@
     rect.ury = corner[0].y;
     for (i = 0; i < 4; ++i) {
       if (corner[i].x < rect.llx)
-	rect.llx = corner[i].x;
+        rect.llx = corner[i].x;
       if (corner[i].x > rect.urx)
-	rect.urx = corner[i].x;
+        rect.urx = corner[i].x;
       if (corner[i].y < rect.lly)
-	rect.lly = corner[i].y;
+        rect.lly = corner[i].y;
       if (corner[i].y > rect.ury)
-	rect.ury = corner[i].y;
+        rect.ury = corner[i].y;
     }
 
     pdf_doc_expand_box(&rect);
@@ -1903,7 +1890,6 @@
   return 0;
 }
 
-
 void
 transform_info_clear (transform_info *info)
 {
@@ -1926,7 +1912,8 @@
 void
 pdf_dev_begin_actualtext (uint16_t *unicodes, int count)
 {
-  int len, i, pdf_doc_enc = 1;
+  pdf_dev *p = current_device();
+  int      len, i, pdf_doc_enc = 1;
 
   /* check whether we can use PDFDocEncoding for this string
      (we punt on the 0x80..0xA0 range that does not directly correspond to unicode)  */
@@ -1937,16 +1924,15 @@
     }
   }
 
-  graphics_mode();
+  pdf_dev_graphics_mode(p);
 
-  len = sprintf(work_buffer, "\n/Span<</ActualText(");
-  if (!pdf_doc_enc) {
-    len += sprintf(work_buffer + len, "\xFE\xFF");
-  }
-  pdf_doc_add_page_content(work_buffer, len);
+  dev_out(p, "\n/Span << /ActualText (", 23);
+  if (!pdf_doc_enc)
+    dev_out(p, "\xFE\xFF", 2);
 
   while (count-- > 0) {
     unsigned char s[2] = { *unicodes >> 8, *unicodes & 0xff };
+    char          buf[32];
     i = pdf_doc_enc; /* if using PDFDocEncoding, we only care about the low 8 bits,
                         so start with the second byte of our pair */
     len = 0;
@@ -1953,25 +1939,129 @@
     for (; i < 2; i++) {
       unsigned char c = s[i];
       if (c == '(' || c == ')' || c == '\\') {
-        len += sprintf(work_buffer + len, "\\%c", c);
+        len += sprintf(buf + len, "\\%c", c);
       } else if (c < ' ') {
-        len += sprintf(work_buffer + len, "\\%03o", c);
+        len += sprintf(buf + len, "\\%03o", c);
       } else {
-        len += sprintf(work_buffer + len, "%c", c);
+        len += sprintf(buf + len, "%c", c);
       }
     }
-    pdf_doc_add_page_content(work_buffer, len);
+    dev_out(p, buf, len);
     ++unicodes;
   }
 
-  len = sprintf(work_buffer, ")>>BDC");
-  pdf_doc_add_page_content(work_buffer, len);
+  dev_out(p, ") >> BDC", 8);
 }
 
 void
 pdf_dev_end_actualtext (void)
 {
-  graphics_mode();
+  pdf_dev *p = current_device();
 
-  pdf_doc_add_page_content(" EMC", 4);
+  pdf_dev_graphics_mode(p);
+
+  dev_out(p, " EMC", 4);
 }
+
+/* Compatibility functions.... For other files still using old interface */
+void
+graphics_mode (void)
+{
+  pdf_dev *p = current_device();
+
+  pdf_dev_graphics_mode(p);
+}
+
+double
+dev_unit_dviunit (void)
+{
+  pdf_dev *p = current_device();
+  return pdf_dev_unit_dviunit(p);
+}
+
+int
+pdf_sprint_matrix (char *buf, const pdf_tmatrix *M)
+{
+  pdf_dev *p = current_device();
+  return (int) pdf_dev_sprint_matrix(p, buf, M);
+}
+
+int
+pdf_sprint_rect (char *buf, const pdf_rect *rect)
+{
+  pdf_dev *p = current_device();
+  return (int) pdf_dev_sprint_rect(p, buf, rect);
+}
+
+int
+pdf_sprint_coord (char *buf, const pdf_coord *c)
+{
+  pdf_dev *p = current_device();
+  return (int) pdf_dev_sprint_coord(p, buf, c);
+}
+
+int
+pdf_sprint_length (char *buf, double value)
+{
+  pdf_dev *p = current_device();
+  return (int) pdf_dev_sprint_length(p, buf, value);
+}
+
+int
+pdf_sprint_number (char *buf, double value)
+{
+  pdf_dev *p = current_device();
+  return (int) pdf_dev_sprint_number(p, buf, value);
+}
+
+/* Access text state parameters. */
+int
+pdf_dev_get_font_wmode (int font_id)
+{
+  pdf_dev *p = current_device();
+  struct dev_font *font;
+
+  font = GET_FONT(p, font_id);
+  if (font) {
+    return font->wmode;
+  }
+
+  return 0;
+}
+
+/* Saved text position compensation */
+void
+pdf_dev_get_coord (double *xpos, double *ypos)
+{
+  pdf_dev *p = current_device();
+
+  if (p->num_dev_coords > 0) {
+    *xpos = p->dev_coords[p->num_dev_coords-1].x;
+    *ypos = p->dev_coords[p->num_dev_coords-1].y;
+  } else {
+    *xpos = *ypos = 0.0;
+  }
+}
+
+void
+pdf_dev_push_coord (double xpos, double ypos)
+{
+  pdf_dev *p = current_device();
+
+  if (p->num_dev_coords >= p->max_dev_coords) {
+    p->max_dev_coords += 4;
+    p->dev_coords = RENEW(p->dev_coords, p->max_dev_coords, pdf_coord);
+  }
+  p->dev_coords[p->num_dev_coords].x = xpos;
+  p->dev_coords[p->num_dev_coords].y = ypos;
+  p->num_dev_coords++;
+}
+
+void
+pdf_dev_pop_coord (void)
+{
+  pdf_dev *p = current_device();
+
+  if (p->num_dev_coords > 0)
+    p->num_dev_coords--;
+}

Modified: trunk/Build/source/texk/dvipdfm-x/pdfdev.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfdev.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfdev.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2019 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -27,6 +27,8 @@
 #include "pdfobj.h"
 #include "pdfcolor.h"
 
+typedef struct pdf_dev pdf_dev;
+
 typedef int spt_t;
 
 typedef struct pdf_tmatrix
@@ -89,39 +91,6 @@
 /* returns 1.0/unit_conv */
 extern double dev_unit_dviunit  (void);
 
-#if 0
-/* DVI interpreter knows text positioning in relative motion.
- * However, pdf_dev_set_string() recieves text string with placement
- * in absolute position in user space, and it convert absolute
- * positioning back to relative positioning. It is quite wasteful.
- *
- * TeX using DVI register stack operation to do CR and then use down
- * command for LF. DVI interpreter knows hint for current leading
- * and others (raised or lowered), but they are mostly lost in
- * pdf_dev_set_string().
- */
-
-typedef struct
-{
-  int      argc;
-
-  struct {
-    int    is_kern; /* kern or string */
-
-    spt_t  kern;    /* negative kern means space */
-
-    int    offset;  /* offset to sbuf   */
-    int    length;  /* length of string */
-  } args[];
-
-  unsigned char sbuf[PDF_STRING_LEN_MAX];
-
-} pdf_text_string;
-
-/* Something for handling raise, leading, etc. here. */
-
-#endif
-
 /* Draw texts and rules:
  *
  * xpos, ypos, width, and height are all fixed-point numbers
@@ -134,15 +103,12 @@
  *   2 - input string is in 16-bit encoding.
  */
 extern void   pdf_dev_set_string (spt_t xpos, spt_t ypos,
-				  const void *instr_ptr, int instr_len,
-				  spt_t text_width,
-				  int   font_id, int ctype);
-extern void   pdf_dev_set_rule   (spt_t xpos, spt_t ypos,
-				  spt_t width, spt_t height);
+                                  const void *instr_ptr, int instr_len,
+                                  spt_t text_width, int font_id, int ctype);
+extern void   pdf_dev_set_rule   (spt_t xpos, spt_t ypos, spt_t width, spt_t height);
 
 /* Place XObject */
-extern int    pdf_dev_put_image  (int xobj_id,
-				  transform_info *p, double ref_x, double ref_y);
+extern int    pdf_dev_put_image  (int xobj_id, transform_info *p, double ref_x, double ref_y);
 
 /* The design_size and ptsize required by PK font support...
  */
@@ -151,18 +117,9 @@
 /* The following two routines are NOT WORKING.
  * Dvipdfmx doesn't manage gstate well..
  */
-#if 0
-/* pdf_dev_translate() or pdf_dev_concat() should be used. */
-extern void   pdf_dev_set_origin (double orig_x, double orig_y);
-#endif
-/* Always returns 1.0, please rename this. */
-extern double pdf_dev_scale      (void);
+#define pdf_dev_scale() (1.0)
 
 /* Access text state parameters. */
-#if 0
-extern int    pdf_dev_currentfont     (void); /* returns font_id */
-extern double pdf_dev_get_font_ptsize (int font_id);
-#endif
 extern int    pdf_dev_get_font_wmode  (int font_id); /* ps: special support want this (pTeX). */
 
 /* Text composition (direction) mode
@@ -214,11 +171,11 @@
  */
 extern void   graphics_mode (void);
 
-extern void   pdf_dev_get_coord(double *xpos, double *ypos);
-extern void   pdf_dev_push_coord(double xpos, double ypos);
-extern void   pdf_dev_pop_coord(void);
+extern void   pdf_dev_get_coord  (double *xpos, double *ypos);
+extern void   pdf_dev_push_coord (double xpos, double ypos);
+extern void   pdf_dev_pop_coord  (void);
 
 extern void   pdf_dev_begin_actualtext (uint16_t *unicodes, int len);
-extern void   pdf_dev_end_actualtext (void);
+extern void   pdf_dev_end_actualtext   (void);
 
 #endif /* _PDFDEV_H_ */

Modified: trunk/Build/source/texk/dvipdfm-x/pdfdoc.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfdoc.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfdoc.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -66,19 +66,6 @@
 #define PDFDOC_ARTICLE_ALLOC_SIZE 16
 #define PDFDOC_BEAD_ALLOC_SIZE    16
 
-static char  manual_thumb_enabled  = 0;
-static char *thumb_basename = NULL;
-
-void
-pdf_doc_enable_manual_thumbnails (void)
-{
-#if HAVE_LIBPNG
-  manual_thumb_enabled = 1;
-#else
-  WARN("Manual thumbnail is not supported without the libpng library.");
-#endif
-}
-
 static pdf_obj *
 read_thumbnail (const char *thumb_filename) 
 {
@@ -234,10 +221,12 @@
   struct {
     int    outline_open_depth;
     double annot_grow;
-  } opt;
+    int    enable_manual_thumb;
+  } options;
 
   struct form_list_node *pending_forms;
 
+  char *thumb_basename;
 } pdf_doc;
 static pdf_doc pdoc;
 
@@ -1257,7 +1246,7 @@
   pdf_olitem *item;
 
 #define MAX_OUTLINE_DEPTH 256u
-  p->opt.outline_open_depth =
+  p->options.outline_open_depth =
     ((bm_open_depth >= 0) ?
      bm_open_depth : MAX_OUTLINE_DEPTH - bm_open_depth);
 
@@ -1470,7 +1459,7 @@
     item = item->next;
   }
 
-#define BMOPEN(b,p) (((b) < 0) ? (((p)->outlines.current_depth > (p)->opt.outline_open_depth) ? 0 : 1) : (b))
+#define BMOPEN(b,p) (((b) < 0) ? (((p)->outlines.current_depth > (p)->options.outline_open_depth) ? 0 : 1) : (b))
 
 #if 0
   item->dict    = pdf_link_obj(dict);
@@ -2381,13 +2370,13 @@
     currentpage->resources = NULL;
   }
 
-  if (manual_thumb_enabled) {
+  if (p->options.enable_manual_thumb) {
     char    *thumb_filename;
     pdf_obj *thumb_ref;
 
-    thumb_filename = NEW(strlen(thumb_basename)+7, char);
+    thumb_filename = NEW(strlen(p->thumb_basename)+7, char);
     sprintf(thumb_filename, "%s.%ld",
-            thumb_basename, (p->pages.num_entries % 99999) + 1L);
+            p->thumb_basename, (p->pages.num_entries % 99999) + 1L);
     thumb_ref = read_thumbnail(thumb_filename);
     RELEASE(thumb_filename);
     if (thumb_ref)
@@ -2494,23 +2483,30 @@
 
 void
 pdf_open_document (const char *filename,
-                   const char *creator, const unsigned char *id1, const unsigned char *id2,
+                   const char *creator,
+                   const unsigned char *id1, const unsigned char *id2,
                    struct pdf_setting settings)
 {
   pdf_doc *p = &pdoc;
 
-  if (settings.enable_encrypt)
-    pdf_init_encryption(settings.encrypt, id1);
-
-  pdf_out_init(filename, settings.enable_encrypt,
+  pdf_out_init(filename, id1, id2,
+               settings.ver_major, settings.ver_minor, settings.object.compression_level,
+               settings.enable_encrypt,
                settings.object.enable_objstm, settings.object.enable_predictor);
   pdf_files_init();
 
   pdf_doc_init_catalog(p);
 
-  p->opt.annot_grow = settings.annot_grow_amount;
-  p->opt.outline_open_depth = settings.outline_open_depth;
+  /* After Catalog is created... */
+  if (settings.enable_encrypt) {
+    pdf_out_set_encrypt(settings.encrypt.key_size, settings.encrypt.permission,
+                        settings.encrypt.oplain, settings.encrypt.uplain,
+                        1, 1);
+  }
 
+  p->options.annot_grow = settings.annot_grow_amount;
+  p->options.outline_open_depth = settings.outline_open_depth;
+
   pdf_init_resources();
   pdf_init_colors();
   pdf_init_fonts();
@@ -2531,30 +2527,18 @@
 
   pdf_doc_set_bgcolor(NULL);
 
-  if (settings.enable_encrypt) {
-    pdf_obj *encrypt = pdf_encrypt_obj();
-    pdf_set_encrypt(encrypt);
-    pdf_release_obj(encrypt);
-  }
-  if (id1 && id2) {
-    pdf_obj *id_obj = pdf_new_array();
-
-    pdf_add_array(id_obj, pdf_new_string(id1, 16));
-    pdf_add_array(id_obj, pdf_new_string(id2, 16));
-    pdf_set_id(id_obj);
-  }
-
+  p->options.enable_manual_thumb = settings.enable_manual_thumb;
   /* Create a default name for thumbnail image files */
-  if (manual_thumb_enabled) {
+  if (p->options.enable_manual_thumb) {
     if (strlen(filename) > 4 &&
         !strncmp(".pdf", filename + strlen(filename) - 4, 4)) {
       size_t len = strlen(filename) - strlen(".pdf");
-      thumb_basename = NEW(len+1, char);
-      strncpy(thumb_basename, filename, len);
-      thumb_basename[len] = 0;
+      p->thumb_basename = NEW(len+1, char);
+      strncpy(p->thumb_basename, filename, len);
+      p->thumb_basename[len] = 0;
     } else {
-      thumb_basename = NEW(strlen(filename)+1, char);
-      strcpy(thumb_basename, filename);
+      p->thumb_basename = NEW(strlen(filename)+1, char);
+      strcpy(p->thumb_basename, filename);
     }
   }
 
@@ -2598,8 +2582,8 @@
   pdf_files_close();
   pdf_out_flush();
 
-  if (thumb_basename)
-    RELEASE(thumb_basename);
+  if (p->thumb_basename)
+    RELEASE(p->thumb_basename);
 
   return;
 }
@@ -2817,7 +2801,7 @@
 pdf_doc_break_annot (void)
 {
   pdf_doc *p = &pdoc;
-  double   g = p->opt.annot_grow;
+  double   g = p->options.annot_grow;
 
   if (breaking_state.dirty) {
     pdf_obj  *annot_dict, *annot_copy;

Modified: trunk/Build/source/texk/dvipdfm-x/pdfdoc.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfdoc.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfdoc.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -55,14 +55,17 @@
 struct pdf_obj_setting {
     int         enable_objstm;
     int         enable_predictor;
+    int         compression_level;
 };
 
 struct pdf_setting
 {
+    int    ver_major, ver_minor;
     double media_width, media_height;
     double annot_grow_amount;
     int    outline_open_depth;
     int    check_gotos;
+    int    enable_manual_thumb;
     int    enable_encrypt;
     struct pdf_enc_setting encrypt;
     struct pdf_dev_setting device;
@@ -71,7 +74,8 @@
 
 extern void pdf_open_document (const char *filename,
                                const char *creator,
-                               const unsigned char *id1, const unsigned char *id2,
+                               const unsigned char *id1,
+                               const unsigned char *id2,
                                struct pdf_setting settings);
 extern void pdf_close_document(void);
 

Modified: trunk/Build/source/texk/dvipdfm-x/pdfencrypt.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfencrypt.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfencrypt.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     This program is free software; you can redistribute it and/or modify
@@ -45,20 +45,13 @@
  * TODO: Convert password to PDFDocEncoding. SASLPrep stringpref for AESV3.
  */
 
-static void pdf_enc_set_passwd (unsigned int bits, unsigned int perm,
-                                const char *oplain, const char *uplain);
 
-/* PDF-2.0 is not published yet. */
 #define USE_ADOBE_EXTENSION 1
 
-#ifdef USE_ADOBE_EXTENSION
-#include "pdfdoc.h"
-#endif
-
 #include "dvipdfmx.h"
 #include "pdfencrypt.h"
 
-static struct pdf_sec {
+struct pdf_sec {
    unsigned char key[32];
    int           key_size;
 
@@ -78,8 +71,11 @@
      uint64_t objnum;
      uint16_t gennum;
    } label;
-} sec_data;
+};
 
+static void pdf_enc_set_password (pdf_sec *p_sec, unsigned int bits, unsigned int perm,
+                                  const char *oplain, const char *uplain);
+
 static const unsigned char padding_bytes[32] = {
   0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
   0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
@@ -87,31 +83,40 @@
   0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
 };
 
-int
-pdf_init_encryption (struct pdf_enc_setting settings, const unsigned char *trailer_id)
+pdf_sec *
+pdf_enc_init (const unsigned char *id,
+              int keybits, uint32_t permission,
+              const char *opasswd, const char *upasswd,
+              int use_aes, int encrypt_metadata)
 {
-  time_t          current_time;
-  struct pdf_sec *p = &sec_data;
+  time_t   current_time;
+  pdf_sec *p_sec;
 
-  if (trailer_id) {
-    memcpy(p->ID, trailer_id, 16);
-  } else {
-    memset(p->ID, 0, 16);
-  }
+  p_sec = NEW(1, pdf_sec);
+  memset(p_sec, 0, sizeof(pdf_sec));
   current_time = dpx_util_get_unique_time_if_given();
   if (current_time == INVALID_EPOCH_VALUE)
     current_time = time(NULL);
   srand(current_time); /* For AES IV */
-  p->setting.use_aes = settings.use_aes;
-  p->setting.encrypt_metadata = settings.encrypt_metadata;
-  p->setting.need_adobe_extension = 0;
+  p_sec->setting.use_aes              = use_aes;
+  p_sec->setting.encrypt_metadata     = encrypt_metadata;
+  p_sec->setting.need_adobe_extension = 0;
 
-  pdf_enc_set_passwd(settings.key_size, settings.permission,
-                     settings.oplain, settings.uplain);
+  memcpy(p_sec->ID, id, 16);
+  pdf_enc_set_password(p_sec, keybits, permission, opasswd, upasswd);
 
-  return 0;
+  return  p_sec;
 }
 
+void
+pdf_enc_close (pdf_sec **p_sec)
+{
+  if (p_sec && *p_sec) {
+    RELEASE(*p_sec);
+    *p_sec = NULL;
+  }
+}
+
 static void
 passwd_padding (const char *src, unsigned char *dst)
 {
@@ -124,10 +129,10 @@
 }
 
 static void
-compute_owner_password (struct pdf_sec *p,
+compute_owner_password (pdf_sec *p_sec,
                         const char *opasswd, const char *upasswd)
 {
-  int  i, j;
+  int           i, j;
   unsigned char padded[32];
   MD5_CONTEXT   md5;
   ARC4_CONTEXT  arc4;
@@ -138,7 +143,7 @@
   MD5_init (&md5);
   MD5_write(&md5, padded, 32);
   MD5_final(hash, &md5);
-  if (p->R >= 3) {
+  if (p_sec->R >= 3) {
     for (i = 0; i < 50; i++) {
       /*
        * NOTE: We truncate each MD5 hash as in the following step.
@@ -145,11 +150,11 @@
        *       Otherwise Adobe Reader won't decrypt the PDF file.
        */
       MD5_init (&md5);
-      MD5_write(&md5, hash, p->key_size);
+      MD5_write(&md5, hash, p_sec->key_size);
       MD5_final(hash, &md5);
     }
   }
-  ARC4_set_key(&arc4, p->key_size, hash);
+  ARC4_set_key(&arc4, p_sec->key_size, hash);
   passwd_padding(upasswd, padded);
   {
     unsigned char tmp1[32], tmp2[32];
@@ -156,21 +161,21 @@
     unsigned char key[16];
 
     ARC4(&arc4, 32, padded, tmp1);
-    if (p->R >= 3) {
+    if (p_sec->R >= 3) {
       for (i = 1; i <= 19; i++) {
         memcpy(tmp2, tmp1, 32);
-        for (j = 0; j < p->key_size; j++)
+        for (j = 0; j < p_sec->key_size; j++)
           key[j] = hash[j] ^ i;
-        ARC4_set_key(&arc4, p->key_size, key);
+        ARC4_set_key(&arc4, p_sec->key_size, key);
         ARC4(&arc4, 32, tmp2, tmp1);
       }
     }
-    memcpy(p->O, tmp1, 32);
+    memcpy(p_sec->O, tmp1, 32);
   }
 }
 
 static void
-compute_encryption_key (struct pdf_sec *p, const char *passwd)
+compute_encryption_key (pdf_sec *p_sec, const char *passwd)
 {
   int  i;
   unsigned char hash[32], padded[32];
@@ -179,20 +184,20 @@
   passwd_padding(passwd, padded);
   MD5_init (&md5);
   MD5_write(&md5, padded, 32);
-  MD5_write(&md5, p->O, 32);
+  MD5_write(&md5, p_sec->O, 32);
   {
     unsigned char tmp[4];
 
-    tmp[0] = (unsigned char)(p->P) & 0xFF;
-    tmp[1] = (unsigned char)(p->P >> 8) & 0xFF;
-    tmp[2] = (unsigned char)(p->P >> 16) & 0xFF;
-    tmp[3] = (unsigned char)(p->P >> 24) & 0xFF;
+    tmp[0] = (unsigned char)(p_sec->P) & 0xFF;
+    tmp[1] = (unsigned char)(p_sec->P >> 8) & 0xFF;
+    tmp[2] = (unsigned char)(p_sec->P >> 16) & 0xFF;
+    tmp[3] = (unsigned char)(p_sec->P >> 24) & 0xFF;
     MD5_write(&md5, tmp, 4);
   }
-  MD5_write(&md5, p->ID, 16);
+  MD5_write(&md5, p_sec->ID, 16);
 #if 0
   /* Not Supported Yet */
-  if (!p->setting.encrypt_metadata) {
+  if (!p_sec->setting.encrypt_metadata) {
     unsigned char tmp[4] = {0xff, 0xff, 0xff, 0xff};
     MD5_write(&md5, tmp, 4);
   }
@@ -199,7 +204,7 @@
 #endif
   MD5_final(hash, &md5);
 
-  if (p->R >= 3) {
+  if (p_sec->R >= 3) {
     for (i = 0; i < 50; i++) {
       /*
        * NOTE: We truncate each MD5 hash as in the following step.
@@ -206,15 +211,15 @@
        *       Otherwise Adobe Reader won't decrypt the PDF file.
        */
       MD5_init (&md5);
-      MD5_write(&md5, hash, p->key_size);
+      MD5_write(&md5, hash, p_sec->key_size);
       MD5_final(hash, &md5);
     }
   }
-  memcpy(p->key, hash, p->key_size);
+  memcpy(p_sec->key, hash, p_sec->key_size);
 }
 
 static void
-compute_user_password (struct pdf_sec *p, const char *uplain)
+compute_user_password (pdf_sec *p_sec, const char *uplain)
 {
   int           i, j;
   ARC4_CONTEXT  arc4;
@@ -221,11 +226,11 @@
   MD5_CONTEXT   md5;
   unsigned char upasswd[32];
 
-  compute_encryption_key(p, uplain);
+  compute_encryption_key(p_sec, uplain);
 
-  switch (p->R) {
+  switch (p_sec->R) {
   case 2:
-    ARC4_set_key(&arc4, p->key_size, p->key);
+    ARC4_set_key(&arc4, p_sec->key_size, p_sec->key);
     ARC4(&arc4, 32, padding_bytes, upasswd);
     break;
   case 3: case 4:
@@ -236,19 +241,19 @@
       MD5_init (&md5);
       MD5_write(&md5, padding_bytes, 32);
 
-      MD5_write(&md5, p->ID, 16);
+      MD5_write(&md5, p_sec->ID, 16);
       MD5_final(hash, &md5);
 
-      ARC4_set_key(&arc4, p->key_size, p->key);
+      ARC4_set_key(&arc4, p_sec->key_size, p_sec->key);
       ARC4(&arc4, 16, hash, tmp1);
 
-    for (i = 1; i <= 19; i++) {
+      for (i = 1; i <= 19; i++) {
         unsigned char key[16];
 
         memcpy(tmp2, tmp1, 16);
-        for (j = 0; j < p->key_size; j++)
-          key[j] = p->key[j] ^ i;
-        ARC4_set_key(&arc4, p->key_size, key);
+        for (j = 0; j < p_sec->key_size; j++)
+          key[j] = p_sec->key[j] ^ i;
+        ARC4_set_key(&arc4, p_sec->key_size, key);
         ARC4(&arc4, 16, tmp2, tmp1);
       }
       memcpy(upasswd, tmp1, 32);
@@ -258,7 +263,7 @@
     ERROR("Invalid revision number.");
   }
 
-  memcpy(p->U, upasswd, 32);
+  memcpy(p_sec->U, upasswd, 32);
 }
 
 /* Algorithm 2.B from ISO 32000-1 chapter 7 */
@@ -352,7 +357,7 @@
 }
 
 static void
-compute_owner_password_V5 (struct pdf_sec *p, const char *oplain)
+compute_owner_password_V5 (pdf_sec *p_sec, const char *oplain)
 {
   unsigned char  vsalt[8], ksalt[8], hash[32];
   unsigned char *OE, iv[AES_BLOCKSIZE];
@@ -364,20 +369,20 @@
     ksalt[i] = rand() % 256;
   }
 
-  compute_hash_V5(hash, oplain, vsalt, p->U, p->R);
-  memcpy(p->O,      hash,  32);
-  memcpy(p->O + 32, vsalt,  8);
-  memcpy(p->O + 40, ksalt,  8);
+  compute_hash_V5(hash, oplain, vsalt, p_sec->U, p_sec->R);
+  memcpy(p_sec->O,      hash,  32);
+  memcpy(p_sec->O + 32, vsalt,  8);
+  memcpy(p_sec->O + 40, ksalt,  8);
 
-  compute_hash_V5(hash, oplain, ksalt, p->U, p->R);
+  compute_hash_V5(hash, oplain, ksalt, p_sec->U, p_sec->R);
   memset(iv, 0, AES_BLOCKSIZE);
-  AES_cbc_encrypt(hash, 32, iv, 0, p->key, p->key_size, &OE, &OE_len);
-  memcpy(p->OE, OE, 32);
+  AES_cbc_encrypt(hash, 32, iv, 0, p_sec->key, p_sec->key_size, &OE, &OE_len);
+  memcpy(p_sec->OE, OE, 32);
   RELEASE(OE);
 }
 
 static void
-compute_user_password_V5 (struct pdf_sec *p, const char *uplain)
+compute_user_password_V5 (pdf_sec *p_sec, const char *uplain)
 {
   unsigned char  vsalt[8], ksalt[8], hash[32];
   unsigned char *UE, iv[AES_BLOCKSIZE];
@@ -389,36 +394,36 @@
     ksalt[i] = rand() % 256;
   }
 
-  compute_hash_V5(hash, uplain, vsalt, NULL, p->R);
-  memcpy(p->U,      hash,  32);
-  memcpy(p->U + 32, vsalt,  8);
-  memcpy(p->U + 40, ksalt,  8);
+  compute_hash_V5(hash, uplain, vsalt, NULL, p_sec->R);
+  memcpy(p_sec->U,      hash,  32);
+  memcpy(p_sec->U + 32, vsalt,  8);
+  memcpy(p_sec->U + 40, ksalt,  8);
 
-  compute_hash_V5(hash, uplain, ksalt, NULL, p->R);
+  compute_hash_V5(hash, uplain, ksalt, NULL, p_sec->R);
   memset(iv, 0, AES_BLOCKSIZE);
-  AES_cbc_encrypt(hash, 32, iv, 0, p->key, p->key_size, &UE, &UE_len);
-  memcpy(p->UE, UE, 32);
+  AES_cbc_encrypt(hash, 32, iv, 0, p_sec->key, p_sec->key_size, &UE, &UE_len);
+  memcpy(p_sec->UE, UE, 32);
   RELEASE(UE);
 }
 
 static void
-check_version (struct pdf_sec *p, int version)
+check_version (pdf_sec *p_sec, int version)
 {
-  if (p->V > 2 && version < 14) {
+  if (p_sec->V > 2 && version < 14) {
     WARN("Current encryption setting requires PDF version >= 1.4.");
-    p->V = 1;
-    p->key_size = 5;
-  } else if (p->V == 4 && version < 15) {
+    p_sec->V = 1;
+    p_sec->key_size = 5;
+  } else if (p_sec->V == 4 && version < 15) {
     WARN("Current encryption setting requires PDF version >= 1.5.");
-    p->V = 2;
-  } else if (p->V ==5 && version < 17) {
+    p_sec->V = 2;
+  } else if (p_sec->V ==5 && version < 17) {
     WARN("Current encryption setting requires PDF version >= 1.7" \
          " (plus Adobe Extension Level 3).");
-    p->V = 4;
-    p->key_size = 16;
+    p_sec->V = 4;
+    p_sec->key_size = 16;
   }
-  if (p->V == 5 && version < 20) {
-    p->setting.need_adobe_extension = 1;
+  if (p_sec->V == 5 && version < 20) {
+    p_sec->setting.need_adobe_extension = 1;
   }
 }
 
@@ -493,54 +498,55 @@
 }
 
 static void
-pdf_enc_set_passwd (unsigned int bits, unsigned int perm,
-                    const char *oplain, const char *uplain)
+pdf_enc_set_password (pdf_sec *p_sec, unsigned int bits, unsigned int perm,
+                      const char *oplain, const char *uplain)
 {
-  struct pdf_sec *p = &sec_data;
-  char            opasswd[128], upasswd[128];
-  int             version;
-  char            empty_passwd[1] = "\0";
+  char   opasswd[128], upasswd[128];
+  int    version;
+  char   empty_passwd[1] = "\0";
 
   version = pdf_get_version();
 
-  p->key_size = (int) (bits / 8);
-  if (p->key_size == 5) /* 40bit */
-    p->V = 1;
-  else if (p->key_size <= 16) {
-    p->V = p->setting.use_aes ? 4 : 2;
-  } else if (p->key_size == 32) {
-    p->V = 5;
+  p_sec->key_size = (int) (bits / 8);
+  if (p_sec->key_size == 5) { /* 40bit */
+    p_sec->V = 1;
+  } else if (p_sec->key_size < 16) {
+    p_sec->V = 2;
+  } else if (p_sec->key_size == 16) {
+    p_sec->V = p_sec->setting.use_aes ? 4 : 2;
+  } else if (p_sec->key_size == 32) {
+    p_sec->V = 5;
   } else {
     WARN("Key length %d unsupported.", bits);
-    p->key_size = 5;
-    p->V = 2;
+    p_sec->key_size = 5;
+    p_sec->V = 2;
   }
-  check_version(p, version);
+  check_version(p_sec, version);
 
-  p->P = (int32_t) (perm | 0xC0U);
+  p_sec->P = (int32_t) (perm | 0xC0U);
   /* Bit position 10 shall be always set to 1 for PDF >= 2.0. */
   if (version >= 20)
-    p->P |= (1 << 9);
-  switch (p->V) {
+    p_sec->P |= (1 << 9);
+  switch (p_sec->V) {
   case 1:
-    p->R = (p->P < 0x100L) ? 2 : 3;
+    p_sec->R = (p_sec->P < 0x100L) ? 2 : 3;
     break;
   case 2: case 3:
-    p->R = 3;
+    p_sec->R = 3;
     break;
   case 4:
-    p->R = 4;
+    p_sec->R = 4;
     break;
   case 5:
 #if USE_ADOBE_EXTENSION
-    p->R = 6;
+    p_sec->R = 6;
 #else
     WARN("Encryption V 5 unsupported.");
-    p->R = 4; p->V = 4;
+    p_sec->R = 4; p_sec->V = 4;
 #endif
     break;
   default:
-    p->R = 3;
+    p_sec->R = 3;
     break;
   }
 
@@ -548,54 +554,54 @@
   memset(upasswd, 0, 128);
   /* Password must be preprocessed. */
   if (oplain) {
-    if (preproc_password(oplain, opasswd, p->V) < 0)
+    if (preproc_password(oplain, opasswd, p_sec->V) < 0)
       WARN("Invaid UTF-8 string for password.");
   } else {
-    preproc_password(empty_passwd, opasswd, p->V);
+    preproc_password(empty_passwd, opasswd, p_sec->V);
   }
   if (uplain) {
-    if (preproc_password(uplain, upasswd, p->V) < 0)
+    if (preproc_password(uplain, upasswd, p_sec->V) < 0)
       WARN("Invalid UTF-8 string for passowrd.");
   } else {
-    preproc_password(empty_passwd, upasswd, p->V);
+    preproc_password(empty_passwd, upasswd, p_sec->V);
   }
 
-  if (p->R >= 3)
-    p->P |= 0xFFFFF000U;
+  if (p_sec->R >= 3)
+    p_sec->P |= 0xFFFFF000U;
 
-  if (p->V < 5) {
-    compute_owner_password(p, opasswd, upasswd);
-    compute_user_password (p, upasswd);
-  } else if (p->V == 5) {
+  if (p_sec->V < 5) {
+    compute_owner_password(p_sec, opasswd, upasswd);
+    compute_user_password (p_sec, upasswd);
+  } else if (p_sec->V == 5) {
     int i;
 
     for (i = 0; i < 32; i++)
-      p->key[i] = rand() % 256;
-    p->key_size = 32;
+      p_sec->key[i] = rand() % 256;
+    p_sec->key_size = 32;
     /* Order is important here */
-    compute_user_password_V5 (p, upasswd);
-    compute_owner_password_V5(p, opasswd); /* uses p->U */
+    compute_user_password_V5 (p_sec, upasswd);
+    compute_owner_password_V5(p_sec, opasswd); /* uses p_sec->U */
   }
 }
 
 static void
-calculate_key (struct pdf_sec *p, unsigned char *key)
+calculate_key (pdf_sec *p_sec, unsigned char *key)
 {
-  int           len = p->key_size + 5;
+  int           len = p_sec->key_size + 5;
   unsigned char tmp[25];
   MD5_CONTEXT   md5;
 
-  memcpy(tmp, p->key, p->key_size);
-  tmp[p->key_size  ] = (unsigned char) p->label.objnum        & 0xFF;
-  tmp[p->key_size+1] = (unsigned char)(p->label.objnum >>  8) & 0xFF;
-  tmp[p->key_size+2] = (unsigned char)(p->label.objnum >> 16) & 0xFF;
-  tmp[p->key_size+3] = (unsigned char)(p->label.gennum)       & 0xFF;
-  tmp[p->key_size+4] = (unsigned char)(p->label.gennum >>  8) & 0xFF;
-  if (p->V >= 4) {
-    tmp[p->key_size + 5] = 0x73;
-    tmp[p->key_size + 6] = 0x41;
-    tmp[p->key_size + 7] = 0x6c;
-    tmp[p->key_size + 8] = 0x54;
+  memcpy(tmp, p_sec->key, p_sec->key_size);
+  tmp[p_sec->key_size  ] = (unsigned char) p_sec->label.objnum        & 0xFF;
+  tmp[p_sec->key_size+1] = (unsigned char)(p_sec->label.objnum >>  8) & 0xFF;
+  tmp[p_sec->key_size+2] = (unsigned char)(p_sec->label.objnum >> 16) & 0xFF;
+  tmp[p_sec->key_size+3] = (unsigned char)(p_sec->label.gennum)       & 0xFF;
+  tmp[p_sec->key_size+4] = (unsigned char)(p_sec->label.gennum >>  8) & 0xFF;
+  if (p_sec->V >= 4) {
+    tmp[p_sec->key_size + 5] = 0x73;
+    tmp[p_sec->key_size + 6] = 0x41;
+    tmp[p_sec->key_size + 7] = 0x6c;
+    tmp[p_sec->key_size + 8] = 0x54;
     len += 4;
   }
   MD5_init (&md5);
@@ -604,49 +610,52 @@
 }
 
 void
-pdf_encrypt_data (const unsigned char *plain, size_t plain_len,
+pdf_encrypt_data (pdf_sec *p_sec,
+                  const unsigned char *plain, size_t plain_len,
                   unsigned char **cipher, size_t *cipher_len)
 {
-  struct pdf_sec *p = &sec_data;
-  unsigned char   key[32];
+  unsigned char key[32];
 
-  switch (p->V) {
+  ASSERT(p_sec);
+
+  switch (p_sec->V) {
   case 1: case 2:
-    calculate_key(p, key);
+    calculate_key(p_sec, key);
     {
       ARC4_CONTEXT arc4;
 
       *cipher_len = plain_len;
       *cipher     = NEW(*cipher_len, unsigned char);
-      ARC4_set_key(&arc4, MIN(16, p->key_size + 5), key);
+      ARC4_set_key(&arc4, MIN(16, p_sec->key_size + 5), key);
       ARC4(&arc4, plain_len, plain, *cipher);
     }
     break;
   case 4:
-    calculate_key(p, key);
-    AES_cbc_encrypt(key, MIN(16, p->key_size + 5), NULL, 1,
+    calculate_key(p_sec, key);
+    AES_cbc_encrypt(key, MIN(16, p_sec->key_size + 5), NULL, 1,
                     plain, plain_len, cipher, cipher_len);
     break;
   case 5:
-    AES_cbc_encrypt(p->key, p->key_size, NULL, 1,
+    AES_cbc_encrypt(p_sec->key, p_sec->key_size, NULL, 1,
                     plain, plain_len, cipher, cipher_len);
     break;
   default:
-    ERROR("pdfencrypt: Unexpected V value: %d", p->V);
+    ERROR("pdfencrypt: Unexpected V value: %d", p_sec->V);
     break;
   }
 }
 
 pdf_obj *
-pdf_encrypt_obj (void)
+pdf_enc_get_encrypt_dict (pdf_sec *p_sec)
 {
-  struct pdf_sec *p = &sec_data;
   pdf_obj *doc_encrypt;
 
+  ASSERT(p_sec);
+
   doc_encrypt = pdf_new_dict();
 
   pdf_add_dict(doc_encrypt,  pdf_new_name("Filter"), pdf_new_name("Standard"));
-  pdf_add_dict(doc_encrypt,  pdf_new_name("V"),      pdf_new_number(p->V));
+  pdf_add_dict(doc_encrypt,  pdf_new_name("V"),      pdf_new_number(p_sec->V));
 #if 0
   /* PDF reference describes it as:
    *
@@ -654,18 +663,18 @@
    *
    * but Acrobat *requires* this even for V 5!
    */
-  if (p->V > 1 && p->V < 4)
+  if (p_sec->V > 1 && p_sec->V < 4)
 #endif
     pdf_add_dict(doc_encrypt,
-                 pdf_new_name("Length"), pdf_new_number(p->key_size * 8));
-  if (p->V >= 4) {
+                 pdf_new_name("Length"), pdf_new_number(p_sec->key_size * 8));
+  if (p_sec->V >= 4) {
     pdf_obj *CF, *StdCF;
     CF    = pdf_new_dict();
     StdCF = pdf_new_dict();
     pdf_add_dict(StdCF, pdf_new_name("CFM"),
-                 pdf_new_name( (p->V == 4) ? "AESV2" : "AESV3" ));
+                 pdf_new_name( (p_sec->V == 4) ? "AESV2" : "AESV3" ));
     pdf_add_dict(StdCF, pdf_new_name("AuthEvent"), pdf_new_name("DocOpen"));
-    pdf_add_dict(StdCF, pdf_new_name("Length"),    pdf_new_number(p->key_size));
+    pdf_add_dict(StdCF, pdf_new_name("Length"),    pdf_new_number(p_sec->key_size));
     pdf_add_dict(CF, pdf_new_name("StdCF"), StdCF);
     pdf_add_dict(doc_encrypt, pdf_new_name("CF"), CF);
     pdf_add_dict(doc_encrypt, pdf_new_name("StmF"), pdf_new_name("StdCF"));
@@ -672,36 +681,36 @@
     pdf_add_dict(doc_encrypt, pdf_new_name("StrF"), pdf_new_name("StdCF"));
 #if 0
     /* NOT SUPPORTED YET */
-    if (!p->setting.encrypt_metadata)
+    if (!p_sec->setting.encrypt_metadata)
       pdf_add_dict(doc_encrypt,
                    pdf_new_name("EncryptMetadata"), pdf_new_boolean(false));
 #endif
   }
-  pdf_add_dict(doc_encrypt, pdf_new_name("R"), pdf_new_number(p->R));
-  if (p->V < 5) {
-    pdf_add_dict(doc_encrypt, pdf_new_name("O"), pdf_new_string(p->O, 32));
-    pdf_add_dict(doc_encrypt, pdf_new_name("U"), pdf_new_string(p->U, 32));
-  } else if (p->V == 5) {
-    pdf_add_dict(doc_encrypt, pdf_new_name("O"), pdf_new_string(p->O, 48));
-    pdf_add_dict(doc_encrypt, pdf_new_name("U"), pdf_new_string(p->U, 48));
+  pdf_add_dict(doc_encrypt, pdf_new_name("R"), pdf_new_number(p_sec->R));
+  if (p_sec->V < 5) {
+    pdf_add_dict(doc_encrypt, pdf_new_name("O"), pdf_new_string(p_sec->O, 32));
+    pdf_add_dict(doc_encrypt, pdf_new_name("U"), pdf_new_string(p_sec->U, 32));
+  } else if (p_sec->V == 5) {
+    pdf_add_dict(doc_encrypt, pdf_new_name("O"), pdf_new_string(p_sec->O, 48));
+    pdf_add_dict(doc_encrypt, pdf_new_name("U"), pdf_new_string(p_sec->U, 48));
   }
-  pdf_add_dict(doc_encrypt,	pdf_new_name("P"), pdf_new_number(p->P));
+  pdf_add_dict(doc_encrypt,	pdf_new_name("P"), pdf_new_number(p_sec->P));
 
-  if (p->V == 5) {
+  if (p_sec->V == 5) {
     unsigned char perms[16], *cipher = NULL;
     size_t        cipher_len = 0;
 
-    pdf_add_dict(doc_encrypt, pdf_new_name("OE"), pdf_new_string(p->OE, 32));
-    pdf_add_dict(doc_encrypt, pdf_new_name("UE"), pdf_new_string(p->UE, 32));
-    perms[0] =  p->P        & 0xff;
-    perms[1] = (p->P >>  8) & 0xff;
-    perms[2] = (p->P >> 16) & 0xff;
-    perms[3] = (p->P >> 24) & 0xff;
+    pdf_add_dict(doc_encrypt, pdf_new_name("OE"), pdf_new_string(p_sec->OE, 32));
+    pdf_add_dict(doc_encrypt, pdf_new_name("UE"), pdf_new_string(p_sec->UE, 32));
+    perms[0] =  p_sec->P        & 0xff;
+    perms[1] = (p_sec->P >>  8) & 0xff;
+    perms[2] = (p_sec->P >> 16) & 0xff;
+    perms[3] = (p_sec->P >> 24) & 0xff;
     perms[4] = 0xff;
     perms[5] = 0xff;
     perms[6] = 0xff;
     perms[7] = 0xff;
-    perms[8] = p->setting.encrypt_metadata ? 'T' : 'F';
+    perms[8] = p_sec->setting.encrypt_metadata ? 'T' : 'F';
     perms[9]  = 'a';
     perms[10] = 'd';
     perms[11] = 'b';
@@ -709,39 +718,47 @@
     perms[13] = 0;
     perms[14] = 0;
     perms[15] = 0;
-    AES_ecb_encrypt(p->key, p->key_size, perms, 16, &cipher, &cipher_len);
+    AES_ecb_encrypt(p_sec->key, p_sec->key_size, perms, 16, &cipher, &cipher_len);
     pdf_add_dict(doc_encrypt,
                  pdf_new_name("Perms"), pdf_new_string(cipher, cipher_len));
     RELEASE(cipher);
   }
+  
+  return doc_encrypt;
+}
 
+pdf_obj *
+pdf_enc_get_extension_dict (pdf_sec *p_sec)
+{
+  pdf_obj *ext = NULL, *adbe;
+
+  ASSERT(p_sec);
+
 #ifdef USE_ADOBE_EXTENSION
-  if (p->R > 5 && p->setting.need_adobe_extension != 0) {
-    pdf_obj *catalog = pdf_doc_catalog();
-    pdf_obj *ext  = pdf_new_dict();
-    pdf_obj *adbe = pdf_new_dict();
+  if (p_sec->setting.need_adobe_extension) {
+    ext  = pdf_new_dict();
+    adbe = pdf_new_dict();
 
     pdf_add_dict(adbe, pdf_new_name("BaseVersion"), pdf_new_name("1.7"));
     pdf_add_dict(adbe, pdf_new_name("ExtensionLevel"),
-                       pdf_new_number(p->R == 5 ? 3 : 8));
+                       pdf_new_number(p_sec->R == 5 ? 3 : 8));
     pdf_add_dict(ext, pdf_new_name("ADBE"), adbe);
-    pdf_add_dict(catalog, pdf_new_name("Extensions"), ext);
   }
 #endif
 
-  return doc_encrypt;
+  return ext;
 }
 
-void pdf_enc_set_label (unsigned label)
+void pdf_enc_set_label (pdf_sec *p_sec, unsigned label)
 {
-  struct pdf_sec *p = &sec_data;
+  ASSERT(p_sec);
 
-  p->label.objnum = label;
+  p_sec->label.objnum = label;
 }
 
-void pdf_enc_set_generation (unsigned generation)
+void pdf_enc_set_generation (pdf_sec *p_sec, unsigned generation)
 {
-  struct pdf_sec *p = &sec_data;
+  ASSERT(p_sec);
 
-  p->label.gennum = generation;
+  p_sec->label.gennum = generation;
 }

Modified: trunk/Build/source/texk/dvipdfm-x/pdfencrypt.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfencrypt.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfencrypt.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -2,7 +2,7 @@
 
     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2007-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     This program is free software; you can redistribute it and/or modify
@@ -28,11 +28,18 @@
 
 #define MAX_PWD_LEN 127
 
-extern int  pdf_init_encryption  (struct pdf_enc_setting, const unsigned char *trailer_id);
-extern void pdf_enc_set_label      (unsigned label);
-extern void pdf_enc_set_generation (unsigned generation);
-extern void pdf_encrypt_data (const unsigned char *plain, size_t plain_len,
-                              unsigned char **cipher, size_t *cipher_len);
-extern pdf_obj *pdf_encrypt_obj (void);
+typedef struct pdf_sec pdf_sec;
+extern pdf_sec *pdf_enc_init (const unsigned char *id,
+                              int keybits, uint32_t permission,
+                              const char *opasswd, const char *upasswd,
+                              int use_aes, int encrypt_metadata);
+extern void     pdf_enc_close (pdf_sec **p_sec);
 
+extern void     pdf_enc_set_label      (pdf_sec *p_sec, unsigned label);
+extern void     pdf_enc_set_generation (pdf_sec *p_sec, unsigned generation);
+extern void     pdf_encrypt_data (pdf_sec *p_sec, const unsigned char *plain, size_t plain_len,
+                                  unsigned char **cipher, size_t *cipher_len);
+extern pdf_obj *pdf_enc_get_encrypt_dict (pdf_sec *p_sec);
+extern pdf_obj *pdf_enc_get_extension_dict (pdf_sec *p_sec);
+
 #endif /* _PDFENCRYPT_H_ */

Modified: trunk/Build/source/texk/dvipdfm-x/pdfobj.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfobj.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfobj.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2007-2020 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -35,6 +35,7 @@
 #include "mfileio.h"
 #include "dpxconf.h"
 #include "dpxutil.h"
+
 #include "pdflimits.h"
 #include "pdfencrypt.h"
 #include "pdfparse.h"
@@ -60,13 +61,12 @@
 /* Any of these types can be represented as follows */
 struct pdf_obj 
 {
-  int type;
+  int      type;
 
-  unsigned int   label;  /* Only used for indirect objects
-			    all other "label" to zero */
-  unsigned short generation;  /* Only used if "label" is used */
-  unsigned refcount;  /* Number of links to this object */
-  int      flags;
+  uint32_t label;      /* Only used for indirect objects all other "label" to zero */
+  uint16_t generation; /* Only used if "label" is used */
+  int      refcount;   /* Number of links to this object */
+  int32_t  flags;
   void    *data;
 
 #if defined(PDFOBJ_DEBUG)
@@ -81,7 +81,7 @@
 
 struct pdf_boolean
 {
-  char  value;
+  char   value;
 };
 
 struct pdf_number
@@ -92,7 +92,7 @@
 struct pdf_string
 {
   unsigned char *string;
-  unsigned short length;
+  size_t         length;
 };
 
 struct pdf_name
@@ -102,8 +102,8 @@
 
 struct pdf_array
 {
-  unsigned int max;
-  unsigned int size;
+  size_t           max;
+  size_t           size;
   struct pdf_obj **values;
 };
 
@@ -138,8 +138,8 @@
   struct pdf_obj     *dict;
   unsigned char      *stream;
   int                *objstm_data;    /* used for object streams */
-  unsigned int        stream_length;
-  unsigned int        max_length;
+  size_t              stream_length;
+  size_t              max_length;
   int32_t             _flags;
   struct decode_parms decodeparms;
 };
@@ -146,10 +146,10 @@
 
 struct pdf_indirect
 {
-  pdf_file      *pf;
-  pdf_obj       *obj;             /* used when PF == NULL */
-  unsigned       label;
-  unsigned short generation;
+  pdf_file *pf;
+  pdf_obj  *obj;   /* used when PF == NULL */
+  uint32_t  label;
+  uint16_t  generation;
 };
 
 typedef void                pdf_null;
@@ -162,101 +162,182 @@
 typedef struct pdf_stream   pdf_stream;
 typedef struct pdf_indirect pdf_indirect;
 
-static FILE *pdf_output_file = NULL;
-
-static int pdf_output_file_position = 0;
-static int pdf_output_line_position = 0;
-static int compression_saved        = 0;
-
-#define FORMAT_BUF_SIZE 4096
-static char format_buffer[FORMAT_BUF_SIZE];
-
 typedef struct xref_entry
 {
-  unsigned char  type;       /* object storage type              */
-  unsigned int   field2;     /* offset in file or object stream  */
-  unsigned short field3;     /* generation or index              */
-  pdf_obj       *direct;     /* used for imported objects        */
-  pdf_obj       *indirect;   /* used for imported objects        */
+  uint8_t      type;       /* object storage type              */
+  uint32_t     field2;     /* offset in file or object stream  */
+  uint16_t     field3;     /* generation or index              */
+  pdf_obj     *direct;     /* used for imported objects        */
+  pdf_obj     *indirect;   /* used for imported objects        */
 } xref_entry;
 
-static xref_entry *output_xref;
-
-static unsigned int pdf_max_ind_objects;
-static unsigned int next_label;
-
-static unsigned int startxref;
-
 struct pdf_file
 {
-  FILE       *file;
-  pdf_obj    *trailer;
-  xref_entry *xref_table;
-  pdf_obj    *catalog;
-  int         num_obj;
-  int         file_size;
-  int         version;
+  FILE         *file;
+  pdf_obj      *trailer;
+  xref_entry   *xref_table;
+  pdf_obj      *catalog;
+  int           num_obj;
+  int           file_size;
+  int           version;
 };
 
-static pdf_obj *output_stream;
+static int error_out = 0;
 
 #define OBJSTM_MAX_OBJS  200
 /* the limit is only 100 for linearized PDF */
 
-static int enc_mode;
-static int doc_enc_mode;
+struct pdf_out {
+  struct {
+    int         enc_mode; /* boolean */
+  } state;
 
-static pdf_obj *trailer_dict;
-static pdf_obj *xref_stream;
+  unsigned char id1[16];
+  unsigned char id2[16];
 
+  struct {
+    int         major;
+    int         minor; 
+  } version;
+
+  struct {
+    struct {
+      int       level;
+      int       use_predictor;
+    } compression;
+
+    int         enable_encrypt;
+    int         use_objstm;
+  } options;
+
+  struct {
+    FILE       *file;
+    size_t      file_position;
+    int         line_position;
+    size_t      compression_saved;
+#if defined(LIBDPX)
+    size_t      file_stats;
+#endif /* LIBDPX */
+  } output;
+
+  struct {
+    uint32_t    next_label;
+    uint32_t    max_ind_objects;
+  } obj;
+
+  pdf_sec      *sec_data;
+
+  pdf_obj      *trailer;
+  uint32_t      startxref;
+  xref_entry *  xref_table;
+
+  pdf_obj      *xref_stream;
+  pdf_obj      *output_stream;
+  pdf_obj      *current_objstm;
+};
+
+/* Underway to reform PDF related code... For a moment place pdf_out
+ * object as a static variable. */
+static pdf_out pout;
+
+static pdf_out *
+current_output (void)
+{
+  return &pout;
+}
+
+static void
+init_pdf_out_struct (pdf_out *p)
+{
+  ASSERT(p);
+
+  p->state.enc_mode = 0;
+
+  memset(p->id1, 0, 16);
+  memset(p->id2, 0, 16);
+
+  p->version.major  = 1;
+  p->version.minor  = PDF_VERSION_DEFAULT;
+
+  p->options.compression.level = 9;
+  p->options.compression.use_predictor = 1;
+  p->options.enable_encrypt    = 0;
+  p->options.use_objstm        = 1;
+
+  p->output.file = NULL;
+  p->output.file_position = 0;
+  p->output.line_position = 0;
+  p->output.compression_saved = 0;
+#if defined(LIBDPX)
+  p->output.file_stats = 0;
+#endif /* LIBDPX */
+
+  p->obj.next_label = 1;
+  p->obj.max_ind_objects = 0;
+
+  p->sec_data   = NULL;
+  p->trailer    = NULL;
+  p->startxref  = 0;
+  p->xref_table = NULL;
+
+  p->xref_stream    = NULL;
+  p->output_stream  = NULL;
+  p->current_objstm = NULL;
+}
+
+static void
+clean_pdf_out_struct (pdf_out *p)
+{
+  memset(p, 0, sizeof(pdf_out));
+}
+
 /* Internal static routines */
 
-static int check_for_pdf_version (FILE *file);
+static int      check_for_pdf_version (FILE *file);
 
-static void pdf_flush_obj (pdf_obj *object, FILE *file);
-static void pdf_label_obj (pdf_obj *object);
-static void pdf_write_obj (pdf_obj *object, FILE *file);
+static void     pdf_flush_obj (pdf_out *p, pdf_obj *object);
+static void     pdf_label_obj (pdf_out *p, pdf_obj *object);
+static void     pdf_write_obj (pdf_out *p, pdf_obj *object);
 
-static void  set_objstm_data (pdf_obj *objstm, int *data);
-static int  *get_objstm_data (pdf_obj *objstm);
-static void  release_objstm  (pdf_obj *objstm);
+static void     set_objstm_data (pdf_obj *objstm, int *data);
+static int     *get_objstm_data (pdf_obj *objstm);
+static void     release_objstm  (pdf_obj *objstm);
 
-static void pdf_out_char (FILE *file, char c);
-static void pdf_out      (FILE *file, const void *buffer, int length);
+static void     pdf_out_char (pdf_out *p, char c);
+static void     pdf_out_str  (pdf_out *p, const void *buffer, size_t length);
 
-static pdf_obj *pdf_new_ref  (pdf_obj *object);
-static void release_indirect (pdf_indirect *data);
-static void write_indirect   (pdf_indirect *indirect, FILE *file);
+static pdf_obj *pdf_new_ref      (pdf_out *p, pdf_obj *object);
+static void     release_indirect (pdf_indirect *data);
+static void     write_indirect   (pdf_out *p, pdf_indirect *indirect);
 
-static void release_boolean (pdf_obj *data);
-static void write_boolean   (pdf_boolean *data, FILE *file);
+static void     release_boolean (pdf_obj *data);
+static void     write_boolean   (pdf_out *p, pdf_boolean *data);
 
-static void write_null   (FILE *file);
+static void     write_null      (pdf_out *p);
 
-static void release_number (pdf_number *number);
-static void write_number   (pdf_number *number, FILE *file);
+static void     release_number  (pdf_number *number);
+static void     write_number    (pdf_out *p, pdf_number *number);
 
-static void write_string   (pdf_string *str, FILE *file);
-static void release_string (pdf_string *str);
+static void     write_string    (pdf_out *p, pdf_string *str);
+static void     release_string  (pdf_string *str);
 
-static void write_name   (pdf_name *name, FILE *file);
-static void release_name (pdf_name *name);
+static void     write_name      (pdf_out *p, pdf_name *name);
+static void     release_name    (pdf_name *name);
 
-static void write_array   (pdf_array *array, FILE *file);
-static void release_array (pdf_array *array);
+static void     write_array     (pdf_out *p, pdf_array *array);
+static void     release_array   (pdf_array *array);
 
-static void write_dict   (pdf_dict *dict, FILE *file);
-static void release_dict (pdf_dict *dict);
+static void     write_dict      (pdf_out *p, pdf_dict *dict);
+static void     release_dict    (pdf_dict *dict);
 
-static void write_stream   (pdf_stream *stream, FILE *file);
-static void release_stream (pdf_stream *stream);
+static void     write_stream    (pdf_out *p, pdf_stream *stream);
+static void     release_stream  (pdf_stream *stream);
 
-static char compression_level = 9;
-static char compression_use_predictor = 1;
+static void
+pdf_out_set_compression (pdf_out *p, int level)
+{
+  ASSERT(p);
 
-void
-pdf_set_compression (int level)
-{
 #ifndef   HAVE_ZLIB
   ERROR("You don't have compression compiled in. Possibly libz wasn't found by configure.");
 #else
@@ -265,7 +346,7 @@
     WARN("Unable to set compression level -- your zlib doesn't have compress2().");
 #endif
   if (level >= 0 && level <= 9) 
-    compression_level = level;
+    p->options.compression.level = level;
   else {
     ERROR("set_compression: invalid compression level: %d", level);
   }
@@ -277,17 +358,24 @@
 FILE *
 pdf_get_output_file (void)
 {
-  return pdf_output_file;
+  pdf_out *p = current_output();
+  return p->output.file;
 }
 
-static int pdf_version = PDF_VERSION_DEFAULT;
+static void
+pdf_out_set_version (pdf_out *p, int ver_major, int ver_minor)
+{
+  int version;
 
-void
-pdf_set_version (int version)
-{
+  ASSERT(p);
+
+  version = ver_major * 10 + ver_minor;
   /* Don't forget to update CIDFont_stdcc_def[] in cid.c too! */
   if (version >= PDF_VERSION_MIN && version <= PDF_VERSION_MAX) {
-    pdf_version = version;
+    p->version.major = ver_major;
+    p->version.minor = ver_minor;
+  } else {
+    WARN("Unsupported PDF version %d.%d ... Ignoring.", ver_major, ver_minor);
   }
 }
 
@@ -294,84 +382,107 @@
 int
 pdf_get_version (void)
 {
-  return pdf_version;
+  pdf_out *p = current_output();
+  return (p->version.major * 10 + p->version.minor);
 }
 
 int
 pdf_get_version_major (void)
 {
-  return pdf_version/10;
+  pdf_out *p = current_output();
+  return p->version.major;
 }
 
 int
 pdf_get_version_minor (void)
 {
-  return pdf_version%10;
+  pdf_out *p = current_output();
+  return p->version.minor;
 }
 
 int
 pdf_check_version (int major, int minor)
 {
-  return (pdf_version >= major*10+minor) ? 0 : -1;
+  pdf_out *p = current_output();
+  if (p->version.major > major)
+    return 0;
+  else if (p->version.major < major)
+    return -1;
+  else {
+    return (p->version.minor >= minor) ? 0 : -1;
+  }
+
+  return -1;
 }
 
-static pdf_obj *current_objstm = NULL;
-static int do_objstm;
-
 static void
-add_xref_entry (unsigned label, unsigned char type, unsigned int field2, unsigned short field3)
+add_xref_entry (pdf_out *p,
+                uint32_t label, uint8_t type, uint32_t field2, uint16_t field3)
 {
-  if (label >= pdf_max_ind_objects) {
-    pdf_max_ind_objects = (label/IND_OBJECTS_ALLOC_SIZE+1)*IND_OBJECTS_ALLOC_SIZE;
-    output_xref = RENEW(output_xref, pdf_max_ind_objects, xref_entry);
+  ASSERT(p);
+
+  if (label >= p->obj.max_ind_objects) {
+    p->obj.max_ind_objects = (label/IND_OBJECTS_ALLOC_SIZE+1)*IND_OBJECTS_ALLOC_SIZE;
+    p->xref_table = RENEW(p->xref_table, p->obj.max_ind_objects, xref_entry);
   }
 
-  output_xref[label].type   = type;
-  output_xref[label].field2 = field2;
-  output_xref[label].field3 = field3;
-  output_xref[label].direct   = NULL;
-  output_xref[label].indirect = NULL;
+  p->xref_table[label].type     = type;
+  p->xref_table[label].field2   = field2;
+  p->xref_table[label].field3   = field3;
+  p->xref_table[label].direct   = NULL;
+  p->xref_table[label].indirect = NULL;
 }
 
 #define BINARY_MARKER "%\344\360\355\370\n"
-void
+pdf_out *
 pdf_out_init (const char *filename,
-              int do_encryption, int enable_objstm, int enable_predictor)
+              const unsigned char *id1,
+              const unsigned char *id2,
+              int ver_major, int ver_minor, int compression_level,
+              int enable_encrypt,
+              int enable_objstm,
+              int enable_predictor)
 {
-  char v;
+  pdf_out  *p = current_output();
+  char      v;
 
-  output_xref = NULL;
-  pdf_max_ind_objects = 0;
-  add_xref_entry(0, 0, 0, 0xffff);
-  next_label = 1;
+  init_pdf_out_struct(p);
 
-  if (pdf_version >= 15) {
+  pdf_out_set_version(p, ver_major, ver_minor);
+  pdf_out_set_compression(p, compression_level);
+
+  add_xref_entry(p, 0, 0, 0, 0xffff);
+
+  /* This must be set before pdf_set_root() is called */
+  p->options.enable_encrypt = enable_encrypt;
+  if (pdf_check_version(1, 5) == 0) {
     if (enable_objstm) {
-      xref_stream = pdf_new_stream(STREAM_COMPRESS);
-      xref_stream->flags |= OBJ_NO_ENCRYPT;
-      trailer_dict = pdf_stream_dict(xref_stream);
-      pdf_add_dict(trailer_dict, pdf_new_name("Type"), pdf_new_name("XRef"));
-      do_objstm = 1;
+      p->xref_stream         = pdf_new_stream(STREAM_COMPRESS);
+      p->xref_stream->flags |= OBJ_NO_ENCRYPT;
+      p->trailer             = pdf_stream_dict(p->xref_stream);
+      pdf_add_dict(p->trailer, pdf_new_name("Type"), pdf_new_name("XRef"));
+      p->options.use_objstm  = 1;
     } else {
-      trailer_dict = pdf_new_dict();
-      do_objstm = 0;
+      p->xref_stream         = NULL;
+      p->trailer             = pdf_new_dict();
+      p->options.use_objstm  = 0;
     }
   } else {
-    xref_stream = NULL;
-    trailer_dict = pdf_new_dict();
-    do_objstm = 0;
+    p->xref_stream        = NULL;
+    p->trailer            = pdf_new_dict();
+    p->options.use_objstm = 0;
   }
 
-  output_stream = NULL;
+  p->output_stream = NULL;
 
   if (filename == NULL) { /* no filename: writing to stdout */
 #ifdef WIN32
     setmode(fileno(stdout), _O_BINARY);
 #endif
-    pdf_output_file = stdout;
+    p->output.file = stdout;
   } else {
-    pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE);
-    if (!pdf_output_file) {
+    p->output.file = MFOPEN(filename, FOPEN_WBIN_MODE);
+    if (!p->output.file) {
       if (strlen(filename) < 128)
         ERROR("Unable to open \"%s\".", filename);
       else
@@ -378,55 +489,102 @@
         ERROR("Unable to open file.");
     }
   }
-  pdf_out(pdf_output_file, "%PDF-", strlen("%PDF-"));
-  v = '0' + (pdf_version / 10);
-  pdf_out(pdf_output_file, &v, 1);
-  pdf_out(pdf_output_file, ".", 1);
-  v = '0' + (pdf_version % 10);
-  pdf_out(pdf_output_file, &v, 1);
-  pdf_out(pdf_output_file, "\n", 1);
-  pdf_out(pdf_output_file, BINARY_MARKER, strlen(BINARY_MARKER));
+  pdf_out_str(p, "%PDF-", strlen("%PDF-"));
+  v = '0' + p->version.major;
+  pdf_out_str(p, &v, 1);
+  pdf_out_str(p, ".", 1);
+  v = '0' + p->version.minor;
+  pdf_out_str(p, &v, 1);
+  pdf_out_str(p, "\n", 1);
+  pdf_out_str(p, BINARY_MARKER, strlen(BINARY_MARKER));
 
-  enc_mode = 0;
-  doc_enc_mode = do_encryption;
-  compression_use_predictor = enable_predictor;
+  /* Set trailer ID and setup security handler */
+  {
+    pdf_obj       *id_array;
+
+    memcpy(p->id1, id1, 16);
+    memcpy(p->id2, id2, 16);
+    id_array = pdf_new_array();
+    pdf_add_array(id_array, pdf_new_string(p->id1, 16));
+    pdf_add_array(id_array, pdf_new_string(p->id2, 16));
+    pdf_add_dict(p->trailer, pdf_new_name("ID"), id_array);
+  }
+  p->state.enc_mode = 0;
+  p->options.compression.use_predictor = enable_predictor;
+
+  return p;
 }
 
+void
+pdf_out_set_encrypt (int keybits, int32_t permission,
+                     const char *opasswd, const char *upasswd,
+                     int use_aes, int encrypt_metadata)
+{
+  pdf_out *p = current_output();
+
+  pdf_obj *encrypt, *extension, *catalog;
+
+  p->sec_data = pdf_enc_init(p->id1, keybits, permission,
+                               opasswd, upasswd, use_aes, encrypt_metadata);
+  if (!p->sec_data) {
+    p->options.enable_encrypt = 0;
+    return;
+  }
+
+  encrypt = pdf_enc_get_encrypt_dict(p->sec_data);
+  pdf_add_dict(p->trailer,
+               pdf_new_name("Encrypt"), pdf_ref_obj(encrypt));
+  encrypt->flags |= OBJ_NO_ENCRYPT;
+  encrypt->flags |= OBJ_NO_OBJSTM;
+  pdf_release_obj(encrypt);
+  
+  extension = pdf_enc_get_extension_dict(p->sec_data);
+  if (extension) {
+    catalog = pdf_doc_catalog();
+    pdf_add_dict(catalog, pdf_new_name("Extensions"), extension);
+  }
+}
+
 static void
-dump_xref_table (void)
+dump_xref_table (pdf_out *p)
 {
-  int length;
-  unsigned int i;
+  int   i, length;
+  char  buf[32];
 
-  pdf_out(pdf_output_file, "xref\n", 5);
+  ASSERT(p);
 
-  length = sprintf(format_buffer, "%d %u\n", 0, next_label);
-  pdf_out(pdf_output_file, format_buffer, length);
+  pdf_out_str(p, "xref\n", 5);
 
+  length = sprintf(buf, "%d %u\n", 0, p->obj.next_label);
+  pdf_out_str(p, buf, length);
+
   /*
    * Every space counts.  The space after the 'f' and 'n' is * *essential*.
    * The PDF spec says the lines must be 20 characters long including the
    * end of line character.
    */
-  for (i = 0; i < next_label; i++) {
-    unsigned char type = output_xref[i].type;
+  for (i = 0; i < p->obj.next_label; i++) {
+    uint8_t type = p->xref_table[i].type;
     if (type > 1)
       ERROR("object type %hu not allowed in xref table", type);
-    length = sprintf(format_buffer, "%010u %05hu %c \n",
-		     output_xref[i].field2, output_xref[i].field3,
-		     type ? 'n' : 'f');
-    pdf_out(pdf_output_file, format_buffer, length);
+    length = sprintf(buf, "%010u %05hu %c \n",
+                     p->xref_table[i].field2, p->xref_table[i].field3,
+                     type ? 'n' : 'f');
+    pdf_out_str(p, buf, length);
   }
 }
 
 static void
-dump_trailer_dict (void)
+dump_trailer (pdf_out *p)
 {
-  pdf_out(pdf_output_file, "trailer\n", 8);
-  enc_mode = 0;
-  write_dict(trailer_dict->data, pdf_output_file);
-  pdf_release_obj(trailer_dict);
-  pdf_out_char(pdf_output_file, '\n');
+  ASSERT(p);
+
+  pdf_out_str(p, "trailer\n", 8);
+  p->state.enc_mode = 0;
+  write_dict(p, p->trailer->data);
+  pdf_release_obj(p->trailer);
+  p->trailer = NULL;
+  pdf_out_char(p, '\n');
 }
 
 /*
@@ -434,16 +592,17 @@
  * contributed by Matthias Franz (March 21, 2007)
  */
 static void
-dump_xref_stream (void)
+dump_xref_stream (pdf_out *p)
 {
-  unsigned int pos, i;
-  unsigned poslen;
+  uint32_t      pos, i;
+  uint32_t      poslen;
   unsigned char buf[7] = {0, 0, 0, 0, 0};
+  pdf_obj      *w;
 
-  pdf_obj *w;
+  ASSERT(p);
 
   /* determine the necessary size of the offset field */
-  pos = startxref; /* maximal offset value */
+  pos = p->startxref; /* maximal offset value */
   poslen = 1;
   while (pos >>= 8)
     poslen++;
@@ -452,35 +611,36 @@
   pdf_add_array(w, pdf_new_number(1));      /* type                */
   pdf_add_array(w, pdf_new_number(poslen)); /* offset (big-endian) */
   pdf_add_array(w, pdf_new_number(2));      /* generation          */
-  pdf_add_dict(trailer_dict, pdf_new_name("W"), w);
+  pdf_add_dict(p->trailer, pdf_new_name("W"), w);
 
   /* We need the xref entry for the xref stream right now */
-  add_xref_entry(next_label-1, 1, startxref, 0);
+  add_xref_entry(p, p->obj.next_label - 1, 1, p->startxref, 0);
 
-  for (i = 0; i < next_label; i++) {
-    unsigned j;
-    unsigned short f3;
-    buf[0] = output_xref[i].type;
-    pos = output_xref[i].field2;
+  for (i = 0; i < p->obj.next_label; i++) {
+    size_t   j;
+    uint16_t f3;
+    buf[0] = p->xref_table[i].type;
+    pos    = p->xref_table[i].field2;
     for (j = poslen; j--; ) {
       buf[1+j] = (unsigned char) pos;
       pos >>= 8;
     }
-    f3 = output_xref[i].field3;
+    f3 = p->xref_table[i].field3;
     buf[poslen+1] = (unsigned char) (f3 >> 8);
     buf[poslen+2] = (unsigned char) (f3);
-    pdf_add_stream(xref_stream, &buf, poslen+3);
+    pdf_add_stream(p->xref_stream, &buf, poslen+3);
   }
 
-  pdf_release_obj(xref_stream);
+  pdf_release_obj(p->xref_stream);
+  p->xref_stream = NULL;
 }
 
 #if defined(LIBDPX)
-static long pdf_output_file_stats = 0;
 long
 pdf_output_stats (void)
 {
-  return pdf_output_file_stats;
+  pdf_out *p = current_output();
+  return p->output.file_stats;
 }
 #endif /* LIBDPX */
 
@@ -487,13 +647,16 @@
 void
 pdf_out_flush (void)
 {
-  if (pdf_output_file) {
-    int length;
+  pdf_out *p = current_output();
+  char     buf[16];
 
+  if (p->output.file) {
+    int  length;
+
     /* Flush current object stream */
-    if (current_objstm) {
-      release_objstm(current_objstm);
-      current_objstm =NULL;
+    if (p->current_objstm) {
+      release_objstm(p->current_objstm);
+      p->current_objstm =NULL;
     }
 
     /*
@@ -501,53 +664,56 @@
      * for the xref stream dictionary (= trailer).
      * Labelling it in pdf_out_init (with 1)  does not work (why?).
      */
-    if (xref_stream)
-      pdf_label_obj(xref_stream);
+    if (p->xref_stream)
+      pdf_label_obj(p, p->xref_stream);
 
     /* Record where this xref is for trailer */
-    startxref = pdf_output_file_position;
+    p->startxref = p->output.file_position;
 
-    pdf_add_dict(trailer_dict, pdf_new_name("Size"),
-		 pdf_new_number(next_label));
+    pdf_add_dict(p->trailer,
+                 pdf_new_name("Size"), pdf_new_number(p->obj.next_label));
 
-    if (xref_stream)
-      dump_xref_stream();
+    if (p->xref_stream)
+      dump_xref_stream(p);
     else {
-      dump_xref_table();
-      dump_trailer_dict();
+      dump_xref_table(p);
+      dump_trailer(p);
     }
 
     /* Done with xref table */
-    RELEASE(output_xref);
+    RELEASE(p->xref_table);
+    p->xref_table = NULL;
 
-    pdf_out(pdf_output_file, "startxref\n", 10);
-    length = sprintf(format_buffer, "%u\n", startxref);
-    pdf_out(pdf_output_file, format_buffer, length);
-    pdf_out(pdf_output_file, "%%EOF\n", 6);
+    pdf_out_str(p, "startxref\n", 10);
+    length = sprintf(buf, "%u\n", p->startxref);
+    pdf_out_str(p, buf, length);
+    pdf_out_str(p, "%%EOF\n", 6);
 
 #if !defined(LIBDPX)
     MESG("\n");
 #endif /* !LIBDPX */
     if (dpx_conf.verbose_level > 0) {
-      if (compression_level > 0) {
-	MESG("Compression saved %ld bytes%s\n", compression_saved,
-	     pdf_version < 15 ? ". Try \"-V 1.5\" for better compression" : "");
+      if (p->options.compression.level > 0) {
+        MESG("Compression saved %ld bytes%s\n", p->output.compression_saved);
       }
     }
 #if !defined(LIBDPX)
-    MESG("%ld bytes written", pdf_output_file_position);
+    MESG("%ld bytes written", p->output.file_position);
 #else
-    pdf_output_file_stats = pdf_output_file_position;
+    p->output.file_stats = p->output.file_position;
 #endif /* !LIBDPX */
 
-    MFCLOSE(pdf_output_file);
-    pdf_output_file_position = 0;
-    pdf_output_line_position = 0;
-    pdf_output_file = NULL;
+    MFCLOSE(p->output.file);
+    p->output.file = NULL;
+    p->output.file_position = 0;
+    p->output.line_position = 0;
   }
+  if (p->sec_data)  
+    pdf_enc_close(&p->sec_data);
 #if defined(PDFOBJ_DEBUG)
   {
     int i;
+    error_out = 1;
     MESG("\ndebug>> %d PDF objects created.", cur_obj_id);
     for (i = 0; i < cur_obj_id; i++) {
       pdf_obj *obj = bucket[i];
@@ -555,9 +721,11 @@
         if (obj->label > 0) {
           WARN("Object obj_id=<%lu, %u> unreleased...", obj->label, obj->generation);
           WARN("Reference count=%d", obj->refcount);
+          pdf_write_obj(p, obj);
+          MESG("\n");
         } else {
-          WARN("Unreleased object found: %d", i);
-          pdf_write_obj(obj, stderr);
+          WARN("Unreleased object found: (unlabeled) id=%d", i);
+          pdf_write_obj(p, obj);
           MESG("\n");
         }
       }
@@ -564,18 +732,20 @@
     }
   }
 #endif
+  clean_pdf_out_struct(p);
 }
 
 void
 pdf_error_cleanup (void)
 {
+  pdf_out *p = current_output();
   /*
    * This routine is the cleanup required for an abnormal exit.
    * For now, simply close the file.
    */
-  if (pdf_output_file)
-    MFCLOSE(pdf_output_file);
-  pdf_output_file = NULL;
+  if (p->output.file)
+    MFCLOSE(p->output.file);
+  p->output.file = NULL;
 }
 
 
@@ -582,15 +752,17 @@
 void
 pdf_set_root (pdf_obj *object)
 {
-  if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) {
+  pdf_out *p = current_output();
+
+  if (pdf_lookup_dict(p->trailer, "Root"))
     ERROR("Root object already set!");
-  }
+  pdf_add_dict(p->trailer, pdf_new_name("Root"), pdf_ref_obj(object));
   /* Adobe Readers don't like a document catalog inside an encrypted
    * object stream, although the PDF v1.5 spec seems to allow this.
    * Note that we don't set OBJ_NO_ENCRYPT since the name dictionary in
    * a document catalog may contain strings, which should be encrypted.
    */
-  if (doc_enc_mode)
+  if (p->options.enable_encrypt)
     object->flags |= OBJ_NO_OBJSTM;
 }
 
@@ -597,42 +769,32 @@
 void
 pdf_set_info (pdf_obj *object)
 {
-  if (pdf_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) {
+  pdf_out *p = current_output();
+
+  if (pdf_lookup_dict(p->trailer, "Info"))
     ERROR ("Info object already set!");
-  }
+  pdf_add_dict(p->trailer, pdf_new_name("Info"), pdf_ref_obj(object));
 }
 
-void
-pdf_set_id (pdf_obj *id)
-{
-  if (pdf_add_dict(trailer_dict, pdf_new_name("ID"), id)) {
-    ERROR ("ID already set!");
-  }
-}
 
-void
-pdf_set_encrypt (pdf_obj *encrypt)
+
+static void
+pdf_out_char (pdf_out *p, char c)
 {
-  if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) {
-    ERROR("Encrypt object already set!");
-  }
-  encrypt->flags |= OBJ_NO_ENCRYPT;
-}
+  ASSERT(p);
 
-static
-void pdf_out_char (FILE *file, char c)
-{
-  if (output_stream && file ==  pdf_output_file)
-    pdf_add_stream(output_stream, &c, 1);
-  else {
-    fputc(c, file);
-    /* Keep tallys for xref table *only* if writing a pdf file. */
-    if (file == pdf_output_file) {
-      pdf_output_file_position += 1;
+  if (error_out) {
+    fputc(c, stderr);
+  } else {
+    if (p->output_stream)
+    pdf_add_stream(p->output_stream, &c, 1);
+    else {
+      fputc(c, p->output.file);
+      p->output.file_position += 1;
       if (c == '\n')
-        pdf_output_line_position  = 0;
+        p->output.line_position  = 0;
       else
-        pdf_output_line_position += 1;
+        p->output.line_position += 1;
     }
   }
 }
@@ -639,26 +801,33 @@
 
 static char xchar[] = "0123456789abcdef";
 
-#define pdf_out_xchar(f,c) do {\
-  pdf_out_char((f), xchar[((c) >> 4) & 0x0f]);\
-  pdf_out_char((f), xchar[(c) & 0x0f]);\
-} while (0)
+static void
+pdf_out_xchar (pdf_out *p, char c)
+{
+  ASSERT(p);
 
-static
-void pdf_out (FILE *file, const void *buffer, int length)
+  pdf_out_char(p, xchar[(c >> 4) & 0x0f]);
+  pdf_out_char(p, xchar[c & 0x0f]);
+}
+
+static void
+pdf_out_str (pdf_out *p, const void *buffer, size_t length)
 {
-  if (output_stream && file ==  pdf_output_file)
-    pdf_add_stream(output_stream, buffer, length);
+  ASSERT(p);
+
+  if (error_out)
+    fwrite(buffer, 1, length, stderr);
   else {
-    fwrite(buffer, 1, length, file);
-    /* Keep tallys for xref table *only* if writing a pdf file */
-    if (file == pdf_output_file) {
-      pdf_output_file_position += length;
-      pdf_output_line_position += length;
+    if (p->output_stream)
+      pdf_add_stream(p->output_stream, buffer, length);
+    else {
+      fwrite(buffer, 1, length, p->output.file);
+      p->output.file_position += length;
+      p->output.line_position += length;
       /* "foo\nbar\n "... */
       if (length > 0 &&
-	((const char *)buffer)[length-1] == '\n')
-        pdf_output_line_position = 0;
+          ((const char *)buffer)[length-1] == '\n')
+        p->output.line_position = 0;
     }
   }
 }
@@ -674,12 +843,14 @@
 }
 
 static
-void pdf_out_white (FILE *file)
+void pdf_out_white (pdf_out *p)
 {
-  if (file == pdf_output_file && pdf_output_line_position >= 80) {
-    pdf_out_char(file, '\n');
+  ASSERT(p);
+
+  if (p->output.line_position >= 80) {
+    pdf_out_char(p, '\n');
   } else {
-    pdf_out_char(file, ' ');
+    pdf_out_char(p, ' ');
   }
 }
 
@@ -724,8 +895,10 @@
 }
 
 static void
-pdf_label_obj (pdf_obj *object)
+pdf_label_obj (pdf_out *p, pdf_obj *object)
 {
+  ASSERT(p);
+
   if (INVALIDOBJ(object))
     ERROR("pdf_label_obj(): passed invalid object.");
 
@@ -733,7 +906,7 @@
    * Don't change label on an already labeled object. Ignore such calls.
    */
   if (object->label == 0) {
-    object->label      = next_label++;
+    object->label      = p->obj.next_label++;
     object->generation = 0;
   }
 }
@@ -772,19 +945,23 @@
 pdf_obj *
 pdf_ref_obj (pdf_obj *object)
 {
+  pdf_out *p = current_output();
+
   if (INVALIDOBJ(object))
     ERROR("pdf_ref_obj(): passed invalid object.");
   
   if (object->refcount == 0) {
     MESG("\nTrying to refer already released object!!!\n");
-    pdf_write_obj(object, stderr);
+    error_out = 1;
+    pdf_write_obj(p, object);
     ERROR("Cannot continue...");
+    error_out = 0;
   }
 
   if (PDF_OBJ_INDIRECTTYPE(object)) {
     return pdf_link_obj(object);
   } else {
-    return pdf_new_ref(object);
+    return pdf_new_ref(p, object);
   }
 }
 
@@ -795,14 +972,17 @@
 }
 
 static void
-write_indirect (pdf_indirect *indirect, FILE *file)
+write_indirect (pdf_out *p, pdf_indirect *indirect)
 {
-  int length;
+  int   length;
+  char  buf[64];
 
+  ASSERT(p);
   ASSERT(!indirect->pf);
 
-  length = sprintf(format_buffer, "%u %hu R", indirect->label, indirect->generation);
-  pdf_out(file, format_buffer, length);
+  length = sprintf(buf, "%u %hu R",
+                   indirect->label, indirect->generation);
+  pdf_out_str(p, buf, length);
 }
 
 /* The undefined object is used as a placeholder in pdfnames.c
@@ -831,9 +1011,9 @@
 }
 
 static void
-write_null (FILE *file)
+write_null (pdf_out *p)
 {
-  pdf_out(file, "null", 4);
+  pdf_out_str(p, "null", 4);
 }
 
 pdf_obj *
@@ -857,12 +1037,12 @@
 }
 
 static void
-write_boolean (pdf_boolean *data, FILE *file)
+write_boolean (pdf_out *p, pdf_boolean *data)
 {
   if (data->value) {
-    pdf_out(file, "true", 4);
+    pdf_out_str(p, "true", 4);
   } else {
-    pdf_out(file, "false", 5);
+    pdf_out_str(p, "false", 5);
   }
 }
 
@@ -899,13 +1079,14 @@
 }
 
 static void
-write_number (pdf_number *number, FILE *file)
+write_number (pdf_out *p, pdf_number *number)
 {
-  int count;
+  int  count;
+  char buf[512];
 
-  count = pdf_sprint_number(format_buffer, number->value);
+  count = pdf_sprint_number(buf, number->value);
 
-  pdf_out(file, format_buffer, count);
+  pdf_out_str(p, buf, count);
 }
 
 
@@ -938,20 +1119,20 @@
   pdf_obj    *result;
   pdf_string *data;
 
+  ASSERT(str);
+
   result = pdf_new_obj(PDF_STRING);
   data   = NEW(1, pdf_string);
   result->data = data;
   data->length = length;
 
-  if (str && length > 0) {
+  if (length) {
     data->string = NEW(length+1, unsigned char);
     memcpy(data->string, str, length);
     /* Shouldn't assume NULL terminated. */
     data->string[length] = '\0';
-  } else {
+  } else
     data->string = NULL;
-    data->length = 0;
-  }
 
   return result;
 }
@@ -977,7 +1158,7 @@
 
   data = object->data;
 
-  return (unsigned) (data->length);
+  return (unsigned) data->length;
 }
 
 /*
@@ -987,8 +1168,8 @@
 int
 pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len)
 {
-  int result = 0;
-  int i;
+  size_t result = 0;
+  size_t i;
 
   for (i = 0; i < len; i++) {
     unsigned char ch;
@@ -1031,21 +1212,22 @@
     }
   }
 
-  return result;
+  return (int) result;
 }
 
 static void
-write_string (pdf_string *str, FILE *file)
+write_string (pdf_out *p, pdf_string *str)
 {
-  unsigned char *s = NULL;
-  char wbuf[FORMAT_BUF_SIZE]; /* Shouldn't use format_buffer[]. */
-  int  nescc = 0, i, count;
-  size_t len = 0;
+  unsigned char *s   = NULL;
+  size_t         i, nescc = 0;
+  size_t         len = 0;
 
-  if (enc_mode) {
-    pdf_encrypt_data(str->string, str->length, &s, &len);
+  ASSERT(p);
+
+  if (p->state.enc_mode) {
+    pdf_encrypt_data(p->sec_data, str->string, str->length, &s, &len);
   } else {
-  s = str->string;
+    s   = str->string;
     len = str->length;
   }
 
@@ -1061,13 +1243,22 @@
    * ASCII hex string.
    */
   if (nescc > len / 3) {
-    pdf_out_char(file, '<');
+    pdf_out_char(p, '<');
     for (i = 0; i < len; i++) {
-      pdf_out_xchar(file, s[i]);
+      pdf_out_xchar(p, s[i]);
     }
-    pdf_out_char(file, '>');
+    pdf_out_char(p, '>');
   } else {
-    pdf_out_char(file, '(');
+    char   *buf;
+    size_t  size, count;
+  
+    /* At most len/3 is to be escaped here. (see above)
+     * Thus 4*len/3 + 2*len/3 + 2 is enough for buffer size.
+     */
+    size = len * 2 + 3;
+    buf  = NEW(size, char);
+
+    pdf_out_char(p, '(');
     /*
      * This section of code probably isn't speed critical.  Escaping the
      * characters in the string one at a time may seem slow, but it's
@@ -1077,12 +1268,14 @@
      * handled as quickly as possible since there are so many of them.
      */ 
     for (i = 0; i < len; i++) {
-      count = pdfobj_escape_str(wbuf, FORMAT_BUF_SIZE, &(s[i]), 1);
-      pdf_out(file, wbuf, count);
+      count = pdfobj_escape_str(buf, size, &(s[i]), 1);
+      pdf_out_str(p, buf, count);
     }
-    pdf_out_char(file, ')');
+    pdf_out_char(p, ')');
+    RELEASE(buf);
   }
-  if (enc_mode && s)
+
+  if (p->state.enc_mode && s)
     RELEASE(s);
 }
 
@@ -1123,7 +1316,7 @@
 pdf_new_name (const char *name)
 {
   pdf_obj  *result;
-  unsigned  length;
+  size_t    length;
   pdf_name *data;
 
   result = pdf_new_obj(PDF_NAME);
@@ -1142,11 +1335,13 @@
 }
 
 static void
-write_name (pdf_name *name, FILE *file)
+write_name (pdf_out *p, pdf_name *name)
 {
-  char *s;
-  int i, length;
+  char   *s;
+  size_t  i, length;
 
+  ASSERT(p);
+
   s      = name->name;
   length = name->name ? strlen(name->name) : 0;
   /*
@@ -1169,14 +1364,14 @@
                      (c) == '{' || (c) == '}' || \
                      (c) == '%')
 #endif
-  pdf_out_char(file, '/');
+  pdf_out_char(p, '/');
   for (i = 0; i < length; i++) {
     if (s[i] < '!' || s[i] > '~' || s[i] == '#' || is_delim(s[i])) {
       /*     ^ "space" is here. */
-      pdf_out_char (file, '#');
-      pdf_out_xchar(file, s[i]);
+      pdf_out_char (p, '#');
+      pdf_out_xchar(p, s[i]);
     } else {
-      pdf_out_char (file, s[i]);
+      pdf_out_char (p, s[i]);
     }
   }
 }
@@ -1225,25 +1420,27 @@
 }
 
 static void
-write_array (pdf_array *array, FILE *file)
+write_array (pdf_out *p, pdf_array *array)
 {
-  pdf_out_char(file, '[');
+  ASSERT(p);
+
+  pdf_out_char(p, '[');
   if (array->size > 0) {
-    unsigned int i;
-    int type1 = PDF_UNDEFINED, type2;
+    size_t i;
+    int    type1 = PDF_UNDEFINED, type2;
     
     for (i = 0; i < array->size; i++) {
       if (array->values[i]) {
-	type2 = array->values[i]->type;
-	if (type1 != PDF_UNDEFINED && pdf_need_white(type1, type2))
-	  pdf_out_white(file);
-	type1 = type2;
-	pdf_write_obj(array->values[i], file);
+        type2 = array->values[i]->type;
+        if (type1 != PDF_UNDEFINED && pdf_need_white(type1, type2))
+          pdf_out_white(p);
+        type1 = type2;
+        pdf_write_obj(p, array->values[i]);
       } else
-	WARN("PDF array element #ld undefined.", i);
+        WARN("PDF array element #ld undefined.", i);
     }
   }
-  pdf_out_char(file, ']');
+  pdf_out_char(p, ']');
 }
 
 pdf_obj *
@@ -1264,7 +1461,7 @@
   return result;
 }
 
-unsigned int
+unsigned
 pdf_array_length (pdf_obj *array)
 {
   pdf_array *data;
@@ -1273,13 +1470,13 @@
 
   data = (pdf_array *) array->data;
 
-  return (unsigned int) data->size;
+  return (unsigned) data->size;
 }
 
 static void
 release_array (pdf_array *data)
 {
-  unsigned int i;
+  size_t  i;
 
   if (data->values) {
     for (i = 0; i < data->size; i++) {
@@ -1316,7 +1513,7 @@
 
 #if 0
 void
-pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object)
+pdf_put_array (pdf_obj *array, int idx, pdf_obj *object)
 {
   pdf_array *data;
   int        i;
@@ -1357,7 +1554,7 @@
 
   data = array->data;
   if (data->size > 0) {
-    int i;
+    size_t i;
 
     result = data->values[0];
     for (i = 1; i < data->size; i++)
@@ -1409,25 +1606,25 @@
 #endif
 
 static void
-write_dict (pdf_dict *dict, FILE *file)
+write_dict (pdf_out *p, pdf_dict *dict)
 {
 #if 0
-  pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */
+  pdf_out_str (p, "<<\n", 3); /* dropping \n saves few kb. */
 #else
-  pdf_out (file, "<<", 2);
+  pdf_out_str(p, "<<", 2);
 #endif
   while (dict->key != NULL) {
-    pdf_write_obj(dict->key, file);
+    pdf_write_obj(p, dict->key);
     if (pdf_need_white(PDF_NAME, (dict->value)->type)) {
-      pdf_out_white(file);
+      pdf_out_white(p);
     }
-    pdf_write_obj(dict->value, file);
+    pdf_write_obj(p, dict->value);
 #if 0
     pdf_out_char (file, '\n'); /* removing this saves few kb. */
 #endif
     dict = dict->next;
   }
-  pdf_out (file, ">>", 2);
+  pdf_out_str(p, ">>", 2);
 }
 
 pdf_obj *
@@ -1826,7 +2023,9 @@
   return  dst;
 }
 
-/* This modifies "raster" itself! */
+/* TIFF predictor filter support
+ * This modifies "raster" itself!
+ */
 static void
 apply_filter_TIFF2_1_2_4 (unsigned char *raster,
                           int32_t width, int32_t height,
@@ -1880,7 +2079,8 @@
       }
     }
     if (outbits > 0) {
-      raster[k] = (outbuf << (8 - outbits)); k++;
+      raster[k] = (outbuf << (8 - outbits));
+      k++;
     }
   }
   RELEASE(prev);
@@ -1966,17 +2166,19 @@
 }
 
 static void
-write_stream (pdf_stream *stream, FILE *file)
+write_stream (pdf_out *p, pdf_stream *stream)
 {
   unsigned char *filtered;
-  unsigned int   filtered_length;
+  size_t         filtered_length;
 #ifdef HAVE_ZLIB
   uLong          buffer_length;
 #else
-  unsigned int   buffer_length;
+  size_t         buffer_length;
 #endif
   unsigned char *buffer;
 
+  ASSERT(p);
+
   /*
    * Always work from a copy of the stream. All filters read from
    * "filtered" and leave their result in "filtered".
@@ -2001,11 +2203,11 @@
   /* Apply compression filter if requested */
   if (stream->stream_length > 0 &&
       (stream->_flags & STREAM_COMPRESS) &&
-      compression_level > 0) {
+      p->options.compression.level > 0) {
     pdf_obj *filters;
 
     /* First apply predictor filter if requested. */
-    if ( compression_use_predictor &&
+    if ( p->options.compression.use_predictor &&
         (stream->_flags & STREAM_USE_PREDICTOR) &&
         !pdf_lookup_dict(stream->dict, "DecodeParms")) {
       int      bits_per_pixel  = stream->decodeparms.colors *
@@ -2071,18 +2273,19 @@
     }
 #ifdef HAVE_ZLIB_COMPRESS2    
     if (compress2(buffer, &buffer_length, filtered,
-		  filtered_length, compression_level)) {
+        filtered_length, p->options.compression.level)) {
       ERROR("Zlib error");
     }
 #else 
     if (compress(buffer, &buffer_length, filtered,
-		 filtered_length)) {
+        filtered_length)) {
       ERROR ("Zlib error");
     }
 #endif /* HAVE_ZLIB_COMPRESS2 */
     RELEASE(filtered);
-    compression_saved += filtered_length - buffer_length
-      - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n"));
+    p->output.compression_saved +=
+      filtered_length - buffer_length
+        - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n"));
 
     filtered        = buffer;
     filtered_length = buffer_length;
@@ -2090,10 +2293,10 @@
 #endif /* HAVE_ZLIB */
 
   /* AES will change the size of data! */
-  if (enc_mode) {
+  if (p->state.enc_mode) {
     unsigned char *cipher = NULL;
     size_t         cipher_len = 0;
-    pdf_encrypt_data(filtered, filtered_length, &cipher, &cipher_len);
+    pdf_encrypt_data(p->sec_data, filtered, filtered_length, &cipher, &cipher_len);
     RELEASE(filtered);
     filtered        = cipher;
     filtered_length = cipher_len;
@@ -2115,12 +2318,12 @@
   pdf_add_dict(stream->dict,
 	       pdf_new_name("Length"), pdf_new_number(filtered_length));
 
-  pdf_write_obj(stream->dict, file);
+  pdf_write_obj(p, stream->dict);
 
-  pdf_out(file, "\nstream\n", 8);
+  pdf_out_str(p, "\nstream\n", 8);
 
   if (filtered_length > 0)
-    pdf_out(file, filtered, filtered_length);
+    pdf_out_str(p, filtered, filtered_length);
   RELEASE(filtered);
 
   /*
@@ -2130,8 +2333,8 @@
    * filters, this could be a problem.
    */
 
-  pdf_out(file, "\n", 1);
-  pdf_out(file, "endstream", 9);
+  pdf_out_str(p, "\n", 1);
+  pdf_out_str(p, "endstream", 9);
 }
 
 static void
@@ -2497,7 +2700,7 @@
       WARN("Ignoring zlib error: status=%d, message=\"%s\"", status, z.msg);
       break;
     } else if (status != Z_OK) {
-      WARN("inflate() failed (status=%d, message=\"%s\").", status, z.msg);
+      WARN("inflate() failed. Broken PDF file?");
       inflateEnd(&z);
       pdf_release_obj(tmp);
       return NULL;
@@ -2861,10 +3064,12 @@
 #endif
 
 static void
-pdf_write_obj (pdf_obj *object, FILE *file)
+pdf_write_obj (pdf_out *p, pdf_obj *object)
 {
+  ASSERT(p);
+
   if (object == NULL) {
-    write_null(file);
+    write_null(p);
     return;
   }
 
@@ -2871,36 +3076,36 @@
   if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object))
     ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type);
 
-  if (file == stderr)
+  if (error_out)
     fprintf(stderr, "{%d}", object->refcount);
 
   switch (object->type) {
   case PDF_BOOLEAN:
-    write_boolean(object->data, file);
+    write_boolean(p, object->data);
     break;
   case PDF_NUMBER:
-    write_number (object->data, file);
+    write_number (p, object->data);
     break;
   case PDF_STRING:
-    write_string (object->data, file);
+    write_string (p, object->data);
     break;
   case PDF_NAME:
-    write_name(object->data, file);
+    write_name(p, object->data);
     break;
   case PDF_ARRAY:
-    write_array(object->data, file);
+    write_array(p, object->data);
     break;
   case PDF_DICT:
-    write_dict (object->data, file);
+    write_dict (p, object->data);
     break;
   case PDF_STREAM:
-    write_stream(object->data, file);
+    write_stream(p, object->data);
     break;
   case PDF_NULL:
-    write_null(file);
+    write_null(p);
     break;
   case PDF_INDIRECT:
-    write_indirect(object->data, file);
+    write_indirect(p, object->data);
     break;
   }
 }
@@ -2907,30 +3112,35 @@
 
 /* Write the object to the file */ 
 static void
-pdf_flush_obj (pdf_obj *object, FILE *file)
+pdf_flush_obj (pdf_out *p, pdf_obj *object)
 {
-  int length;
+  size_t length;
+  char   buf[64];
 
   /*
    * Record file position
    */
-  add_xref_entry(object->label, 1,
-		 pdf_output_file_position, object->generation);
-  length = sprintf(format_buffer, "%u %hu obj\n", object->label, object->generation);
-  enc_mode = doc_enc_mode && !(object->flags & OBJ_NO_ENCRYPT);
-  pdf_enc_set_label(object->label);
-  pdf_enc_set_generation(object->generation);
-  pdf_out(file, format_buffer, length);
-  pdf_write_obj(object, file);
-  pdf_out(file, "\nendobj\n", 8);
+  add_xref_entry(p, object->label, 1,
+                 p->output.file_position, object->generation);
+  length = sprintf(buf, "%u %hu obj\n", object->label, object->generation);
+  p->state.enc_mode =
+    (p->options.enable_encrypt && !(object->flags & OBJ_NO_ENCRYPT)) ? 1 : 0;
+  if (p->state.enc_mode) {
+    pdf_enc_set_label(p->sec_data, object->label);
+    pdf_enc_set_generation(p->sec_data, object->generation);
+  }
+  pdf_out_str(p, buf, length);
+  pdf_write_obj(p, object);
+  pdf_out_str(p, "\nendobj\n", 8);
 }
 
 static int
-pdf_add_objstm (pdf_obj *objstm, pdf_obj *object)
+pdf_add_objstm (pdf_out *p, pdf_obj *objstm, pdf_obj *object)
 {
   int *data, pos;
 
   TYPECHECK(objstm, PDF_STREAM);
+  ASSERT(p);
 
   data = get_objstm_data(objstm);
   pos = ++data[0];
@@ -2938,14 +3148,14 @@
   data[2*pos]   = object->label;
   data[2*pos+1] = pdf_stream_length(objstm);
 
-  add_xref_entry(object->label, 2, objstm->label, pos-1);
+  add_xref_entry(p, object->label, 2, objstm->label, pos-1);
  
   /* redirect output into objstm */
-  output_stream = objstm;
-  enc_mode = 0;
-  pdf_write_obj(object, pdf_output_file);
-  pdf_out_char(pdf_output_file, '\n');
-  output_stream = NULL;
+  p->output_stream  = objstm;
+  p->state.enc_mode = 0;
+  pdf_write_obj(p, object);
+  pdf_out_char(p, '\n');
+  p->output_stream = NULL;
 
   return pos;
 }
@@ -2958,7 +3168,7 @@
   pdf_obj *dict;
   pdf_stream *stream;
   unsigned char *old_buf;
-  unsigned int old_length;
+  size_t         old_length;
   stream = (pdf_stream *) objstm->data;
 
   /* Precede stream data by offset table */
@@ -2971,8 +3181,9 @@
   {
     int i = 2*pos, *val = data+2;
     while (i--) {
-      int length = sprintf(format_buffer, "%d ", *(val++));
-      pdf_add_stream(objstm, format_buffer, length);
+      char buf[32];
+      size_t length = sprintf(buf, "%d ", *(val++));
+      pdf_add_stream(objstm, buf, length);
     }
   }
 
@@ -2989,13 +3200,17 @@
 void
 pdf_release_obj (pdf_obj *object)
 {
+  pdf_out *p = current_output();
+
   if (object == NULL)
     return;
   if (INVALIDOBJ(object) || object->refcount <= 0) {
     MESG("\npdf_release_obj: object=%p, type=%d, refcount=%d\n",
-	 object, object->type, object->refcount);
-    pdf_write_obj(object, stderr);
+         object, object->type, object->refcount);
+    error_out = 1;
+    pdf_write_obj(p, object);
     ERROR("pdf_release_obj:  Called with invalid object.");
+    error_out = 0;
   }
   object->refcount -= 1;
   if (object->refcount == 0) {
@@ -3006,23 +3221,23 @@
      * Nothing is using this object so it's okay to remove it.
      * Nonzero "label" means object needs to be written before it's destroyed.
      */
-    if (object->label && pdf_output_file != NULL) {
-      if (!do_objstm || object->flags & OBJ_NO_OBJSTM
-	  || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT)
-	  || object->generation)
-	pdf_flush_obj(object, pdf_output_file);
+    if (object->label && p->output.file != NULL) {
+      if (!p->options.use_objstm || object->flags & OBJ_NO_OBJSTM ||
+          (p->options.enable_encrypt && (object->flags & OBJ_NO_ENCRYPT)) ||
+          object->generation)
+        pdf_flush_obj(p, object);
       else {
-        if (!current_objstm) {
-	  int *data = NEW(2*OBJSTM_MAX_OBJS+2, int);
-	  data[0] = data[1] = 0;
-	  current_objstm = pdf_new_stream(STREAM_COMPRESS);
-	  set_objstm_data(current_objstm, data);
-	  pdf_label_obj(current_objstm);
-	}
-	if (pdf_add_objstm(current_objstm, object) == OBJSTM_MAX_OBJS) {
-	  release_objstm(current_objstm);
-	  current_objstm = NULL;
-	}
+        if (!p->current_objstm) {
+          int *data = NEW(2*OBJSTM_MAX_OBJS+2, int);
+          data[0] = data[1] = 0;
+          p->current_objstm = pdf_new_stream(STREAM_COMPRESS);
+          set_objstm_data(p->current_objstm, data);
+          pdf_label_obj(p, p->current_objstm);
+        }
+        if (pdf_add_objstm(p, p->current_objstm, object) == OBJSTM_MAX_OBJS) {
+          release_objstm(p->current_objstm);
+          p->current_objstm = NULL;
+        }
       }
     }
     switch (object->type) {
@@ -3060,6 +3275,9 @@
   }
 }
 
+/* Reading external PDF files
+ *
+ */
 static int
 backup_line (FILE *pdf_input_file)
 {
@@ -3086,11 +3304,11 @@
 static int
 find_xref (FILE *pdf_input_file)
 {
-  int   xref_pos = 0;
-  int   len, tries = 10;
+  size_t  len, xref_pos = 0;
+  int     tries = 10;
 
   do {
-    int currentpos;
+    size_t currentpos;
 
     if (!backup_line(pdf_input_file)) {
       tries = 0;
@@ -3162,10 +3380,11 @@
  * :-(
  */
 static int
-next_object_offset (pdf_file *pf, unsigned int obj_num)
+next_object_offset (pdf_file *pf, uint32_t obj_num)
 {
-  int  next = pf->file_size;  /* Worst case */
-  int  i, curr;
+  uint32_t next = pf->file_size;  /* Worst case */
+  size_t   i;
+  uint32_t curr;
 
   curr = pf->xref_table[obj_num].field2;
   /* Check all other type 1 objects to find next one */
@@ -3184,7 +3403,7 @@
   ((pf)->xref_table[(n)].type == 2 && !(g))))
 
 pdf_obj *
-pdf_new_indirect (pdf_file *pf, unsigned obj_num, unsigned short obj_gen)
+pdf_new_indirect (pdf_file *pf, uint32_t obj_num, uint16_t obj_gen)
 {
   pdf_obj      *result;
   pdf_indirect *indirect;
@@ -3202,13 +3421,12 @@
 }
 
 static pdf_obj *
-pdf_read_object (unsigned int obj_num, unsigned short obj_gen,
-		pdf_file *pf, int offset, int limit)
+pdf_read_object (uint32_t obj_num, uint16_t obj_gen, pdf_file *pf, size_t offset, size_t limit)
 {
-  int      length;
-  char    *buffer;
+  pdf_obj    *result = NULL; 
+  size_t      length;
+  char       *buffer;
   const char *p, *endptr;
-  pdf_obj *result;
 
   length = limit - offset;
 
@@ -3227,7 +3445,7 @@
   {
     const char   *q = p; /* <== p */
     char         *sp;
-    unsigned int  n, g;
+    uint32_t      n, g;
 
     skip_white(&q, endptr);
     sp = parse_unsigned(&q, endptr);
@@ -3279,17 +3497,17 @@
 }
 
 static pdf_obj *
-read_objstm (pdf_file *pf, unsigned int num)
+read_objstm (pdf_file *pf, uint32_t num)
 {
-  unsigned int offset = pf->xref_table[num].field2;
-  unsigned short gen = pf->xref_table[num].field3;
-  int limit = next_object_offset(pf, num), n, first, *header = NULL;
-  char *data = NULL, *q;
+  size_t      offset = pf->xref_table[num].field2;
+  uint16_t    gen    = pf->xref_table[num].field3;
+  size_t      limit  = next_object_offset(pf, num);
+  int         n, first, *header = NULL;
+  char       *data = NULL, *q;
   const char *p, *endptr;
-  int i;
+  int         i;
+  pdf_obj    *objstm, *dict, *type, *n_obj, *first_obj;
 
-  pdf_obj *objstm, *dict, *type, *n_obj, *first_obj;
-
   objstm = pdf_read_object(num, gen, pf, offset, limit);
 
   if (!PDF_OBJ_STREAMTYPE(objstm))
@@ -3365,7 +3583,7 @@
  * several cross-reference sections.
  */ 
 static pdf_obj *
-pdf_get_object (pdf_file *pf, unsigned int obj_num, unsigned short obj_gen)
+pdf_get_object (pdf_file *pf, uint32_t obj_num, uint16_t obj_gen)
 {
   pdf_obj *result;
 
@@ -3381,27 +3599,27 @@
 
   if (pf->xref_table[obj_num].type == 1) {
     /* type == 1 */
-    unsigned int offset;
-    int limit;
+    uint32_t offset;
+    size_t   limit;
     offset = pf->xref_table[obj_num].field2;
     limit  = next_object_offset(pf, obj_num);
     result = pdf_read_object(obj_num, obj_gen, pf, offset, limit);
   } else {
     /* type == 2 */
-    unsigned int   objstm_num = pf->xref_table[obj_num].field2;
-    unsigned short index = pf->xref_table[obj_num].field3;
-    pdf_obj *objstm;
-    int  *data, n, first, length;
+    uint32_t    objstm_num = pf->xref_table[obj_num].field2;
+    uint16_t    index = pf->xref_table[obj_num].field3;
+    pdf_obj    *objstm;
+    int        *data, n, first, length;
     const char *p, *q;
 
     if (objstm_num >= pf->num_obj ||
-	pf->xref_table[objstm_num].type != 1 ||
-	!((objstm = pf->xref_table[objstm_num].direct) ||
-	  (objstm = read_objstm(pf, objstm_num))))
+        pf->xref_table[objstm_num].type != 1 ||
+        !((objstm = pf->xref_table[objstm_num].direct) ||
+          (objstm = read_objstm(pf, objstm_num))))
       goto error;
 
-    data = get_objstm_data(objstm);
-    n = *(data++);
+    data  = get_objstm_data(objstm);
+    n     = *(data++);
     first = *(data++);
 
     if (index >= n || data[2*index] != obj_num)
@@ -3431,12 +3649,14 @@
 #define OBJ_GEN(o)  (((pdf_indirect *)((o)->data))->generation)
 
 static pdf_obj *
-pdf_new_ref (pdf_obj *object)
+pdf_new_ref (pdf_out *p, pdf_obj *object)
 {
   pdf_obj *result;
 
+  ASSERT(p);
+
   if (object->label == 0) {
-    pdf_label_obj(object);
+    pdf_label_obj(p, object);
   }
   result = pdf_new_indirect(NULL, object->label, object->generation);
   OBJ_OBJ(result) = object;
@@ -3456,8 +3676,8 @@
   while (PDF_OBJ_INDIRECTTYPE(obj) && --count) {
     pdf_file *pf = OBJ_FILE(obj);
     if (pf) {
-      unsigned int   obj_num = OBJ_NUM(obj);
-      unsigned short obj_gen = OBJ_GEN(obj);
+      uint32_t obj_num = OBJ_NUM(obj);
+      uint16_t obj_gen = OBJ_GEN(obj);
       pdf_release_obj(obj);
       obj = pdf_get_object(pf, obj_num, obj_gen);
     } else {
@@ -3481,9 +3701,9 @@
 }
 
 static void
-extend_xref (pdf_file *pf, int new_size) 
+extend_xref (pdf_file *pf, size_t new_size) 
 {
-  unsigned int i;
+  size_t  i;
 
   pf->xref_table = RENEW(pf->xref_table, new_size, xref_entry);
   for (i = pf->num_obj; i < new_size; i++) {
@@ -3498,12 +3718,12 @@
 
 /* Returns < 0 for error, 1 for success, and 0 when xref stream found. */
 static int
-parse_xref_table (pdf_file *pf, int xref_pos)
+parse_xref_table (pdf_file *pf, size_t xref_pos)
 {
   FILE       *pdf_input_file = pf->file;
   const char *p, *endptr;
   char        buf[256]; /* See, PDF ref. v.1.7, p.91 for "255+1" here. */
-  int         len;
+  size_t      len;
 
   /*
    * This routine reads one xref segment. It may be called multiple times
@@ -3535,10 +3755,10 @@
 
   /* Next line in file has first item and size of table */
   for (;;) {
-    char         flag;
-    unsigned int current_pos;
-    int          i;
-    uint32_t     first, size, offset, obj_gen;
+    char      flag;
+    size_t    current_pos, size, offset;
+    int       i;
+    uint32_t  first, obj_gen;
 
     current_pos = tell_position(pdf_input_file);
     len = mfreadln(buf, 255, pdf_input_file);
@@ -3702,10 +3922,10 @@
   return  1;
 }
 
-static unsigned int
-parse_xrefstm_field (const char **p, int length, unsigned int def)
+static uint32_t
+parse_xrefstm_field (const char **p, size_t length, uint32_t def)
 {
-  unsigned int val = 0;
+  uint32_t val = 0;
 
   if (!length)
     return def;
@@ -3720,9 +3940,9 @@
 
 static int
 parse_xrefstm_subsec (pdf_file *pf,
-		      const char **p, int *length,
-		      int *W, int wsum,
-		      int first, int size) {
+                      const char **p, size_t *length,
+                      int *W, int wsum, int first, int size)
+{
   xref_entry *e;
 
   if ((*length -= wsum*size) < 0)
@@ -3733,9 +3953,9 @@
 
   e = pf->xref_table + first;
   while (size--) {
-    unsigned char  type;
-    unsigned int   field2;
-    unsigned short field3;
+    uint8_t  type;
+    uint32_t field2;
+    uint16_t field3;
 
     type = (unsigned char) parse_xrefstm_field(p, W[0], 1);
     if (type > 2)
@@ -3746,8 +3966,8 @@
       return -1;
 #endif
 
-    field2 = (unsigned int)  parse_xrefstm_field(p, W[1], 0);
-    field3 = (unsigned short) parse_xrefstm_field(p, W[2], 0);
+    field2 = (uint32_t) parse_xrefstm_field(p, W[1], 0);
+    field3 = (uint16_t) parse_xrefstm_field(p, W[2], 0);
 
     if (!e->field2) {
       e->type   = type;
@@ -3761,12 +3981,12 @@
 }
 
 static int
-parse_xref_stream (pdf_file *pf, int xref_pos, pdf_obj **trailer)
+parse_xref_stream (pdf_file *pf, size_t xref_pos, pdf_obj **trailer)
 {
-  pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj;
-  unsigned int size;
-  int length;
-  int W[3], i, wsum = 0;
+  pdf_obj    *xrefstm, *size_obj, *W_obj, *index_obj;
+  uint32_t    size;
+  size_t      length;
+  int         W[3], i, wsum = 0;
   const char *p;
 
   xrefstm = pdf_read_object(0, 0, pf, xref_pos, pf->file_size);
@@ -3786,7 +4006,7 @@
   size_obj = pdf_lookup_dict(*trailer, "Size");
   if (!PDF_OBJ_NUMBERTYPE(size_obj))
     goto error;
-  size = (unsigned int) pdf_number_value(size_obj);
+  size = (uint32_t) pdf_number_value(size_obj);
 
   length = pdf_stream_length(xrefstm);
 
@@ -3805,7 +4025,7 @@
 
   index_obj = pdf_lookup_dict(*trailer, "Index");
   if (index_obj) {
-    unsigned int index_len;
+    size_t index_len;
     if (!PDF_OBJ_ARRAYTYPE(index_obj) ||
         ((index_len = pdf_array_length(index_obj)) % 2 ))
       goto error;
@@ -3845,7 +4065,7 @@
 read_xref (pdf_file *pf)
 {
   pdf_obj *trailer = NULL, *main_trailer = NULL;
-  int      xref_pos;
+  size_t   xref_pos;
 
   if (!(xref_pos = find_xref(pf->file)))
     goto error;
@@ -3859,37 +4079,37 @@
       pdf_obj *xrefstm;
 
       if (!(trailer = parse_trailer(pf)))
-	goto error;
+        goto error;
 
       if (!main_trailer)
-	main_trailer = pdf_link_obj(trailer);
+        main_trailer = pdf_link_obj(trailer);
 
       if ((xrefstm = pdf_lookup_dict(trailer, "XRefStm"))) {
-	pdf_obj *new_trailer = NULL;
-	if (PDF_OBJ_NUMBERTYPE(xrefstm) &&
-	    parse_xref_stream(pf, (int) pdf_number_value(xrefstm),
+        pdf_obj *new_trailer = NULL;
+        if (PDF_OBJ_NUMBERTYPE(xrefstm) &&
+            parse_xref_stream(pf, (int) pdf_number_value(xrefstm),
 			      &new_trailer))
-	  pdf_release_obj(new_trailer);
-	else
-	  WARN("Skipping hybrid reference section.");
-	/* Many PDF 1.5 xref streams use DecodeParms, which we cannot
-	   parse. This way we can use at least xref tables in hybrid
-	   documents. Or should we better stop parsing the file?
-	*/
+          pdf_release_obj(new_trailer);
+        else
+          WARN("Skipping hybrid reference section.");
+	      /* Many PDF 1.5 xref streams use DecodeParms, which we cannot
+	       * parse. This way we can use at least xref tables in hybrid
+	       * documents. Or should we better stop parsing the file?
+	       */
       }
 
     } else if (!res && parse_xref_stream(pf, xref_pos, &trailer)) {
       /* cross-reference stream */
       if (!main_trailer)
-	main_trailer = pdf_link_obj(trailer);
+        main_trailer = pdf_link_obj(trailer);
     } else
       goto error;
 
     if ((prev = pdf_lookup_dict(trailer, "Prev"))) {
       if (PDF_OBJ_NUMBERTYPE(prev))
-	xref_pos = (int) pdf_number_value(prev);
+        xref_pos = (size_t) pdf_number_value(prev);
       else
-	goto error;
+        goto error;
     } else
       xref_pos = 0;
 
@@ -3938,7 +4158,7 @@
 static void
 pdf_file_free (pdf_file *pf)
 {
-  unsigned int i;
+  size_t i;
 
   if (!pf) {
     return;
@@ -3995,6 +4215,7 @@
 pdf_file *
 pdf_open (const char *ident, FILE *file)
 {
+  pdf_out  *p  = current_output();
   pdf_file *pf = NULL;
 
   ASSERT(pdf_files);
@@ -4008,15 +4229,21 @@
     pdf_obj *new_version;
     int version = check_for_pdf_version(file);
 
-    if (version < 10)
-      WARN("Unrecognized PDF version specified for input PDF file: %d.%d",
-        pdf_version/10, pdf_version%10);
-    else if (version > pdf_version) {
-      WARN("Trying to include PDF file with version (%d.%d), which is " \
-           "newer than current output PDF setting (%d.%d).",
-        version/10, version%10, pdf_version/10, pdf_version%10);
+    if (!dpx_conf.is_xbb) {
+      int ver_major, ver_minor;
+
+      ver_major = version / 10;
+      ver_minor = version % 10;
+
+      if (version < 10)
+        WARN("Unrecognized PDF version specified for input PDF file: %d.%d",
+             ver_major, ver_minor);
+      else if (pdf_check_version(ver_major, ver_minor) < 0) {
+        WARN("Trying to include PDF file with version (%d.%d), which is " \
+             "newer than current output PDF setting (%d.%d).",
+             ver_major, ver_minor, p->version.major, p->version.minor);
+      }
     }
-
     pf = pdf_file_new(file);
     pf->version = version;
 
@@ -4096,7 +4323,7 @@
   if (version < 0)  /* not a PDF file */
     return 0;
 
-  if (version <= pdf_version)
+  if (version <= pdf_get_version())
     return 1;
 
   return 1;
@@ -4122,10 +4349,11 @@
 static pdf_obj *
 pdf_import_indirect (pdf_obj *object)
 {
+  pdf_out  *p  = current_output();
   pdf_file *pf = OBJ_FILE(object);
-  unsigned int obj_num = OBJ_NUM(object);
-  unsigned short obj_gen = OBJ_GEN(object);
-  pdf_obj *ref;
+  uint32_t  obj_num = OBJ_NUM(object);
+  uint16_t  obj_gen = OBJ_GEN(object);
+  pdf_obj  *ref;
 
   ASSERT(pf);
 
@@ -4154,7 +4382,7 @@
      * are completely read.
      */
     reserved = pdf_new_null(); /* for reservation of label */
-    pf->xref_table[obj_num].indirect = ref = pdf_new_ref(reserved);
+    pf->xref_table[obj_num].indirect = ref = pdf_new_ref(p, reserved);
     imported = pdf_import_object(obj);
     if (imported) {
       if (imported->label) {
@@ -4187,7 +4415,7 @@
 {
   pdf_obj  *imported;
   pdf_obj  *tmp;
-  int       i;
+  size_t    i;
 
   switch (pdf_obj_typeof(object)) {
 
@@ -4233,8 +4461,8 @@
     for (i = 0; i < pdf_array_length(object); i++) {
       tmp = pdf_import_object(pdf_get_array(object, i));
       if (!tmp) {
-	pdf_release_obj(imported);
-	return NULL;
+        pdf_release_obj(imported);
+        return NULL;
       }
       pdf_add_array(imported, tmp);
     }

Modified: trunk/Build/source/texk/dvipdfm-x/pdfobj.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfobj.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfobj.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2007-2020 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 
+typedef struct pdf_out pdf_out;
 
 /* Here is the complete list of PDF object types */
 
@@ -54,13 +55,19 @@
 extern void     pdf_error_cleanup   (void);
 
 extern FILE    *pdf_get_output_file (void);
+extern pdf_out *pdf_out_init (const char *filename,
+                              const unsigned char *id1, const unsigned char *id2,
+                              int ver_major, int ver_minor,
+                              int compression_level,
+                              int enable_encrypt,
+                              int enable_objstm,
+                              int enable_predictor);
+extern void     pdf_out_set_encrypt (int keybits, int32_t permission,
+                                     const char *opasswd, const char *upasswd,
+                                     int use_aes, int encrypt_metadata);
+extern void     pdf_out_flush     (void);
 
-extern void     pdf_out_init      (const char *filename,
-                                   int enable_encrypt, int enable_objstm,
-                                   int enable_predictor);
-extern void     pdf_out_flush     (void);
-extern void     pdf_set_version   (int version);
-extern int      pdf_get_version   (void);
+extern int      pdf_get_version       (void);
 extern int      pdf_get_version_major (void);
 extern int      pdf_get_version_minor (void);
 
@@ -152,6 +159,7 @@
 extern void        pdf_add_stream        (pdf_obj *stream,
                                           const void *stream_data_ptr,
                                           int stream_data_len);
+
 extern int         pdf_concat_stream     (pdf_obj *dst, pdf_obj *src);
 extern pdf_obj    *pdf_stream_dict       (pdf_obj *stream);
 extern int         pdf_stream_length     (pdf_obj *stream);
@@ -164,24 +172,21 @@
                                              int predictor, int32_t columns,
                                              int bpc, int colors);
 
-/* Compare labels of two indirect reference object. */
+/* Compare label of two indirect reference object. */
 extern int         pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2);
 /* Compare objects. */
 extern int         pdf_compare_object    (pdf_obj *obj1, pdf_obj *obj2);
 
+
 /* The following routines are not appropriate for pdfobj.
  */
 
-extern void      pdf_set_compression (int level);
-
 extern void      pdf_set_info     (pdf_obj *obj);
 extern void      pdf_set_root     (pdf_obj *obj);
-extern void      pdf_set_id       (pdf_obj *id);
-extern void      pdf_set_encrypt  (pdf_obj *encrypt);
 
 extern void      pdf_files_init    (void);
 extern void      pdf_files_close   (void);
-extern int      check_for_pdf     (FILE *file);
+extern int       check_for_pdf     (FILE *file);
 extern pdf_file *pdf_open          (const char *ident, FILE *file);
 extern void      pdf_close         (pdf_file *pf);
 extern pdf_obj  *pdf_file_get_trailer (pdf_file *pf);
@@ -193,7 +198,7 @@
 
 extern int      pdfobj_escape_str (char *buffer, int size, const unsigned char *s, int len);
 
-extern pdf_obj *pdf_new_indirect  (pdf_file *pf, unsigned label, unsigned short generation);
+extern pdf_obj *pdf_new_indirect  (pdf_file *pf, uint32_t label, uint16_t generation);
 
 extern int pdf_check_version (int major, int minor);
 

Modified: trunk/Build/source/texk/dvipdfm-x/pdfparse.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfparse.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfparse.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2016 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -70,8 +70,6 @@
 
 static int xtoi (char ch);
 
-static const char *save = NULL;
-
 void
 dump (const char *start, const char *end)
 {
@@ -86,14 +84,6 @@
   MESG("<--\n");
 }
 
-#define SAVE(s,e) do {\
-   save = (s);\
- } while (0)
-#define DUMP_RESTORE(s,e) do {\
-   dump(save, end);\
-   (s) = save;\
- } while (0)
-
 void
 pdfparse_skip_line (const char **start, const char *end)
 {
@@ -646,29 +636,13 @@
   return NULL;
 }
 
-#ifndef PDF_PARSE_STRICT
-pdf_obj *
-parse_pdf_tainted_dict (const char **pp, const char *endptr)
+static pdf_obj *
+parse_pdf_dict_extended (const char **pp, const char *endptr, pdf_file *pf,
+                         pdf_obj* (*unknown_handler) (const char **pp,
+                                                      const char *endptr,
+                                                      void *user_data),
+                         void *user_data)
 {
-  pdf_obj *result;
-
-  parser_state.tainted = 1;
-  result  = parse_pdf_dict(pp, endptr, NULL);
-  parser_state.tainted = 0;
-
-  return result;
-}
-#else /* PDF_PARSE_STRICT */
-pdf_obj *
-parse_pdf_tainted_dict (const char **pp, const char *endptr)
-{
-  return parse_pdf_dict(pp, endptr, NULL);
-}
-#endif /* !PDF_PARSE_STRICT */
-
-pdf_obj *
-parse_pdf_dict (const char **pp, const char *endptr, pdf_file *pf)
-{
   pdf_obj *result = NULL;
   const char *p;
 
@@ -699,7 +673,7 @@
 
     skip_white(&p, endptr);
 
-    value = parse_pdf_object(&p, endptr, pf);
+    value = parse_pdf_object_extended(&p, endptr, pf, unknown_handler, user_data);
     if (!value) {
       pdf_release_obj(key); 
       pdf_release_obj(value);
@@ -723,8 +697,12 @@
   return result;
 }
 
-pdf_obj *
-parse_pdf_array (const char **pp, const char *endptr, pdf_file *pf)
+static pdf_obj *
+parse_pdf_array_extended (const char **pp, const char *endptr, pdf_file *pf,
+                          pdf_obj* (*unknown_handler) (const char **pp,
+                                                       const char *endptr,
+                                                       void *user_data),
+                          void *user_data)
 {
   pdf_obj *result;
   const char *p;
@@ -745,7 +723,7 @@
   while (p < endptr && p[0] != ']') {
     pdf_obj *elem;
 
-    elem = parse_pdf_object(&p, endptr, pf);
+    elem = parse_pdf_object_extended(&p, endptr, pf, unknown_handler, user_data);
     if (!elem) {
       pdf_release_obj(result); 
       WARN("Could not find a valid object in array object.");
@@ -865,40 +843,7 @@
   return  result;
 }
 
-#ifndef PDF_PARSE_STRICT
-
-/* PLEASE REMOVE THIS */
-#include "specials.h"
-
-/* This is not PDF indirect reference. */
 static pdf_obj *
-parse_pdf_reference (const char **start, const char *end)
-{
-  pdf_obj *result = NULL;
-  char    *name;
-
-  SAVE(*start, end);
-
-  skip_white(start, end);
-  name = parse_opt_ident(start, end);
-  if (name) {
-    result = spc_lookup_reference(name);
-    if (!result) {
-      WARN("Could not find the named reference (@%s).", name);
-      DUMP_RESTORE(*start, end);
-    }
-    RELEASE(name);
-  } else {
-    WARN("Could not find a reference name.");
-    DUMP_RESTORE(*start, end);
-    result = NULL;
-  }
-
-  return result;
-}
-#endif /* !PDF_PARSE_STRICT */
-
-static pdf_obj *
 try_pdf_reference (const char *start, const char *end, const char **endptr, pdf_file *pf)
 {
   unsigned id = 0;
@@ -945,7 +890,11 @@
 }
 
 pdf_obj *
-parse_pdf_object (const char **pp, const char *endptr, pdf_file *pf)
+parse_pdf_object_extended (const char **pp, const char *endptr, pdf_file *pf,
+                           pdf_obj* (*unknown_handler) (const char **pp,
+                                                        const char *endptr,
+                                                        void *user_data),
+                           void *user_data)
 /* If pf is NULL, then indirect references are not allowed */
 {
   pdf_obj *result = NULL;
@@ -966,7 +915,7 @@
     } else {
       pdf_obj *dict;
 
-      result = parse_pdf_dict(pp, endptr, pf);
+      result = parse_pdf_dict_extended(pp, endptr, pf, unknown_handler, user_data);
       skip_white(pp, endptr);
       if ( result &&
           *pp <= endptr - 15 &&
@@ -982,7 +931,7 @@
     result = parse_pdf_string(pp, endptr);
     break;
   case '[':
-    result = parse_pdf_array(pp, endptr, pf);
+    result = parse_pdf_array_extended(pp, endptr, pf, unknown_handler, user_data);
     break;
   case '/':
     result = parse_pdf_name(pp, endptr);
@@ -1010,18 +959,51 @@
     }
     break;
 
-  case '@':
-
-#ifndef PDF_PARSE_STRICT
-    result = parse_pdf_reference(pp, endptr);
-#endif /* !PDF_PARSE_STRICT */
+  default:
+    if (unknown_handler) {
+      result = unknown_handler(pp, endptr, user_data);
+    } else {
+      WARN("Unknown PDF object type.");
+      result = NULL;
+    }
     break;
-
-  default:
-    WARN("Unknown PDF object type.");
-    result = NULL;
   }
 
   return result;
 }
 
+pdf_obj *
+parse_pdf_dict (const char **pp, const char *endptr, pdf_file *pf)
+{
+  return parse_pdf_dict_extended(pp, endptr, pf, NULL, NULL);
+}
+
+pdf_obj *
+parse_pdf_array (const char **pp, const char *endptr, pdf_file *pf)
+{
+  return parse_pdf_array_extended(pp, endptr, pf, NULL, NULL);
+}
+
+pdf_obj *
+parse_pdf_object (const char **pp, const char *endptr, pdf_file *pf)
+{
+  return parse_pdf_object_extended(pp, endptr, pf, NULL, NULL);
+}
+
+
+pdf_obj *
+parse_pdf_tainted_dict (const char **pp, const char *endptr,
+                        pdf_obj* (*unknown_handler) (const char **pp,
+                                                     const char *endptr,
+                                                     void *user_data),
+                        void *user_data)
+{
+  pdf_obj *result;
+
+  parser_state.tainted = 1;
+  result  = parse_pdf_dict_extended(pp, endptr, NULL, unknown_handler, user_data);
+  parser_state.tainted = 0;
+
+  return result;
+}
+

Modified: trunk/Build/source/texk/dvipdfm-x/pdfparse.h
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfparse.h	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfparse.h	2020-07-25 22:06:35 UTC (rev 55945)
@@ -1,6 +1,6 @@
 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
-    Copyright (C) 2002-2016 by Jin-Hwan Cho and Shunsaku Hirata,
+    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
     the dvipdfmx project team.
     
     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks at kettering.edu>
@@ -48,6 +48,15 @@
 extern pdf_obj *parse_pdf_array   (const char **pp, const char *endptr, pdf_file *pf);
 extern pdf_obj *parse_pdf_object  (const char **pp, const char *endptr, pdf_file *pf);
 
-extern pdf_obj *parse_pdf_tainted_dict (const char **pp, const char *endptr);
+extern pdf_obj *parse_pdf_object_extended (const char **pp, const char *endptr, pdf_file *pf,
+                                           pdf_obj* (*unknown_handler) (const char **pp,
+                                                                        const char *endptr,
+                                                                        void *user_data),
+                                           void *user_data);
+extern pdf_obj *parse_pdf_tainted_dict (const char **pp, const char *endptr,
+                                        pdf_obj* (*unknown_handler) (const char **pp,
+                                                                     const char *endptr,
+                                                                     void *user_data),
+                                        void *user_data);
 
 #endif /* _PDFPARSE_H_ */

Modified: trunk/Build/source/texk/dvipdfm-x/pdfximage.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/pdfximage.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/pdfximage.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -38,7 +38,6 @@
 #include "pdfdev.h"
 #include "pdfdraw.h"
 #include "pdfnames.h"
-#include "specials.h"
 
 #include "epdf.h"
 #include "mpost.h"

Modified: trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/spc_pdfm.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -59,12 +59,6 @@
 
 #define SPC_PDFM_SUPPORT_ANNOT_TRANS 1
 
-/* PLEASE REMOVE THIS */
-struct resource_map {
-  int   type;
-  int   res_id;
-};
-
 struct tounicode {
   int       cmap_id;
   int       unescape_backslash;
@@ -86,7 +80,28 @@
   NULL
 };
 
+static pdf_obj *
+parse_pdf_reference (const char **start, const char *end, void *user_data)
+{
+  pdf_obj *result = NULL;
+  char    *name;
 
+  skip_white(start, end);
+  name = parse_opt_ident(start, end);
+  if (name) {
+    result = spc_lookup_reference(name);
+    if (!result) {
+      WARN("Could not find the named reference (@%s).", name);
+    }
+    RELEASE(name);
+  } else {
+    WARN("Could not find a reference name.");
+    result = NULL;
+  }
+
+  return result;
+}
+
 static int
 spc_handler_pdfm__init (void *dp)
 {
@@ -340,7 +355,7 @@
   }
   skip_white(&ap->curptr, ap->endptr);
 
-  obj2 = parse_pdf_object(&ap->curptr, ap->endptr, NULL);
+  obj2 = parse_pdf_object_extended(&ap->curptr, ap->endptr, NULL, parse_pdf_reference, spe);
   if (!obj2) {
     spc_warn(spe, "Missing (an) object(s) to put into \"%s\"!", ident);
     RELEASE(ident);
@@ -386,7 +401,7 @@
     /* dvipdfm */
     pdf_add_array(obj1, pdf_link_obj(obj2));
     while (ap->curptr < ap->endptr) {
-      pdf_obj *obj3 = parse_pdf_object(&ap->curptr, ap->endptr, NULL);
+      pdf_obj *obj3 = parse_pdf_object_extended(&ap->curptr, ap->endptr, NULL, parse_pdf_reference, spe);
       if (!obj3)
 	break;
       pdf_add_array(obj1, obj3);
@@ -577,17 +592,30 @@
   pdf_obj  *dict;
 
   /* disable this test for XDV files, as we do UTF8 reencoding with no cmap */
-  if ((dpx_conf.compat_mode != dpx_mode_xdv_mode) && cd->cmap_id < 0)
-    return  parse_pdf_dict(pp, endptr, NULL);
-
-  /* :( */
-  if (cd && cd->unescape_backslash) 
-    dict = parse_pdf_tainted_dict(pp, endptr);
-  else {
-    dict = parse_pdf_dict(pp, endptr, NULL);
+  if ((dpx_conf.compat_mode != dpx_mode_xdv_mode) && cd->cmap_id < 0) {
+    dict = parse_pdf_object_extended(pp, endptr, NULL, parse_pdf_reference, NULL); 
+    if (dict && !PDF_OBJ_DICTTYPE(dict)) {
+      WARN("Dictionary type object expected but non-dictionary type found.");
+      pdf_release_obj(dict);
+      dict = NULL;
+    }
+  } else {
+    /* :( */
+    if (cd && cd->unescape_backslash) {
+      dict = parse_pdf_tainted_dict(pp, endptr, parse_pdf_reference, NULL);
+    } else {
+      dict = parse_pdf_object_extended(pp, endptr, NULL, parse_pdf_reference, NULL);
+    }
+    if (dict) {
+      if (!PDF_OBJ_DICTTYPE(dict)) {
+        WARN("Dictionary type object expected but non-dictionary type found.");
+        pdf_release_obj(dict);
+        dict = NULL;
+      } else {
+        pdf_foreach_dict(dict, modstrings, cd);
+      }
+    }
   }
-  if (dict)
-    pdf_foreach_dict(dict, modstrings, cd);
 
   return  dict;
 }
@@ -1246,7 +1274,7 @@
 
   skip_white(&args->curptr, args->endptr);
   if (args->curptr < args->endptr) {
-    options.dict = parse_pdf_object(&args->curptr, args->endptr, NULL);
+    options.dict = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
   }
 
   xobj_id = pdf_ximage_load_image(ident, pdf_string_value(fspec), options);
@@ -1297,7 +1325,7 @@
     WARN("Failed to convert input string to UTF16...");
 #endif
 
-  array = parse_pdf_object(&args->curptr, args->endptr, NULL);
+  array = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
   if (!array) {
     spc_warn(spe, "No destination specified for pdf:dest.");
     pdf_release_obj(name);
@@ -1334,7 +1362,7 @@
     return  -1;
   }
 
-  tmp = parse_pdf_object(&args->curptr, args->endptr, NULL);
+  tmp = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
   if (!tmp) {
     spc_warn(spe, "PDF object expected but not found.");
     pdf_release_obj(category);
@@ -1369,7 +1397,7 @@
     pdf_release_obj(tmp);
   } else if (PDF_OBJ_STRINGTYPE(tmp)) {
     key   = tmp;
-    value = parse_pdf_object(&args->curptr, args->endptr, NULL);
+    value = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
     if (!value) {
       pdf_release_obj(category);
       pdf_release_obj(key);
@@ -1474,7 +1502,7 @@
     return  -1;
   }
 
-  object = parse_pdf_object(&args->curptr, args->endptr, NULL);
+  object = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
   if (!object) {
     spc_warn(spe, "Could not find an object definition for \"%s\".", ident);
     RELEASE(ident);
@@ -1692,12 +1720,18 @@
 
     stream_dict = pdf_stream_dict(fstream);
 
-    tmp = parse_pdf_dict(&args->curptr, args->endptr, NULL);
+    tmp = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
     if (!tmp) {
       spc_warn(spe, "Parsing dictionary failed.");
       pdf_release_obj(fstream);
       RELEASE(ident);
       return -1;
+    } else if (!PDF_OBJ_DICTTYPE(tmp)) {
+      spc_warn(spe, "Expecting dictionary type object but non-dictionary type found.");
+      pdf_release_obj(fstream);
+      pdf_release_obj(tmp);
+      RELEASE(ident);
+      return -1;
     }
     if (pdf_lookup_dict(tmp, "Length")) {
       pdf_remove_dict(tmp, "Length");
@@ -1829,7 +1863,7 @@
   skip_white(&args->curptr, args->endptr);
 
   if (args->curptr < args->endptr) {
-    attrib = parse_pdf_dict(&args->curptr, args->endptr, NULL);
+    attrib = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
     if (attrib && !PDF_OBJ_DICTTYPE(attrib)) {
       pdf_release_obj(attrib);
       attrib = NULL;
@@ -2131,7 +2165,7 @@
   struct spc_pdf_ *sd = &_pdf_stat;
   pdf_obj *dict;
 
-  dict = parse_pdf_object(&args->curptr, args->endptr, NULL);
+  dict = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
   if (!dict) {
     spc_warn(spe, "Dictionary object expected but not found.");
     return  -1;
@@ -2147,19 +2181,19 @@
 static int
 spc_handler_pdfm_bxgstate (struct spc_env *spe, struct spc_arg *args)
 {
-  pdf_obj *object;
+  pdf_obj *obj;
 
   skip_white(&args->curptr, args->endptr);
-  object = parse_pdf_object(&args->curptr, args->endptr, NULL);
-  if (!object) {
+  obj = parse_pdf_object_extended(&args->curptr, args->endptr, NULL, parse_pdf_reference, spe);
+  if (!obj) {
     spc_warn(spe, "Could not find an object definition.");
     return -1;
-  } else if (!PDF_OBJ_DICTTYPE(object)) {
+  } else if (!PDF_OBJ_DICTTYPE(obj)) {
     spc_warn(spe, "Parsed object for ExtGState not a dictionary object!");
-    pdf_release_obj(object);
+    pdf_release_obj(obj);
     return -1;
   }
-  pdf_dev_xgstate_push(object);
+  pdf_dev_xgstate_push(obj);
 
   skip_white(&args->curptr, args->endptr);
 

Modified: trunk/Build/source/texk/dvipdfm-x/xbb.c
===================================================================
--- trunk/Build/source/texk/dvipdfm-x/xbb.c	2020-07-25 21:47:49 UTC (rev 55944)
+++ trunk/Build/source/texk/dvipdfm-x/xbb.c	2020-07-25 22:06:35 UTC (rev 55945)
@@ -304,7 +304,7 @@
 
   pdf_files_init();
 
-  pdf_set_version(PDF_VERSION_MAX);
+  dpx_conf.is_xbb = 1;
 
   opterr = 0;
   



More information about the tex-live-commits mailing list.