summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdf-x/src/spc_dvips.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdf-x/src/spc_dvips.c')
-rw-r--r--Build/source/texk/dvipdf-x/src/spc_dvips.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdf-x/src/spc_dvips.c b/Build/source/texk/dvipdf-x/src/spc_dvips.c
new file mode 100644
index 00000000000..07ea009172e
--- /dev/null
+++ b/Build/source/texk/dvipdf-x/src/spc_dvips.c
@@ -0,0 +1,434 @@
+/*
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002-2012 by Jin-Hwan Cho 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.
+*/
+
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "system.h"
+#include "mem.h"
+#include "error.h"
+
+#include "dpxfile.h"
+
+#include "pdfparse.h"
+
+#include "pdfdoc.h"
+
+#include "mpost.h"
+
+#include "pdfximage.h"
+#include "pdfdraw.h"
+#include "pdfcolor.h"
+#include "pdfdev.h"
+
+#include "specials.h"
+#include "spc_util.h"
+
+#include "spc_dvips.h"
+
+
+static int block_pending = 0;
+static double pending_x = 0.0;
+static double pending_y = 0.0;
+static int position_set = 0;
+
+static char *
+parse_filename (const char **pp, const char *endptr)
+{
+ char *r;
+ const char *q = NULL, *p = *pp;
+ char qchar;
+ int n;
+
+ if (!p || p >= endptr)
+ return NULL;
+ else if (*p == '\"' || *p == '\'')
+ qchar = *p++;
+ else {
+ qchar = ' ';
+ }
+ for (n = 0, q = p; p < endptr && *p != qchar; n++, p++);
+ if (qchar != ' ') {
+ if (*p != qchar)
+ return NULL;
+ p++;
+ }
+ if (!q || n == 0)
+ return NULL;
+
+#if 0
+ {
+ int i;
+ for (i = 0; i < n && isprint(q[i]); i++);
+ if (i != n) {
+ WARN("Non printable char in filename string...");
+ }
+ }
+#endif
+
+ r = NEW(n + 1, char);
+ memcpy(r, q, n); r[n] = '\0';
+
+ *pp = p;
+ return r;
+}
+
+/* =filename ... */
+static int
+spc_handler_ps_file (struct spc_env *spe, struct spc_arg *args)
+{
+ int form_id;
+ char *filename;
+ transform_info ti;
+
+ ASSERT(spe && args);
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr + 1 >= args->endptr ||
+ args->curptr[0] != '=') {
+ spc_warn(spe, "No filename specified for PSfile special.");
+ return -1;
+ }
+ args->curptr++;
+
+ filename = parse_filename(&args->curptr, args->endptr);
+ if (!filename) {
+ spc_warn(spe, "No filename specified for PSfile special.");
+ return -1;
+ }
+
+ transform_info_clear(&ti);
+ if (spc_util_read_dimtrns(spe, &ti, args, NULL, 1) < 0) {
+ RELEASE(filename);
+ return -1;
+ }
+
+ form_id = pdf_ximage_findresource(filename, 1, NULL);
+ if (form_id < 0) {
+ spc_warn(spe, "Failed to read image file: %s", filename);
+ RELEASE(filename);
+ return -1;
+ }
+ RELEASE(filename);
+
+ pdf_dev_put_image(form_id, &ti, spe->x_user, spe->y_user);
+
+ return 0;
+}
+
+/* This isn't correct implementation but dvipdfm supports... */
+static int
+spc_handler_ps_plotfile (struct spc_env *spe, struct spc_arg *args)
+{
+ int error = 0;
+ int form_id;
+ char *filename;
+ transform_info p;
+
+ ASSERT(spe && args);
+
+ spc_warn(spe, "\"ps: plotfile\" found (not properly implemented)");
+
+ skip_white(&args->curptr, args->endptr);
+ filename = parse_filename(&args->curptr, args->endptr);
+ if (!filename) {
+ spc_warn(spe, "Expecting filename but not found...");
+ return -1;
+ }
+
+ form_id = pdf_ximage_findresource(filename, 1, NULL);
+ if (form_id < 0) {
+ spc_warn(spe, "Could not open PS file: %s", filename);
+ error = -1;
+ } else {
+ transform_info_clear(&p);
+ p.matrix.d = -1.0; /* xscale = 1.0, yscale = -1.0 */
+#if 0
+ /* I don't know how to treat this... */
+ pdf_dev_put_image(form_id, &p,
+ block_pending ? pending_x : spe->x_user,
+ block_pending ? pending_y : spe->y_user);
+#endif
+ pdf_dev_put_image(form_id, &p, 0, 0);
+ }
+ RELEASE(filename);
+
+ return error;
+}
+
+static int
+spc_handler_ps_literal (struct spc_env *spe, struct spc_arg *args)
+{
+ int error = 0;
+ int st_depth, gs_depth;
+ double x_user, y_user;
+
+ ASSERT(spe && args && args->curptr <= args->endptr);
+
+ if (args->curptr + strlen(":[begin]") <= args->endptr &&
+ !strncmp(args->curptr, ":[begin]", strlen(":[begin]"))) {
+ block_pending++;
+ position_set = 1;
+
+ x_user = pending_x = spe->x_user;
+ y_user = pending_y = spe->y_user;
+ args->curptr += strlen(":[begin]");
+ } else if (args->curptr + strlen(":[end]") <= args->endptr &&
+ !strncmp(args->curptr, ":[end]", strlen(":[end]"))) {
+ if (block_pending <= 0) {
+ spc_warn(spe, "No corresponding ::[begin] found.");
+ return -1;
+ }
+ block_pending--;
+
+ position_set = 0;
+
+ x_user = pending_x;
+ y_user = pending_y;
+ args->curptr += strlen(":[end]");
+ } else if (args->curptr < args->endptr &&
+ args->curptr[0] == ':') {
+ x_user = position_set ? pending_x : spe->x_user;
+ y_user = position_set ? pending_y : spe->y_user;
+ args->curptr++;
+ } else {
+ position_set = 1;
+ x_user = pending_x = spe->x_user;
+ y_user = pending_y = spe->y_user;
+ }
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr < args->endptr) {
+
+ st_depth = mps_stack_depth();
+ gs_depth = pdf_dev_current_depth();
+
+ error = mps_exec_inline(&args->curptr,
+ args->endptr,
+ x_user, y_user);
+ if (error) {
+ spc_warn(spe, "Interpreting PS code failed!!! Output might be broken!!!");
+ pdf_dev_grestore_to(gs_depth);
+ } else if (st_depth != mps_stack_depth()) {
+ spc_warn(spe, "Stack not empty after execution of inline PostScript code.");
+ spc_warn(spe, ">> Your macro package makes some assumption on internal behaviour of DVI drivers.");
+ spc_warn(spe, ">> It may not compatible with dvipdfmx.");
+ }
+ }
+
+ return error;
+}
+
+static int
+spc_handler_ps_default (struct spc_env *spe, struct spc_arg *args)
+{
+ int error;
+ int st_depth, gs_depth;
+
+ ASSERT(spe && args);
+
+ pdf_dev_gsave();
+
+ st_depth = mps_stack_depth();
+ gs_depth = pdf_dev_current_depth();
+
+ {
+ pdf_tmatrix M;
+ M.a = M.d = 1.0; M.b = M.c = 0.0; M.e = spe->x_user; M.f = spe->y_user;
+ pdf_dev_concat(&M);
+ error = mps_exec_inline(&args->curptr,
+ args->endptr,
+ spe->x_user, spe->y_user);
+ M.e = -spe->x_user; M.f = -spe->y_user;
+ pdf_dev_concat(&M);
+ }
+ if (error)
+ spc_warn(spe, "Interpreting PS code failed!!! Output might be broken!!!");
+ else {
+ if (st_depth != mps_stack_depth()) {
+ spc_warn(spe, "Stack not empty after execution of inline PostScript code.");
+ spc_warn(spe, ">> Your macro package makes some assumption on internal behaviour of DVI drivers.");
+ spc_warn(spe, ">> It may not compatible with dvipdfmx.");
+ }
+ }
+
+ pdf_dev_grestore_to(gs_depth);
+ pdf_dev_grestore();
+
+ return error;
+}
+
+static struct spc_handler dvips_handlers[] = {
+ {"PSfile", spc_handler_ps_file},
+ {"psfile", spc_handler_ps_file},
+ {"ps: plotfile ", spc_handler_ps_plotfile},
+ {"PS: plotfile ", spc_handler_ps_plotfile},
+ {"PS:", spc_handler_ps_literal},
+ {"ps:", spc_handler_ps_literal},
+ {"\" ", spc_handler_ps_default}
+};
+
+#ifdef XETEX
+int
+spc_dvips_at_begin_document (void)
+{
+ FILE* fp;
+
+ /* This, together with \pscharpath support code, must be moved to xtex.pro header. */
+ global_defs = dpx_create_temp_file();
+ if (!global_defs) {
+ WARN("Failed to create temporary input file for PSTricks image conversion.");
+ return -1;
+ }
+
+ fp = fopen(global_defs, "wb");
+ fprintf(fp, "tx@Dict begin /STV {} def end\n");
+ fclose(fp);
+ return 0;
+}
+
+int
+spc_dvips_at_end_document (void)
+{
+ if (ps_headers) {
+ while (num_ps_headers > 0)
+ RELEASE(ps_headers[--num_ps_headers]);
+ free(ps_headers);
+ ps_headers = NULL;
+ }
+ dpx_delete_temp_file(global_defs, true);
+ dpx_delete_temp_file(page_defs, true);
+ return 0;
+}
+
+int
+spc_dvips_at_begin_page (void)
+{
+ if (page_defs) {
+ dpx_delete_temp_file(page_defs, true);
+ page_defs = 0;
+ }
+
+ put_stack_depth = -1;
+
+ return 0;
+}
+#endif
+
+int
+spc_dvips_at_end_page (void)
+{
+ mps_eop_cleanup();
+#ifdef XETEX
+ if (!temporary_defs) {
+ dpx_delete_temp_file(temporary_defs, true);
+ temporary_defs = 0;
+ }
+#endif
+ return 0;
+}
+
+int
+spc_dvips_check_special (const char *buf, long len)
+{
+ const char *p, *endptr;
+ int i;
+
+ p = buf;
+ endptr = p + len;
+
+ skip_white(&p, endptr);
+ if (p >= endptr)
+ return 0;
+
+ len = (long) (endptr - p);
+ for (i = 0;
+ i < sizeof(dvips_handlers)/sizeof(struct spc_handler); i++) {
+ if (len >= strlen(dvips_handlers[i].key) &&
+ !memcmp(p, dvips_handlers[i].key,
+ strlen(dvips_handlers[i].key))) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+spc_dvips_setup_handler (struct spc_handler *handle,
+ struct spc_env *spe, struct spc_arg *args)
+{
+ const char *key;
+ int i, keylen;
+
+ ASSERT(handle && spe && args);
+
+ skip_white(&args->curptr, args->endptr);
+
+ key = args->curptr;
+ while (args->curptr < args->endptr &&
+ isalpha(args->curptr[0])) {
+ args->curptr++;
+ }
+ /* Test for "ps:". The "ps::" special is subsumed under this case. */
+ if (args->curptr < args->endptr &&
+ args->curptr[0] == ':') {
+ args->curptr++;
+ if (args->curptr+strlen(" plotfile ") <= args->endptr &&
+ !strncmp(args->curptr, " plotfile ", strlen(" plotfile "))) {
+ args->curptr += strlen(" plotfile ");
+ }
+ } else if (args->curptr+1 < args->endptr &&
+ args->curptr[0] == '"' && args->curptr[1] == ' ') {
+ args->curptr += 2;
+ }
+
+ keylen = (int) (args->curptr - key);
+ if (keylen < 1) {
+ spc_warn(spe, "Not ps: special???");
+ return -1;
+ }
+
+ for (i = 0;
+ i < sizeof(dvips_handlers) / sizeof(struct spc_handler); i++) {
+ if (keylen == strlen(dvips_handlers[i].key) &&
+ !strncmp(key, dvips_handlers[i].key, keylen)) {
+
+ skip_white(&args->curptr, args->endptr);
+
+ args->command = dvips_handlers[i].key;
+
+ handle->key = "ps:";
+ handle->exec = dvips_handlers[i].exec;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+