summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c')
-rw-r--r--Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c992
1 files changed, 992 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c b/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c
new file mode 100644
index 00000000000..ac97ed11198
--- /dev/null
+++ b/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c
@@ -0,0 +1,992 @@
+/*
+
+ This is xdvipdfmx, an extended version of...
+
+ DVIPDFMx, an eXtended-2013 version of DVIPDFM by Mark A. Wicks.
+
+ Copyright (c) 2006 SIL. (xdvipdfmx extensions for XeTeX support)
+
+ Copyright (C) 2008-2013 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata,
+ the DVIPDFMx project team.
+
+ Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "system.h"
+#include "mem.h"
+
+#include "dpxconf.h"
+#include "dpxfile.h"
+#include "dpxutil.h"
+
+#include "dvi.h"
+
+#include "pdflimits.h"
+#include "pdfdoc.h"
+#include "pdfdev.h"
+#include "pdfparse.h"
+#include "pdfencrypt.h"
+
+#include "spc_tpic.h"
+#include "specials.h"
+
+#include "mpost.h"
+
+#include "fontmap.h"
+#include "pdffont.h"
+#include "pdfximage.h"
+#include "cid.h"
+
+#include "xbb.h"
+
+#include "tt_aux.h"
+
+#include "error.h"
+
+static int verbose = 0;
+
+static int mp_mode = 0;
+
+static long opt_flags = 0;
+
+#define OPT_TPIC_TRANSPARENT_FILL (1 << 1)
+#define OPT_CIDFONT_FIXEDPITCH (1 << 2)
+#define OPT_FONTMAP_FIRST_MATCH (1 << 3)
+
+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 really_quiet = 0;
+/*
+ * Precision is essentially limited to 0.01pt.
+ * See, dev_set_string() in pdfdev.c.
+ */
+static int pdfdecimaldigits = 2;
+
+/* 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;
+
+/* Encryption */
+static int do_encryption = 0;
+static unsigned key_bits = 40;
+static unsigned permission = 0x003C;
+
+/* Page device */
+double paper_width = 595.0; /* not static, we allow dvi.c to access them */
+double paper_height = 842.0;
+char landscape_mode = 0;
+
+static double x_offset = 72.0;
+static double y_offset = 72.0;
+
+int always_embed = 0; /* always embed fonts, regardless of licensing flags */
+
+char *dvi_filename = NULL, *pdf_filename = NULL;
+
+static void
+read_config_file (const char *config);
+
+#ifdef WIN32
+#define STRN_CMP strncasecmp
+#else
+#define STRN_CMP strncmp
+#endif
+
+static void
+set_default_pdf_filename(void)
+{
+ const char *dvi_base;
+
+ dvi_base = xbasename(dvi_filename);
+ if (mp_mode &&
+ strlen(dvi_base) > 4 &&
+ !STRN_CMP(".mps", dvi_base + strlen(dvi_base) - 4, 4)) {
+ pdf_filename = NEW(strlen(dvi_base)+1, char);
+ strncpy(pdf_filename, dvi_base, strlen(dvi_base) - 4);
+ pdf_filename[strlen(dvi_base)-4] = '\0';
+ } else if (strlen(dvi_base) > 4 &&
+#ifdef XETEX
+ (!STRN_CMP(".dvi", dvi_base+strlen(dvi_base)-4, 4) ||
+ !STRN_CMP(".xdv", dvi_base+strlen(dvi_base)-4, 4))) {
+#else
+ !STRN_CMP(".dvi", dvi_base+strlen(dvi_base)-4, 4)) {
+#endif
+ pdf_filename = NEW(strlen(dvi_base)+1, char);
+ strncpy(pdf_filename, dvi_base, strlen(dvi_base)-4);
+ pdf_filename[strlen(dvi_base)-4] = '\0';
+ } else {
+ pdf_filename = NEW(strlen(dvi_base)+5, char);
+ strcpy(pdf_filename, dvi_base);
+ }
+
+ strcat (pdf_filename, ".pdf");
+}
+
+static void
+usage (int exit_code)
+{
+ fprintf (stdout, "\nThis is %s-%s by Jonathan Kew and Jin-Hwan Cho,\n", PACKAGE, VERSION);
+ fprintf (stdout, "an extended version of DVIPDFMx, which in turn was\n");
+ fprintf (stdout, "an extended version of dvipdfm-0.13.2c developed by Mark A. Wicks.\n");
+ fprintf (stdout, "\nCopyright (c) 2006-2013 SIL International and Jin-Hwan Cho.\n");
+ fprintf (stdout, "\nThis is free software; you can redistribute it and/or modify\n");
+ fprintf (stdout, "it under the terms of the GNU General Public License as published by\n");
+ fprintf (stdout, "the Free Software Foundation; either version 2 of the License, or\n");
+ fprintf (stdout, "(at your option) any later version.\n");
+ fprintf (stdout, "\nUsage: xdvipdfmx [options] xdvfile\n");
+ fprintf (stdout, "-c \t\tIgnore color specials (for B&W printing)\n");
+ fprintf (stdout, "-d number\tSet PDF decimal digits (0-5) [2]\n");
+ fprintf (stdout, "-f filename\tSet font map file name [cid-x.map]\n");
+ fprintf (stdout, "-g dimension\tAnnotation \"grow\" amount [0.0in]\n");
+ fprintf (stdout, "-h \t\tShow this help message\n");
+ fprintf (stdout, "-l \t\tLandscape mode\n");
+ fprintf (stdout, "-m number\tSet additional magnification\n");
+ fprintf (stdout, "-o filename\tSet output file name [dvifile.pdf]\n");
+ fprintf (stdout, "-p papersize\tSet papersize [a4]\n");
+ fprintf (stdout, "-q \t\tBe quiet\n");
+ fprintf (stdout, "-r resolution\tSet resolution (in DPI) for raster fonts [600]\n");
+ fprintf (stdout, "-s pages\tSelect page ranges (-)\n");
+ fprintf (stdout, "-t \t\tEmbed thumbnail images of PNG format [dvifile.1] \n");
+ fprintf (stdout, "-x dimension\tSet horizontal offset [1.0in]\n");
+ fprintf (stdout, "-y dimension\tSet vertical offset [1.0in]\n");
+ fprintf (stdout, "-z number \tSet zlib compression level (0-9) [9]\n");
+
+ fprintf (stdout, "-v \t\tBe verbose\n");
+ fprintf (stdout, "-vv\t\tBe more verbose\n");
+ fprintf (stdout, "-C number\tSpecify miscellaneous option flags [0]:\n");
+ fprintf (stdout, "\t\t 0x0001 reserved\n");
+ fprintf (stdout, "\t\t 0x0002 Use semi-transparent filling for tpic shading command,\n");
+ fprintf (stdout, "\t\t\t instead of opaque gray color. (requires PDF 1.4)\n");
+ fprintf (stdout, "\t\t 0x0004 Treat all CIDFont as fixed-pitch font.\n");
+ fprintf (stdout, "\t\t 0x0008 Do not replace duplicate fontmap entries.\n");
+ fprintf (stdout, "\t\tPositive values are always ORed with previously given flags.\n");
+ fprintf (stdout, "\t\tAnd negative values replace old values.\n");
+ fprintf (stdout, "-D template\tPS->PDF conversion command line template [none]\n");
+ fprintf (stdout, "-E \t\tAlways try to embed fonts, regardless of licensing flags.\n");
+ fprintf (stdout, "-I number\tImage cache life in hours [-2]\n");
+ fprintf (stdout, " \t 0: erase all old images and leave new images\n");
+ fprintf (stdout, " \t-1: erase all old images and also erase new images\n");
+ fprintf (stdout, " \t-2: ignore image cache\n");
+ fprintf (stdout, "-K number\tEncryption key length [40]\n");
+ fprintf (stdout, "-O number\tSet maximum depth of open bookmark items [0]\n");
+ fprintf (stdout, "-P number\tSet permission flags for PDF encryption [0x003C]\n");
+ fprintf (stdout, "-S \t\tEnable PDF encryption\n");
+ fprintf (stdout, "-V number\tSet PDF minor version [4]\n");
+ fprintf (stdout, "\nAll dimensions entered on the command line are \"true\" TeX dimensions.\n");
+ fprintf (stdout, "Argument of \"-s\" lists physical page ranges separated by commas, e.g., \"-s 1-3,5-6\"\n");
+ fprintf (stdout, "Papersize is specified by paper format (e.g., \"a4\") or by w<unit>,h<unit> (e.g., \"20cm,30cm\").\n");
+
+ exit(exit_code);
+}
+
+
+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
+ "pt", "in", "cm", "mm", "bp",
+ 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;
+ 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)
+{
+ const struct paper *pi;
+ int error = 0;
+
+ pi = paperinfo(paperspec);
+ if (pi && papername(pi)) {
+ paper_width = paperpswidth (pi);
+ paper_height = paperpsheight(pi);
+ } else {
+ const char *p = paperspec, *endptr, *comma;
+ comma = strchr(p, ',');
+ endptr = p + strlen(p);
+ if (!comma)
+ ERROR("Unrecognized paper format: %s", paperspec);
+ error = read_length(&paper_width, &p, comma);
+ p = comma + 1;
+ error = read_length(&paper_height, &p, endptr);
+ }
+ if (error || paper_width <= 0.0 || paper_height <= 0.0)
+ ERROR("Invalid paper size: %s (%.2fx%.2f)", paperspec, paper_width, paper_height);
+}
+
+struct page_range
+{
+ long first, last;
+} *page_ranges = NULL;
+
+int num_page_ranges = 0;
+int max_page_ranges = 0;
+
+static void
+select_pages (const char *pagespec)
+{
+ char *q;
+ const char *p = pagespec;
+
+ while (*p != '\0') {
+ /* Enlarge page range table if necessary */
+ if (num_page_ranges >= max_page_ranges) {
+ max_page_ranges += 4;
+ page_ranges = RENEW(page_ranges, max_page_ranges, struct page_range);
+ }
+
+ page_ranges[num_page_ranges].first = 0;
+ page_ranges[num_page_ranges].last = 0;
+
+ for ( ; *p && isspace(*p); p++);
+ q = parse_unsigned(&p, p + strlen(p)); /* Can't be signed. */
+ if (q) { /* '-' is allowed here */
+ page_ranges[num_page_ranges].first = atoi(q) - 1;
+ page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first;
+ RELEASE(q);
+ }
+ for ( ; *p && isspace(*p); p++);
+
+ if (*p == '-') {
+ for (++p; *p && isspace(*p); p++);
+ page_ranges[num_page_ranges].last = -1;
+ if (*p) {
+ q = parse_unsigned(&p, p + strlen(p));
+ if (q) {
+ page_ranges[num_page_ranges].last = atoi(q) - 1;
+ RELEASE(q);
+ }
+ for ( ; *p && isspace(*p); p++);
+ }
+ } else {
+ page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first;
+ }
+
+ num_page_ranges++;
+
+ if (*p == ',')
+ p++;
+ else {
+ for ( ; *p && isspace(*p); p++);
+ if (*p)
+ ERROR("Bad page range specification: %s", p);
+ }
+ }
+ return;
+}
+
+#define POP_ARG() {argv += 1; argc -= 1;}
+/* It doesn't work as expected (due to dvi filename). */
+#define CHECK_ARG(n,m) if (argc < (n) + 1) {\
+ fprintf (stderr, "\nMissing %s after \"-%c\".\n", (m), *flag);\
+ usage(1);\
+}
+
+static void
+set_verbose (int argc, char *argv[])
+{
+ while (argc > 0 && *argv[0] == '-') {
+ char *flag;
+
+ for (flag = argv[0] + 1; *flag != 0; flag++) {
+ if (*flag == 'q')
+ really_quiet++;
+ if (*flag == 'v')
+ verbose++;
+ }
+ POP_ARG();
+ }
+
+ if (!really_quiet) {
+ int i;
+
+ for (i = 0; i < verbose; i++) {
+ dvi_set_verbose();
+ pdf_dev_set_verbose();
+ pdf_doc_set_verbose();
+ pdf_enc_set_verbose();
+ pdf_obj_set_verbose();
+ pdf_fontmap_set_verbose();
+ dpx_file_set_verbose();
+ }
+ }
+}
+
+
+static void
+do_args (int argc, char *argv[])
+{
+ while (argc > 0 && *argv[0] == '-') {
+ char *flag, *nextptr;
+ const char *nnextptr;
+
+ for (flag = argv[0] + 1; *flag != 0; flag++) {
+ switch (*flag) {
+ case 'D':
+ CHECK_ARG(1, "PS->PDF conversion command line template");
+ set_distiller_template(argv[1]);
+ POP_ARG();
+ break;
+ case 'r':
+ CHECK_ARG(1, "bitmap font dpi");
+ font_dpi = atoi(argv[1]);
+ if (font_dpi <= 0)
+ ERROR("Invalid bitmap font dpi specified: %s", argv[1]);
+ POP_ARG();
+ break;
+ case 'm':
+ CHECK_ARG(1, "magnification value");
+ mag = strtod(argv[1], &nextptr);
+ if (mag < 0.0 || nextptr == argv[1])
+ ERROR("Invalid magnification specifiied: %s", argv[1]);
+ POP_ARG();
+ break;
+ case 'g':
+ CHECK_ARG(1, "annotation \"grow\" amount");
+ nnextptr = nextptr = argv[1];
+ read_length(&annot_grow, &nnextptr, nextptr + strlen(nextptr));
+ POP_ARG();
+ break;
+ case 'x':
+ CHECK_ARG(1, "horizontal offset value");
+ nnextptr = nextptr = argv[1];
+ read_length(&x_offset, &nnextptr, nextptr + strlen(nextptr));
+ POP_ARG();
+ break;
+ case 'y':
+ CHECK_ARG(1, "vertical offset value");
+ nnextptr = nextptr = argv[1];
+ read_length(&y_offset, &nnextptr, nextptr + strlen(nextptr));
+ POP_ARG();
+ break;
+ case 'o':
+ CHECK_ARG(1, "output file name");
+ pdf_filename = NEW (strlen(argv[1])+1,char);
+ strcpy(pdf_filename, argv[1]);
+ POP_ARG();
+ break;
+ case 's':
+ CHECK_ARG(1, "page selection specification");
+ select_pages(argv[1]);
+ POP_ARG();
+ break;
+ case 't':
+ pdf_doc_enable_manual_thumbnails();
+ break;
+ case 'p':
+ CHECK_ARG(1, "paper format/size");
+ select_paper(argv[1]);
+ POP_ARG();
+ break;
+ case 'c':
+ ignore_colors = 1;
+ break;
+ case 'l':
+ landscape_mode = 1;
+ break;
+ case 'f':
+ CHECK_ARG(1, "fontmap file name");
+ if (opt_flags & OPT_FONTMAP_FIRST_MATCH)
+ pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_APPEND);
+ else
+ pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_REPLACE);
+ POP_ARG();
+ break;
+ case 'i':
+ CHECK_ARG(1, "subsidiary config file");
+ read_config_file(argv[1]);
+ POP_ARG();
+ break;
+ case 'e':
+ WARN("dvipdfm \"-e\" option not supported.");
+ break;
+ case 'q': case 'v':
+ break;
+ case 'V':
+ {
+ int ver_minor;
+
+ if (isdigit(*(flag+1))) {
+ flag++;
+ ver_minor = atoi(flag);
+ } else {
+ CHECK_ARG(1, "PDF minor version number");
+ ver_minor = atoi(argv[1]);
+ POP_ARG();
+ }
+ if (ver_minor < PDF_VERSION_MIN) {
+ WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.",
+ ver_minor, PDF_VERSION_MIN);
+ ver_minor = PDF_VERSION_MIN;
+ } else if (ver_minor > PDF_VERSION_MAX) {
+ WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.",
+ ver_minor, PDF_VERSION_MAX);
+ ver_minor = PDF_VERSION_MAX;
+ }
+ pdf_set_version((unsigned) ver_minor);
+ }
+ break;
+ case 'z':
+ {
+ int level;
+
+ if (isdigit(*(flag+1))) {
+ flag++;
+ level = atoi(flag);
+ } else {
+ CHECK_ARG(1, "compression level");
+ level = atoi(argv[1]);
+ POP_ARG();
+ }
+ pdf_set_compression(level);
+ }
+ break;
+ case 'd':
+ if (isdigit(*(flag+1))) {
+ flag++;
+ pdfdecimaldigits = atoi(flag);
+ } else {
+ CHECK_ARG(1, "number of fractional digits");
+ pdfdecimaldigits = atoi(argv[1]);
+ POP_ARG();
+ }
+ break;
+ case 'I':
+ CHECK_ARG(1, "image cache life in hours");
+ image_cache_life = atoi(argv[1]);
+ POP_ARG();
+ break;
+ case 'S':
+ do_encryption = 1;
+ break;
+ case 'K':
+ CHECK_ARG(1, "encryption key length");
+ key_bits = (unsigned) atoi(argv[1]);
+ if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7))
+ ERROR("Invalid encryption key length specified: %s", argv[1]);
+ POP_ARG();
+ break;
+ case 'P':
+ CHECK_ARG(1, "encryption permission flag");
+ permission = (unsigned) strtoul(argv[1], &nextptr, 0);
+ if (nextptr == argv[1])
+ ERROR("Invalid encryption permission flag: %s", argv[1]);
+ POP_ARG();
+ break;
+ case 'O':
+ /* Bookmark open level */
+ CHECK_ARG(1, "bookmark open level");
+ bookmark_open = atoi(argv[1]);
+ POP_ARG();
+ break;
+ case 'M':
+ mp_mode = 1;
+ break;
+ case 'C':
+ CHECK_ARG(1, "a number");
+ {
+ long flags;
+
+ flags = (unsigned) strtol(argv[1], &nextptr, 0);
+ if (nextptr == argv[1])
+ ERROR("Invalid flag: %s", argv[1]);
+ if (flags < 0)
+ opt_flags = -flags;
+ else
+ opt_flags |= flags;
+ }
+ POP_ARG();
+ break;
+ case 'E':
+ always_embed = 1;
+ break;
+ case 'h':
+ usage(0);
+ break;
+ default:
+ fprintf (stderr, "Unknown option in \"%s\"", flag);
+ usage(1);
+ break;
+ }
+ }
+ POP_ARG();
+ }
+
+ if (argc > 1) {
+ fprintf(stderr, "Multiple dvi filenames?");
+ usage(1);
+ } else if (argc > 0) {
+ /*
+ * The only legitimate way to have argc == 0 here is
+ * do_args was called from config file. In that case, there is
+ * no dvi file name. Check for that case .
+ */
+ dvi_filename = NEW(strlen(argv[0]) + 5, char); /* space to append .dvi */
+ strcpy(dvi_filename, argv[0]);
+ }
+}
+
+static void
+cleanup (void)
+{
+ if (dvi_filename)
+ RELEASE(dvi_filename);
+ if (pdf_filename)
+ RELEASE(pdf_filename);
+ if (page_ranges)
+ RELEASE(page_ranges);
+}
+
+static void
+read_config_file (const char *config)
+{
+ const char *start, *end;
+ char *option;
+ FILE *fp;
+
+ fp = DPXFOPEN(config, DPX_RES_TYPE_TEXT);
+ if (!fp) {
+ WARN("Could not open config file \"%s\".", config);
+ return;
+ }
+ while ((start = mfgets (work_buffer, WORK_BUFFER_SIZE, fp)) != NULL) {
+ char *argv[2];
+ int argc;
+
+ argc = 0;
+ end = work_buffer + strlen(work_buffer);
+ skip_white (&start, end);
+ if (start >= end)
+ continue;
+ /* Build up an argument list as if it were passed on the command
+ line */
+ if ((option = parse_ident (&start, end))) {
+ argc = 1;
+ argv[0] = NEW (strlen(option)+2, char);
+ strcpy (argv[0]+1, option);
+ RELEASE (option);
+ *argv[0] = '-';
+ skip_white (&start, end);
+ if (start < end) {
+ argc += 1;
+ if (*start == '"') {
+ argv[1] = parse_c_string (&start, end);
+ }
+ else
+ argv[1] = parse_ident (&start, end);
+ }
+ }
+ do_args (argc, argv);
+ while (argc > 0) {
+ RELEASE (argv[--argc]);
+ }
+ }
+ if (fp)
+ MFCLOSE(fp);
+}
+
+static void
+system_default (void)
+{
+ if (systempapername() != NULL) {
+ select_paper(systempapername());
+ } else if (defaultpapername() != NULL) {
+ select_paper(defaultpapername());
+ }
+}
+
+void
+error_cleanup (void)
+{
+ pdf_error_cleanup();
+ if (pdf_filename) {
+ remove(pdf_filename);
+ fprintf(stderr, "\nOutput file removed.\n");
+ }
+}
+
+#define SWAP(v1,v2) do {\
+ double _tmp = (v1);\
+ (v1) = (v2);\
+ (v2) = _tmp;\
+ } while (0)
+
+static void
+do_dvi_pages (void)
+{
+ long page_no, page_count, i, step;
+ double page_width, page_height;
+ double init_paper_width, init_paper_height;
+ pdf_rect mediabox;
+
+ spc_exec_at_begin_document();
+
+ if (num_page_ranges == 0) {
+ if (!page_ranges) {
+ page_ranges = NEW(1, struct page_range);
+ max_page_ranges = 1;
+ }
+ page_ranges[0].first = 0;
+ page_ranges[0].last = -1; /* last page */
+ num_page_ranges = 1;
+ }
+
+ init_paper_width = page_width = paper_width;
+ init_paper_height = page_height = paper_height;
+ page_count = 0;
+
+ mediabox.llx = 0.0;
+ mediabox.lly = 0.0;
+ mediabox.urx = paper_width;
+ mediabox.ury = paper_height;
+
+ pdf_doc_set_mediabox(0, &mediabox); /* Root node */
+
+ for (i = 0; i < num_page_ranges && dvi_npages() > 0; i++) {
+ if (page_ranges[i].last < 0)
+ page_ranges[i].last += dvi_npages();
+
+ step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1;
+ page_no = page_ranges[i].first;
+ while (dvi_npages() > 0) {
+ if (page_no < dvi_npages()) {
+ double w, h, xo, yo;
+ char lm;
+
+ /* Users want to change page size even after page is started! */
+ 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);
+ if (lm != landscape_mode) {
+ SWAP(w, h);
+ landscape_mode = lm;
+ }
+ if (page_width != w || page_height != h) {
+ page_width = w;
+ page_height = h;
+ }
+ if (x_offset != xo || y_offset != yo) {
+ x_offset = xo;
+ y_offset = yo;
+ }
+ if (page_width != init_paper_width ||
+ page_height != init_paper_height) {
+ mediabox.llx = 0.0;
+ mediabox.lly = 0.0;
+ mediabox.urx = page_width;
+ mediabox.ury = page_height;
+ pdf_doc_set_mediabox(page_count+1, &mediabox);
+ }
+ dvi_do_page(page_no,
+ page_width, page_height, x_offset, y_offset);
+ page_count++;
+ }
+
+ if (step > 0 &&
+ page_no >= page_ranges[i].last)
+ break;
+ else if (step < 0 &&
+ page_no <= page_ranges[i].last)
+ break;
+ else {
+ page_no += step;
+ }
+ }
+ }
+
+ if (page_count < 1) {
+ ERROR("No pages fall in range!");
+ }
+
+ spc_exec_at_end_document();
+}
+
+static void
+do_mps_pages (void)
+{
+ FILE *fp;
+
+ /* _FIXME_ */
+ fp = MFOPEN(dvi_filename, FOPEN_RBIN_MODE);
+ if (fp) {
+ mps_do_page(fp);
+ MFCLOSE(fp);
+ } else {
+ int i, page_no, step, page_count = 0;
+ char *filename;
+ /* Process filename.1, filename.2,... */
+ filename = NEW(strlen(dvi_filename) + 16 + 1, char);
+ for (i = 0; i < num_page_ranges; i++) {
+ if (page_ranges[i].last < 0)
+ ERROR("Invalid page number for MPS input: -1");
+
+ step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1;
+ page_no = page_ranges[i].first;
+ for (;;) {
+ sprintf(filename, "%s.%d", dvi_filename, page_no + 1);
+ fp = MFOPEN(filename, FOPEN_RBIN_MODE);
+ if (fp) {
+ MESG("[%d<%s>", page_no + 1, filename);
+ mps_do_page(fp);
+ page_count++;
+ MESG("]");
+ MFCLOSE(fp);
+ }
+ if (step > 0 &&
+ page_no >= page_ranges[i].last)
+ break;
+ else if (step < 0 &&
+ page_no <= page_ranges[i].last)
+ break;
+ else {
+ page_no += step;
+ }
+ }
+ }
+ RELEASE(filename);
+ if (page_count == 0)
+ ERROR("No page output for \"%s\".", dvi_filename);
+ }
+}
+
+
+/* TODO: MetaPost mode */
+#if defined(MIKTEX)
+# define main Main
+#endif
+int CDECL
+main (int argc, char *argv[])
+{
+ double dvi2pts;
+
+ const char *av0 = xbasename(argv[0]);
+ if (STRN_CMP(av0, "ebb", 3) == 0)
+ return extractbb(argc, argv, EBB_OUTPUT);
+ else if (STRN_CMP(av0, "xbb", 3) == 0 || STRN_CMP(av0, "extractbb", 9) == 0)
+ return extractbb(argc, argv, XBB_OUTPUT);
+
+#ifdef MIKTEX
+ miktex_initialize();
+#else
+ kpse_set_program_name(argv[0], "dvipdfmx"); /* we pretend to be dvipdfmx for kpse purposes */
+#ifdef WIN32
+ texlive_gs_init ();
+#endif
+#endif
+
+ paperinit();
+ system_default();
+
+ argv+=1;
+ argc-=1;
+
+ set_verbose(argc, argv);
+
+ pdf_init_fontmaps(); /* This must come before parsing options... */
+
+ read_config_file(DPX_CONFIG_FILE);
+
+ do_args (argc, argv);
+
+ if (really_quiet)
+ shut_up(really_quiet);
+
+#ifndef MIKTEX
+ kpse_init_prog("", font_dpi, NULL, NULL);
+ kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf);
+#endif
+ pdf_font_set_dpi(font_dpi);
+ dpx_delete_old_cache(image_cache_life);
+
+ if (dvi_filename == NULL) {
+ if (verbose)
+ MESG("No dvi filename specified, reading standard input.\n");
+ if (pdf_filename == NULL)
+ if (verbose)
+ MESG("No pdf filename specified, writing to standard output.\n");
+ }
+
+ if (pdf_filename == NULL && dvi_filename != NULL)
+ set_default_pdf_filename();
+
+ pdf_enc_compute_id_string(dvi_filename, pdf_filename);
+ if (do_encryption) {
+ pdf_enc_set_passwd(key_bits, permission, NULL, NULL);
+ if (key_bits > 40 && pdf_get_version() < 4)
+ pdf_set_version(4);
+ }
+
+ if (mp_mode) {
+ x_offset = 0.0;
+ y_offset = 0.0;
+ dvi2pts = 0.01; /* dvi2pts controls accuracy. */
+ } else {
+ unsigned ver_minor = 0;
+ char owner_pw[MAX_PWD_LEN], user_pw[MAX_PWD_LEN];
+ /* Dependency between DVI and PDF side is rather complicated... */
+ dvi2pts = dvi_init(dvi_filename, mag);
+ if (dvi2pts == 0.0)
+ ERROR("dvi_init() failed!");
+
+ pdf_doc_set_creator(dvi_comment());
+
+ if (do_encryption)
+ /* command line takes precedence */
+ dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode,
+ &ver_minor, NULL, NULL, NULL, NULL, NULL);
+ else {
+ dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode,
+ &ver_minor, &do_encryption, &key_bits, &permission, owner_pw, user_pw);
+ if (do_encryption) {
+ if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7))
+ ERROR("Invalid encryption key length specified: %u", key_bits);
+ else if (key_bits > 40 && pdf_get_version() < 4)
+ ERROR("Chosen key length requires at least PDF 1.4. "
+ "Use \"-V 4\" to change.");
+ do_encryption = 1;
+ pdf_enc_set_passwd(key_bits, permission, owner_pw, user_pw);
+ }
+ }
+ if (ver_minor >= PDF_VERSION_MIN && ver_minor <= PDF_VERSION_MAX) {
+ pdf_set_version(ver_minor);
+ }
+ if (landscape_mode) {
+ SWAP(paper_width, paper_height);
+ }
+ }
+
+ MESG("%s -> %s\n", dvi_filename == NULL ? "stdin" : dvi_filename,
+ pdf_filename == NULL ? "stdout" : pdf_filename);
+
+ pdf_files_init();
+
+ /* 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.
+ */
+ pdf_open_document(pdf_filename, do_encryption,
+ paper_width, paper_height, annot_grow, bookmark_open);
+
+ /* Ignore_colors placed here since
+ * they are considered as device's capacity.
+ */
+ pdf_init_device(dvi2pts, pdfdecimaldigits, ignore_colors);
+
+ if (opt_flags & OPT_CIDFONT_FIXEDPITCH)
+ CIDFont_set_flags(CIDFONT_FORCE_FIXEDPITCH);
+
+ /* Please move this to spc_init_specials(). */
+ if (opt_flags & OPT_TPIC_TRANSPARENT_FILL)
+ tpic_set_fill_mode(1);
+
+ if (mp_mode) {
+ do_mps_pages();
+ } else {
+ do_dvi_pages();
+ }
+
+ pdf_files_close();
+
+ /* Order of close... */
+ pdf_close_device ();
+ /* pdf_close_document flushes XObject (image) and other resources. */
+ pdf_close_document();
+
+ pdf_close_fontmaps(); /* pdf_font may depend on fontmap. */
+
+ if (!mp_mode)
+ dvi_close();
+
+ MESG("\n");
+ cleanup();
+
+ paperdone();
+#ifdef MIKTEX
+ miktex_uninitialize ();
+#endif
+
+ return 0;
+}