summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/spc_misc.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/dvipdfm-x/spc_misc.c
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/spc_misc.c')
-rw-r--r--Build/source/texk/dvipdfm-x/spc_misc.c680
1 files changed, 680 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdfm-x/spc_misc.c b/Build/source/texk/dvipdfm-x/spc_misc.c
new file mode 100644
index 00000000000..e974596cca6
--- /dev/null
+++ b/Build/source/texk/dvipdfm-x/spc_misc.c
@@ -0,0 +1,680 @@
+/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002-2021 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "system.h"
+#include "mem.h"
+#include "error.h"
+
+#include "mfileio.h"
+
+#include "dpxutil.h"
+
+#include "pdfparse.h"
+#include "pdfobj.h"
+
+#include "pdfcolor.h"
+#include "pdfdraw.h"
+#include "pdfximage.h"
+#include "pdfdev.h"
+
+#include "mpost.h"
+
+#include "specials.h"
+
+#include "spc_util.h"
+#include "spc_misc.h"
+
+/* pdfcolorstack:
+ * This special is provoded as a compatibility feature to pdftex.
+ */
+struct stack
+{
+ int page;
+ int direct;
+ dpx_stack stack;
+};
+
+#define PDFCOLORSTACK_MAX_STACK 256
+struct spc_stack
+{
+ struct stack stacks[PDFCOLORSTACK_MAX_STACK];
+};
+
+static struct spc_stack spc_stack;
+
+static int
+pdfcolorstack__get_id (struct spc_env *spe, int *id, struct spc_arg *args)
+{
+ char *q;
+
+ if (args->curptr >= args->endptr) {
+ spc_warn(spe, "Stack ID number expected but not found.");
+ return -1;
+ }
+ q = parse_number(&args->curptr, args->endptr);
+ if (!q) {
+ spc_warn(spe, "Stack ID number expected but not found.");
+ return -1;
+ }
+ *id = atoi(q);
+ RELEASE(q);
+
+ skip_white(&args->curptr, args->endptr);
+
+ return 0;
+}
+
+static int
+pdfcolorstack__init (void *dp)
+{
+ struct spc_stack *sd = dp;
+ int i;
+
+ for (i = 0; i < PDFCOLORSTACK_MAX_STACK; i++) {
+ sd->stacks[i].page = 0;
+ sd->stacks[i].direct = 0;
+ dpx_stack_init(&sd->stacks[i].stack);
+ }
+
+ return 0;
+}
+
+static int
+pdfcolorstack__clean (void *dp)
+{
+ struct spc_stack *sd = dp;
+ int i;
+
+ for (i = 0; i < PDFCOLORSTACK_MAX_STACK; i++) {
+ pdf_obj *litstr;
+ dpx_stack *stk = &sd->stacks[i].stack;
+
+ while ((litstr = dpx_stack_pop(stk)) != NULL) {
+ pdf_release_obj(litstr);
+ }
+ }
+
+ return 0;
+}
+
+static void
+pdfcolorstack__set_litstr (pdf_coord cp, pdf_obj *litstr, int direct)
+{
+ pdf_tmatrix M;
+
+ if (!litstr)
+ return;
+
+ if (!direct) {
+ M.a = M.d = 1.0; M.b = M.c = 0.0;
+ M.e = cp.x; M.f = cp.y;
+ pdf_dev_concat(&M);
+ }
+ pdf_doc_add_page_content(" ", 1);
+ pdf_doc_add_page_content(pdf_string_value(litstr), pdf_string_length(litstr));
+ if (!direct) {
+ M.e = -cp.x; M.f = -cp.y;
+ pdf_dev_concat(&M);
+ }
+}
+
+static int
+spc_handler_pdfcolorstackinit (struct spc_env *spe, struct spc_arg *args)
+{
+ int id = -1;
+ struct stack *st;
+ char *q;
+ pdf_coord cp = {0.0, 0.0};
+ pdf_obj *litstr;
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr >= args->endptr)
+ return -1;
+
+ if (pdfcolorstack__get_id(spe, &id, args) < 0)
+ return -1;
+ if (id < 0 || id >= PDFCOLORSTACK_MAX_STACK) {
+ spc_warn(spe, "Invalid stack number specified: %d", id);
+ return -1;
+ }
+ skip_white(&args->curptr, args->endptr);
+
+ st = &spc_stack.stacks[id];
+ if (dpx_stack_depth(&st->stack) > 0) {
+ spc_warn(spe, "Stadk ID=%d already initialized?", id);
+ return -1;
+ }
+
+ while ((q = parse_c_ident(&args->curptr, args->endptr)) != NULL) {
+ if (!strcmp(q, "page")) {
+ st->page = 1;
+ } else if (!strcmp(q, "direct")) {
+ st->direct = 1;
+ } else {
+ spc_warn(spe, "Ignoring unknown option for pdfcolorstack special (init): %s", q);
+ }
+ RELEASE(q);
+ skip_white(&args->curptr, args->endptr);
+ }
+
+ if (args->curptr < args->endptr) {
+ litstr = parse_pdf_string(&args->curptr, args->endptr);
+ if (litstr) {
+ dpx_stack_push(&st->stack, litstr);
+ pdfcolorstack__set_litstr(cp, litstr, st->direct);
+ }
+ skip_white(&args->curptr, args->endptr);
+ } else {
+ spc_warn(spe, "No valid PDF literal specified.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+pdfcolorstack__set (struct spc_env *spe, struct stack *st, pdf_coord cp, struct spc_arg *args)
+{
+ pdf_obj *litstr;
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr >= args->endptr)
+ return -1;
+
+ litstr = dpx_stack_pop(&st->stack);
+ if (!litstr) {
+ spc_warn(spe, "Stack empty!");
+ return -1;
+ }
+ pdf_release_obj(litstr);
+
+ litstr = parse_pdf_string(&args->curptr, args->endptr);
+ if (litstr) {
+ dpx_stack_push(&st->stack, litstr);
+ pdfcolorstack__set_litstr(cp, litstr, st->direct);
+ skip_white(&args->curptr, args->endptr);
+ }
+
+ return 0;
+}
+
+static int
+pdfcolorstack__push (struct spc_env *spe, struct stack *st, pdf_coord cp, struct spc_arg *args)
+{
+ pdf_obj *litstr;
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr >= args->endptr)
+ return -1;
+
+ litstr = parse_pdf_string(&args->curptr, args->endptr);
+ if (litstr) {
+ dpx_stack_push(&st->stack, litstr);
+ pdfcolorstack__set_litstr(cp, litstr, st->direct);
+ skip_white(&args->curptr, args->endptr);
+ }
+
+ return 0;
+}
+
+static int
+pdfcolorstack__current (struct spc_env *spe, struct stack *st, pdf_coord cp, struct spc_arg *args)
+{
+ pdf_obj *litstr;
+
+ litstr = dpx_stack_top(&st->stack);
+ if (litstr) {
+ pdfcolorstack__set_litstr(cp, litstr, st->direct);
+ skip_white(&args->curptr, args->endptr);
+ } else {
+ spc_warn(spe, "Stack empty!");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+pdfcolorstack__pop (struct spc_env *spe, struct stack *st, pdf_coord cp, struct spc_arg *args)
+{
+ int error = 0;
+ pdf_obj *litstr;
+
+ /* "default" at the bottom */
+ if (dpx_stack_depth(&st->stack) < 2) {
+ spc_warn(spe, "Stack underflow");
+ return -1;
+ }
+ litstr = dpx_stack_pop(&st->stack);
+ if (litstr) {
+ pdf_release_obj(litstr);
+ }
+ litstr = dpx_stack_top(&st->stack);
+ if (litstr) {
+ pdfcolorstack__set_litstr(cp, litstr, st->direct);
+ }
+
+ return error;
+}
+
+static int
+spc_handler_pdfcolorstack (struct spc_env *spe, struct spc_arg *args)
+{
+ int error = 0;
+ int id;
+ char *command;
+ struct stack *st;
+ pdf_coord cp;
+
+ skip_white(&args->curptr, args->endptr);
+ if (args->curptr >= args->endptr)
+ return -1;
+
+ if (pdfcolorstack__get_id(spe, &id, args) < 0)
+ return -1;
+ if (id < 0 || id >= PDFCOLORSTACK_MAX_STACK) {
+ spc_warn(spe, "Invalid stack ID specified: %d", id);
+ return -1;
+ }
+ skip_white(&args->curptr, args->endptr);
+
+ st = &spc_stack.stacks[id];
+ if (dpx_stack_depth(&st->stack) < 1) {
+ spc_warn(spe, "Stack ID=%d not properly initialized?", id);
+ return -1;
+ }
+
+ command = parse_c_ident(&args->curptr, args->endptr);
+ if (!command)
+ return -1;
+
+ spc_get_current_point(spe, &cp);
+ if (!strcmp(command, "set")) {
+ error = pdfcolorstack__set(spe, st, cp, args);
+ } else if (!strcmp(command, "push")) {
+ error = pdfcolorstack__push(spe, st, cp, args);
+ } else if (!strcmp(command, "pop")) {
+ error = pdfcolorstack__pop(spe, st, cp, args);
+ } else if (!strcmp(command, "current")) {
+ error = pdfcolorstack__current(spe, st, cp, args);
+ } else {
+ spc_warn(spe, "Unknown action: %s", command);
+ }
+
+ if (error) {
+ spc_warn(spe, "Error occurred while processing pdfcolorstack: id=%d command=\"%s\"", id, command);
+ }
+
+ RELEASE(command);
+
+ return error;
+}
+
+/* Duplicate from spc_pdfm */
+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;
+}
+
+/* pdffontattr */
+#include "pdffont.h"
+
+struct fontattr {
+ char *ident;
+ double size;
+ pdf_obj *attr;
+};
+
+struct fontattr *fontattrs = NULL;
+int num_fontattrs = 0;
+int max_fontattrs = 0;
+
+static int
+process_fontattr (const char *ident, double size, pdf_obj *attr)
+{
+ int font_id;
+ pdf_obj *fontdict;
+
+ ASSERT(ident && attr);
+
+ font_id = pdf_font_findresource(ident, size);
+ if (font_id < 0) {
+ WARN("Could not find specified font resource: %s (%gpt)", ident, size);
+ return -1;
+ }
+
+ fontdict = pdf_get_font_resource(font_id);
+ if (!fontdict) {
+ WARN("Specified object not exist: %s (%gpt)", ident, size);
+ return -1;
+ }
+
+ pdf_merge_dict(fontdict, attr);
+
+ return 0;
+}
+
+static int
+spc_handler_pdffontattr (struct spc_env *spe, struct spc_arg *ap)
+{
+ struct fontattr *fontattr;
+ char *ident = NULL;
+ double size = 0.0;
+ pdf_obj *attr = NULL;
+
+ skip_white(&ap->curptr, ap->endptr);
+ if (ap->curptr >= ap->endptr)
+ return -1;
+
+ ident = parse_ident(&ap->curptr, ap->endptr);
+ if (!ident) {
+ spc_warn(spe, "Missing a font name.");
+ return -1;
+ }
+ skip_white(&ap->curptr, ap->endptr);
+
+ if (ap->curptr < ap->endptr && ap->curptr[0] != '<') {
+ int error = dpx_util_read_length(&size, 1.0, &ap->curptr, ap->endptr);
+ if (error) {
+ spc_warn(spe, "Font size expected but not found.");
+ RELEASE(ident);
+ return -1;
+ }
+ skip_white(&ap->curptr, ap->endptr);
+ }
+
+ attr = parse_pdf_object_extended(&ap->curptr, ap->endptr, NULL, parse_pdf_reference, spe);
+ if (!attr) {
+ spc_warn(spe, "Failed to parse a PDF dictionary object: %s", ident);
+ RELEASE(ident);
+ return -1;
+ } else if (!PDF_OBJ_DICTTYPE(attr)) {
+ spc_warn(spe, "PDF dict expected but non-dict object found: %s", ident);
+ RELEASE(ident);
+ pdf_release_obj(attr);
+ return -1;
+ }
+ skip_white(&ap->curptr, ap->endptr);
+
+ if (num_fontattrs >= max_fontattrs) {
+ fontattrs = RENEW(fontattrs, max_fontattrs + 256, struct fontattr);
+ max_fontattrs += 256;
+ }
+ fontattr = &fontattrs[num_fontattrs];
+ num_fontattrs += 1;
+
+ fontattr->ident = ident;
+ fontattr->size = size;
+ fontattr->attr = attr;
+
+ return 0;
+}
+
+int
+spc_misc_at_begin_document (void)
+{
+ struct spc_stack *sd = &spc_stack;
+
+ if (!fontattrs) {
+ fontattrs = NEW(256, struct fontattr);
+ num_fontattrs = 0;
+ max_fontattrs = 256;
+ }
+
+ return pdfcolorstack__init(sd);
+}
+
+int
+spc_misc_at_end_document (void)
+{
+ struct spc_stack *sd = &spc_stack;
+
+ if (fontattrs) {
+ int i;
+
+ for (i = 0; i < num_fontattrs; i++) {
+ process_fontattr(fontattrs[i].ident, fontattrs[i].size, fontattrs[i].attr);
+ RELEASE(fontattrs[i].ident);
+ pdf_release_obj(fontattrs[i].attr);
+ }
+ RELEASE(fontattrs);
+ fontattrs = NULL;
+ max_fontattrs = num_fontattrs = 0;
+ }
+
+ return pdfcolorstack__clean(sd);
+}
+
+int
+spc_misc_at_begin_page (void)
+{
+ struct spc_stack *sd = &spc_stack;
+ int i;
+
+ for (i = 0; i < PDFCOLORSTACK_MAX_STACK; i++) {
+ dpx_stack *stk = &sd->stacks[i].stack;
+
+ if (sd->stacks[i].page) {
+ pdf_obj *litstr = dpx_stack_top(stk);
+ pdf_coord cp = {0.0, 0.0};
+
+ if (litstr)
+ pdfcolorstack__set_litstr(cp, litstr, sd->stacks[i].direct);
+ }
+ }
+
+ return 0;
+}
+
+int
+spc_misc_at_begin_form (void)
+{
+ return spc_misc_at_begin_page();
+}
+
+int
+spc_misc_at_end_form (void)
+{
+ return spc_misc_at_begin_page();
+}
+
+static int
+spc_handler_postscriptbox (struct spc_env *spe, struct spc_arg *ap)
+{
+ int form_id, len;
+ transform_info ti;
+ load_options options = {1, 0, NULL};
+ char filename[256], *fullname;
+ char buf[512];
+ FILE *fp;
+
+ ASSERT(spe && ap);
+
+ if (ap->curptr >= ap->endptr) {
+ spc_warn(spe, "No width/height/filename given for postscriptbox special.");
+ return -1;
+ }
+
+ /* input is not NULL terminated */
+ len = (int) (ap->endptr - ap->curptr);
+ len = MIN(511, len);
+ memcpy(buf, ap->curptr, len);
+ buf[len] = '\0';
+
+ transform_info_clear(&ti);
+
+ spc_warn(spe, buf);
+ if (sscanf(buf, "{%lfpt}{%lfpt}{%255[^}]}",
+ &ti.width, &ti.height, filename) != 3) {
+ spc_warn(spe, "Syntax error in postscriptbox special?");
+ return -1;
+ }
+ ap->curptr = ap->endptr;
+
+ ti.width *= 72.0 / 72.27;
+ ti.height *= 72.0 / 72.27;
+
+ fullname = kpse_find_pict(filename);
+ if (!fullname) {
+ spc_warn(spe, "Image file \"%s\" not found.", filename);
+ return -1;
+ }
+
+ fp = MFOPEN(fullname, FOPEN_R_MODE);
+ if (!fp) {
+ spc_warn(spe, "Could not open image file: %s", fullname);
+ RELEASE(fullname);
+ return -1;
+ }
+ RELEASE(fullname);
+
+ ti.flags |= (INFO_HAS_WIDTH|INFO_HAS_HEIGHT);
+
+ for (;;) {
+ const char *p = mfgets(buf, 512, fp);
+ if (!p)
+ break;
+ if (mps_scan_bbox(&p, p + strlen(p), &ti.bbox) >= 0) {
+ ti.flags |= INFO_HAS_USER_BBOX;
+ break;
+ }
+ }
+ MFCLOSE(fp);
+
+ form_id = pdf_ximage_load_image(NULL, filename, options);
+ if (form_id < 0) {
+ spc_warn(spe, "Failed to load image file: %s", filename);
+ return -1;
+ }
+
+ spc_put_image(spe, form_id, &ti, spe->x_user, spe->y_user);
+
+ return 0;
+}
+
+static int
+spc_handler_null (struct spc_env *spe, struct spc_arg *args)
+{
+ args->curptr = args->endptr;
+
+ return 0;
+}
+
+static struct spc_handler misc_handlers[] = {
+ {"postscriptbox", spc_handler_postscriptbox},
+ {"pdfcolorstackinit", spc_handler_pdfcolorstackinit},
+ {"pdfcolorstack", spc_handler_pdfcolorstack},
+ {"pdffontattr", spc_handler_pdffontattr},
+ {"landscape", spc_handler_null}, /* handled at bop */
+ {"papersize", spc_handler_null}, /* handled at bop */
+ {"src:", spc_handler_null}, /* simply ignore */
+ {"pos:", spc_handler_null}, /* simply ignore */
+ {"om:", spc_handler_null} /* simply ignore */
+};
+
+
+int
+spc_misc_check_special (const char *buffer, int size)
+{
+ const char *p, *endptr;
+ int i;
+
+ p = buffer;
+ endptr = p + size;
+
+ skip_white(&p, endptr);
+ size = (int) (endptr - p);
+ for (i = 0; i < sizeof(misc_handlers)/sizeof(struct spc_handler); i++) {
+ if (size >= strlen(misc_handlers[i].key) &&
+ !strncmp(p, misc_handlers[i].key, strlen(misc_handlers[i].key))) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+spc_misc_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((unsigned char)args->curptr[0])) {
+ args->curptr++;
+ }
+
+ if (args->curptr < args->endptr &&
+ args->curptr[0] == ':') {
+ args->curptr++;
+ }
+
+ keylen = (int) (args->curptr - key);
+ if (keylen < 1) {
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(misc_handlers)/sizeof(struct spc_handler); i++) {
+ if (keylen == strlen(misc_handlers[i].key) &&
+ !strncmp(key, misc_handlers[i].key, keylen)) {
+
+ skip_white(&args->curptr, args->endptr);
+
+ args->command = misc_handlers[i].key;
+
+ handle->key = "???:";
+ handle->exec = misc_handlers[i].exec;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}