diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/dvipdfm-x/spc_misc.c | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (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.c | 680 |
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; +} |