diff options
Diffstat (limited to 'Build/source/texk/dvipdf-x/spc_xtx.c')
-rw-r--r-- | Build/source/texk/dvipdf-x/spc_xtx.c | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdf-x/spc_xtx.c b/Build/source/texk/dvipdf-x/spc_xtx.c new file mode 100644 index 00000000000..a039c36371c --- /dev/null +++ b/Build/source/texk/dvipdf-x/spc_xtx.c @@ -0,0 +1,457 @@ +/* + This is xdvipdfmx, an extended version of dvipdfmx, + an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (c) 2006 SIL International + Written by Jonathan Kew + + This file based on spc_pdfm.c, part of the dvipdfmx project: + + Copyright (C) 2002 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. +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ctype.h> +#include <math.h> + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" + +#include "numbers.h" + +#include "fontmap.h" +#include "dpxutil.h" + +#include "pdfobj.h" +#include "pdfparse.h" + +#include "pdfdoc.h" + +#include "pdfdraw.h" +#include "pdfcolor.h" +#include "pdfdev.h" + +#include "specials.h" + +#include "spc_util.h" +#include "spc_xtx.h" + + +int +spc_handler_xtx_do_transform (double x_user, double y_user, double a, double b, double c, double d, double e, double f) +{ + pdf_tmatrix M = { 0, 0, 0, 0, 0, 0 }; + pdf_coord pt; + + /* Create transformation matrix */ + M.a = a; + M.b = b; + M.c = c; + M.d = d; + M.e = ((1.0 - M.a) * x_user - M.c * y_user) + e; + M.f = ((1.0 - M.d) * y_user - M.b * x_user) + f; + + pdf_dev_concat(&M); + pdf_dev_get_fixed_point(&pt); + pdf_dev_set_fixed_point(x_user - pt.x, y_user - pt.y); + + return 0; +} + +static int +spc_handler_xtx_scale (struct spc_env *spe, struct spc_arg *args) +{ + double values[2]; + + if (spc_util_read_numbers(&values[0], 2, spe, args) < 2) { + return -1; + } + args->curptr = args->endptr; + + return spc_handler_xtx_do_transform(spe->x_user, spe->y_user, values[0], 0, 0, values[1], 0, 0); +} + +/* Scaling without gsave/grestore. */ +static pdf_coord *scaleFactors = 0; +static int scaleFactorCount = -1; + +static int +spc_handler_xtx_bscale (struct spc_env *spe, struct spc_arg *args) +{ + double values[2]; + + if (!(++scaleFactorCount & 0x0f)) + scaleFactors = realloc(scaleFactors, (scaleFactorCount + 16) * sizeof(pdf_coord)); + if (spc_util_read_numbers(&values[0], 2, spe, args) < 2) { + return -1; + } + if (fabs(values[0]) < 1.e-7 || fabs(values[1]) < 1.e-7) { + return -1; + } + scaleFactors[scaleFactorCount].x = 1 / values[0]; + scaleFactors[scaleFactorCount].y = 1 / values[1]; + args->curptr = args->endptr; + + return spc_handler_xtx_do_transform (spe->x_user, spe->y_user, values[0], 0, 0, values[1], 0, 0); +} + +static int +spc_handler_xtx_escale (struct spc_env *spe, struct spc_arg *args) +{ + pdf_coord factor = scaleFactors[scaleFactorCount--]; + + args->curptr = args->endptr; + + return spc_handler_xtx_do_transform (spe->x_user, spe->y_user, factor.x, 0, 0, factor.y, 0, 0); +} + +static int +spc_handler_xtx_rotate (struct spc_env *spe, struct spc_arg *args) +{ + double value; + + if (spc_util_read_numbers(&value, 1, spe, args) < 1) { + return -1; + } + args->curptr = args->endptr; + + return spc_handler_xtx_do_transform (spe->x_user, spe->y_user, + cos(value * M_PI / 180), sin(value * M_PI / 180), + -sin(value * M_PI / 180), cos(value * M_PI / 180), + 0, 0); +} + +int +spc_handler_xtx_gsave (struct spc_env *spe, struct spc_arg *args) +{ + pdf_dev_gsave(); + + return 0; +} + +int +spc_handler_xtx_grestore (struct spc_env *spe, struct spc_arg *args) +{ + pdf_dev_grestore(); + + /* + * Unfortunately, the following line is necessary in case + * of a font or color change inside of the save/restore pair. + * Anything that was done there must be redone, so in effect, + * we make no assumptions about what fonts. We act like we are + * starting a new page. + */ + pdf_dev_reset_fonts(); + pdf_dev_reset_color(); + + return 0; +} + +/* Please remove this. + * This should be handled before processing pages! + */ +static int +spc_handler_xtx_papersize (struct spc_env *spe, struct spc_arg *args) +{ + return 0; +} + +static int +spc_handler_xtx_backgroundcolor (struct spc_env *spe, struct spc_arg *args) +{ + int error; + pdf_color colorspec; + + error = spc_util_read_colorspec(spe, &colorspec, args, 0); + if (error) + spc_warn(spe, "No valid color specified?"); + else { + pdf_doc_set_bgcolor(&colorspec); + } + + return error; +} + +/* FIXME: xdv2pdf's x:fontmapline and x:fontmapfile may have slightly different syntax/semantics */ +static int +spc_handler_xtx_fontmapline (struct spc_env *spe, struct spc_arg *ap) +{ + fontmap_rec *mrec; + char *map_name, opchr; + int error = 0; + + skip_white(&ap->curptr, ap->endptr); + if (ap->curptr >= ap->endptr) { + spc_warn(spe, "Empty fontmapline special?"); + return -1; + } + + opchr = ap->curptr[0]; + if (opchr == '-' || opchr == '+') + ap->curptr++; + + skip_white(&ap->curptr, ap->endptr); + + switch (opchr) { + case '-': + map_name = parse_ident(&ap->curptr, ap->endptr); + if (map_name) { + pdf_remove_fontmap_record(map_name); + RELEASE(map_name); + } else { + spc_warn(spe, "Invalid fontmap line: Missing TFM name."); + error = -1; + } + break; + case '+': + mrec = NEW(1, fontmap_rec); + pdf_init_fontmap_record(mrec); + error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), + is_pdfm_mapline(ap->curptr)); + if (error) + spc_warn(spe, "Invalid fontmap line."); + else { + pdf_append_fontmap_record(mrec->map_name, mrec); + } + pdf_clear_fontmap_record(mrec); + RELEASE(mrec); + break; + default: + mrec = NEW(1, fontmap_rec); + pdf_init_fontmap_record(mrec); + error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), + is_pdfm_mapline(ap->curptr)); + if (error) + spc_warn(spe, "Invalid fontmap line."); + else { + pdf_insert_fontmap_record(mrec->map_name, mrec); + } + pdf_clear_fontmap_record(mrec); + RELEASE(mrec); + break; + } + if (!error) + ap->curptr = ap->endptr; + + return 0; +} + +static int +spc_handler_xtx_fontmapfile (struct spc_env *spe, struct spc_arg *args) +{ + char *mapfile; + int mode, error = 0; + + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return 0; + + switch (args->curptr[0]) { + case '-': + mode = FONTMAP_RMODE_REMOVE; + args->curptr++; + break; + case '+': + mode = FONTMAP_RMODE_APPEND; + args->curptr++; + break; + default: + mode = FONTMAP_RMODE_REPLACE; + break; + } + + mapfile = parse_val_ident(&args->curptr, args->endptr); + if (!mapfile) { + spc_warn(spe, "No fontmap file specified."); + return -1; + } else { + error = pdf_load_fontmap_file(mapfile, mode); + } + + return error; +} + +static char overlay_name[256]; + +static int +spc_handler_xtx_initoverlay (struct spc_env *spe, struct spc_arg *args) +{ + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return -1; + strncpy(overlay_name, args->curptr, args->endptr - args->curptr); + overlay_name[args->endptr - args->curptr] = 0; + + args->curptr = args->endptr; + return 0; +} + +static int +spc_handler_xtx_clipoverlay (struct spc_env *spe, struct spc_arg *args) +{ + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return -1; + pdf_dev_grestore(); + pdf_dev_gsave(); + if (strncmp(overlay_name, args->curptr, strlen(overlay_name)) != 0 + && strncmp("all", args->curptr, strlen("all")) != 0) + pdf_doc_add_page_content(" 0 0 m W n", 10); + + args->curptr = args->endptr; + return 0; +} + +static int +spc_handler_xtx_renderingmode (struct spc_env *spe, struct spc_arg *args) +{ + double value; + + if (spc_util_read_numbers(&value, 1, spe, args) < 1) { + return -1; + } + if ((int) value < 0 || (int) value > 7) { + spc_warn(spe, "Invalid text rendering mode %d.\n", (int) value); + return -1; + } + sprintf(work_buffer, " %d Tr", (int) value); + pdf_doc_add_page_content(work_buffer, strlen(work_buffer)); + skip_white(&args->curptr, args->endptr); + if (args->curptr < args->endptr) { + pdf_doc_add_page_content(" ", 1); + pdf_doc_add_page_content(args->curptr, args->endptr - args->curptr); + } + + args->curptr = args->endptr; + return 0; +} + +static int +spc_handler_xtx_unsupportedcolor (struct spc_env *spe, struct spc_arg *args) +{ + spc_warn(spe, "xetex-style \\special{x:%s} is not supported by this driver;\n" + "update document or driver to use \\special{color} instead.", args->command); + + args->curptr = args->endptr; + + return 0; +} + +static int +spc_handler_xtx_unsupported (struct spc_env *spe, struct spc_arg *args) +{ + spc_warn(spe, "xetex-style \\special{x:%s} is not supported by this driver.", args->command); + + args->curptr = args->endptr; + + return 0; +} + +static struct spc_handler xtx_handlers[] = { + {"textcolor", spc_handler_xtx_unsupportedcolor}, + {"textcolorpush", spc_handler_xtx_unsupportedcolor}, + {"textcolorpop", spc_handler_xtx_unsupportedcolor}, + + {"rulecolor", spc_handler_xtx_unsupportedcolor}, + {"rulecolorpush", spc_handler_xtx_unsupportedcolor}, + {"rulecolorpop", spc_handler_xtx_unsupportedcolor}, + + {"papersize", spc_handler_xtx_papersize}, + {"backgroundcolor", spc_handler_xtx_backgroundcolor}, + + {"gsave", spc_handler_xtx_gsave}, + {"grestore", spc_handler_xtx_grestore}, + + {"scale", spc_handler_xtx_scale}, + {"bscale", spc_handler_xtx_bscale}, + {"escale", spc_handler_xtx_escale}, + {"rotate", spc_handler_xtx_rotate}, + + {"fontmapline", spc_handler_xtx_fontmapline}, + {"fontmapfile", spc_handler_xtx_fontmapfile}, + + {"shadow", spc_handler_xtx_unsupported}, + {"colorshadow", spc_handler_xtx_unsupported}, + {"renderingmode", spc_handler_xtx_renderingmode}, + + {"initoverlay", spc_handler_xtx_initoverlay}, + {"clipoverlay", spc_handler_xtx_clipoverlay}, +}; + +int +spc_xtx_check_special (const char *buf, long len) +{ + int r = 0; + const char *p, *endptr; + + p = buf; + endptr = p + len; + + skip_white(&p, endptr); + if (p + strlen("x:") <= endptr && + !memcmp(p, "x:", strlen("x:"))) { + r = 1; + } + + return r; +} + +int +spc_xtx_setup_handler (struct spc_handler *sph, + struct spc_env *spe, struct spc_arg *ap) +{ + int error = -1, i; + char *q; + + ASSERT(sph && spe && ap); + + skip_white(&ap->curptr, ap->endptr); + if (ap->curptr + strlen("x:") >= ap->endptr || + memcmp(ap->curptr, "x:", strlen("x:"))) { + spc_warn(spe, "Not x: special???"); + return -1; + } + ap->curptr += strlen("x:"); + + skip_white(&ap->curptr, ap->endptr); + q = parse_c_ident(&ap->curptr, ap->endptr); + if (q) { + for (i = 0; + i < sizeof(xtx_handlers) / sizeof(struct spc_handler); i++) { + if (!strcmp(q, xtx_handlers[i].key)) { + ap->command = xtx_handlers[i].key; + sph->key = "x:"; + sph->exec = xtx_handlers[i].exec; + skip_white(&ap->curptr, ap->endptr); + error = 0; + break; + } + } + RELEASE(q); + } + + return error; +} + |