summaryrefslogtreecommitdiff
path: root/dviware/dvitops/special.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvitops/special.c
Initial commit
Diffstat (limited to 'dviware/dvitops/special.c')
-rw-r--r--dviware/dvitops/special.c1050
1 files changed, 1050 insertions, 0 deletions
diff --git a/dviware/dvitops/special.c b/dviware/dvitops/special.c
new file mode 100644
index 0000000000..bad23d8882
--- /dev/null
+++ b/dviware/dvitops/special.c
@@ -0,0 +1,1050 @@
+static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/special.c,v 1.9 90/08/14 13:56:04 jjc Rel $";
+
+#include "dvitops.h"
+
+struct bounding_box { double llx, lly, urx, ury; };
+
+#ifdef PROTO
+static void do_import(char *arg, integer x, integer y,
+ int region, struct page_info *page, FILE *psfp);
+int strprefix(char *prefix, char *s);
+static void read_import_file(char *filename);
+#else
+static void do_import();
+int strprefix();
+static void read_import_file();
+#endif
+
+/* this holds the list of files to be imported on the current page */
+static struct import {
+ integer x, y;
+ int region;
+ struct import *next;
+ char arg[1];
+} *import_list;
+
+
+static struct import_file {
+ struct bounding_box bb;
+ struct depend_list *font;
+ struct import_file *next;
+ char file[1];
+} *doc_import_list;
+
+/* this routine is used to include a PostScript file
+it will be enhanced later to be quicker and possibly to support
+%%IncludeFont and %%IncludeFile comments
+return 0 on success, -1 on error
+*/
+
+int include_file(filename, psfp)
+char *filename;
+FILE *psfp;
+{
+ char buf[256];
+ FILE *infp;
+ if ((infp = xfopen(filename, FALSE, texinputs, (char *)NULL)) == NULL)
+ return EOF;
+#ifdef HAVE_SETVBUF
+ setvbuf(infp, (char *)NULL, _IOFBF, 16384);
+#endif
+ while (fgets(buf, sizeof(buf), infp) != NULL)
+ if (buf[0] != '%')
+ fputs(buf, psfp);
+ fclose(infp);
+ return 0;
+}
+
+/* return 0 on error */
+
+int bigpoint(str, ptr, val)
+char *str, **ptr;
+double *val;
+{
+ double x;
+ int n;
+ while (isspace(*str))
+ ++str;
+ if (sscanf(str, "%lf", &x) != 1)
+ goto bad;
+ while (isdigit(*str) || *str == '.')
+ str++;
+ while (isspace(*str))
+ str++;
+ n = isupper(str[0]) ? tolower(str[0]) : str[0];
+ n <<= 8;
+ n |= isupper(str[1]) ? tolower(str[1]) : str[1];
+ switch (n) {
+ case ('b' << 8) + 'p' :
+ break;
+ case ('i' << 8) + 'n' :
+ x *= 72.0;
+ break;
+ case ('c' << 8) + 'm' :
+ x *= 72.0/2.54;
+ break;
+ case ('m' << 8) + 'm' :
+ x *= 72.0/25.4;
+ break;
+ case ('s' << 8) + 'p' :
+ x *= 72.0/(72.27*65536.0);
+ break;
+ case ('c' << 8) + 'c' :
+ x *= 12.0*1238.0*72.0/(1157.0*72.27);
+ break;
+ case ('d' << 8) + 'd' :
+ x *= 1238.0*72.0/(1157.0*72.27);
+ break;
+ case ('p' << 8) + 't' :
+ x *= 72.0/72.27;
+ break;
+ case ('p' << 8) + 'c' :
+ x *= 12.0*72.0/72.27;
+ break;
+ default:
+ goto bad;
+ }
+ str += 2;
+ if (ptr != NULL)
+ *ptr = str;
+ *val = x;
+ return 1;
+bad:
+ if (ptr != NULL)
+ *ptr = str;
+ return 0;
+}
+
+static void do_import(arg, x, y, region, page, psfp)
+char *arg;
+integer x, y;
+int region;
+struct page_info *page;
+FILE *psfp;
+{
+ double xscale, yscale;
+ integer gap;
+ double h, w;
+ integer width, height;
+ char *filename;
+ struct import_file *p;
+ struct depend_list *q;
+ struct bounding_box bb;
+ integer llx, lly, urx, ury;
+ double sf = (double)page->den*254000.0/((double)page->num*72.0);
+ char *ptr = arg;
+ typedef enum { CENTER, LEFT, RIGHT, TOP, BOTTOM, FILL } adjust_t;
+ adjust_t hadj = CENTER, vadj = CENTER;
+ while (isspace(*ptr))
+ ptr++;
+ filename = ptr;
+ while (!isspace(*ptr) && *ptr != '\0')
+ ptr++;
+ if (*ptr == '\0') {
+ message(ERROR, "import \\special syntax error: abandoning import");
+ return;
+ }
+ *ptr++ = '\0';
+ if (bigpoint(ptr, &ptr, &w) == 0
+ || bigpoint(ptr, &ptr, &h) == 0) {
+ message(ERROR, "special import syntax error: abandoning import");
+ return;
+ }
+ ptr = strtok(ptr, "\r\n\t ");
+ while (ptr != NULL) {
+ int i;
+ for (i = 0; ptr[i] != '\0'; i++)
+ ptr[i] = isupper(ptr[i]) ? tolower(ptr[i]) : ptr[i];
+ if (strcmp(ptr, "top") == 0)
+ vadj = TOP;
+ else if (strcmp(ptr, "bottom") == 0)
+ vadj = BOTTOM;
+ else if (strcmp(ptr, "fill") == 0)
+ hadj = vadj = FILL;
+ else if (strcmp(ptr, "left") == 0)
+ hadj = LEFT;
+ else if (strcmp(ptr, "right") == 0)
+ hadj = RIGHT;
+ else
+ message(ERROR, "bad option in import \\special: %s: ignored",ptr);
+ ptr = strtok((char *)NULL, " \r\n\t");
+ }
+ /* convert to dvi units */
+ width = (integer)(w*sf);
+ height = (integer)(h*sf);
+ for (p = doc_import_list; p != NULL; p = p->next)
+ if (strcmp(p->file, filename) == 0)
+ break;
+ if (p == NULL) {
+ message(ERROR, "can't import %s", filename);
+ return;
+ }
+ fputs("BO /showpage {} def\n", psfp);
+ for (q = p->font; q != NULL; q = q->next)
+ if (!q->f->in_prolog)
+ emit_ps_font(q->f->s, psfp);
+ if (region != NO_REGION) {
+ integer ox = 0, oy = 0;
+ do_transform(region, &ox, &oy, psfp);
+ x -= ox;
+ y -= oy;
+ }
+ bb = p->bb;
+ if (bb.urx == bb.llx) {
+ message(ERROR, "bad bounding box: no width");
+ return;
+ }
+ if (bb.ury == bb.lly) {
+ message(ERROR, "bad bounding box: no height");
+ return;
+ }
+ xscale = width/(bb.urx - bb.llx);
+ yscale = height/(bb.ury - bb.lly);
+ if (xscale > yscale) {
+ lly = y;
+ ury = y - height;
+ gap = (integer)(width - yscale*(bb.urx - bb.llx));
+ switch(hadj) {
+ case CENTER :
+ llx = x + gap/2;
+ urx = x + width - gap/2;
+ break;
+ case LEFT :
+ llx = x;
+ urx = x + width - gap;
+ break;
+ case RIGHT :
+ llx = x + gap;
+ urx = x + width;
+ break;
+ case FILL :
+ llx = x;
+ urx = x + width;
+ break;
+ default :
+ cant_happen();
+ }
+ }
+ else {
+ llx = x;
+ urx = x + width;
+ gap = (integer)(height - xscale*(bb.ury - bb.lly));
+ switch(vadj) {
+ case CENTER :
+ lly = y - gap/2;
+ ury = y - height + gap/2;
+ break;
+ case TOP :
+ lly = y - gap;
+ ury = y - height;
+ break;
+ case BOTTOM :
+ lly = y;
+ ury = y - height + gap;
+ break;
+ case FILL :
+ lly = y;
+ ury = y - height;
+ break;
+ default :
+ cant_happen();
+ }
+ }
+ fprintf(psfp, "%lg %lg %lg %lg ", bb.llx, bb.lly, bb.urx, bb.ury);
+
+ put_dim((long)llx, psfp);
+ putc(' ', psfp);
+ put_dim((long)lly, psfp);
+ putc(' ', psfp);
+ put_dim((long)urx, psfp);
+ putc(' ', psfp);
+ put_dim((long)ury, psfp);
+ fputs(" Locate\n", psfp);
+ fprintf(psfp, "%%%%BeginDocument: %s\n", filename);
+ if (include_file(filename, psfp) == EOF)
+ message(ERROR, "can't find import file %s: abandoning import",
+ filename);
+ fputs("\n%%EndDocument\nEO\n", psfp);
+}
+
+/* this is called at the end of each page by eop to deal with
+any import specials on the current page; it calls do_import to do
+the real work */
+
+void p_import_list(psfp, page)
+FILE *psfp;
+struct page_info *page;
+{
+ if (import_list == NULL)
+ return;
+ while (import_list != NULL) {
+ struct import *q = import_list;
+ do_import(import_list->arg, import_list->x, import_list->y,
+ import_list->region, page, psfp);
+ import_list = import_list->next;
+ free((char *)q);
+ }
+}
+
+
+
+/* this holds a list of all the pieces of inline code for the current page */
+
+static struct inline_code {
+ int region;
+ integer h, v;
+ struct inline_code *next;
+ char s[1];
+} *inline_list = NULL;
+
+/* this is called by eop at the end of every page to emit any inline
+specials */
+
+void p_inline_list(psfp)
+FILE *psfp;
+{
+ struct inline_code *p = NULL;
+ integer ox = 0, oy = 0;
+ int r = NO_REGION;
+ /* reverse the list */
+ if (inline_list == NULL)
+ return;
+ fputs("BO\n", psfp);
+ while (inline_list != NULL) {
+ struct inline_code *q = inline_list;
+ inline_list = inline_list->next;
+ q->next = p;
+ p = q;
+ }
+ while (p != NULL) {
+ struct inline_code *q = p;
+ if (p->region != r) {
+ fprintf(psfp, "%% region %d\n", p->region);
+ if (r != NO_REGION)
+ fputs("grestore\n", psfp);
+ if (p->region != NO_REGION) {
+ fputs("gsave\n", psfp);
+ do_transform(p->region, &ox, &oy, psfp);
+ }
+ else
+ ox = oy = 0;
+ r = p->region;
+ }
+ put_dim((long)(p->h-ox), psfp);
+ putc(' ', psfp);
+ put_dim((long)(p->v-oy), psfp);
+ fputs(" M\n", psfp);
+ fputs("gsave\n", psfp);
+ put_dim(1L, psfp);
+ fputs(" dup scale\n", psfp);
+ fputs(p->s, psfp);
+ putc('\n', psfp);
+ fputs("grestore\n", psfp);
+ p = p->next;
+ free((char *)q);
+ }
+ inline_list = NULL;
+ if (r != NO_REGION)
+ fputs("grestore\n", psfp);
+ fputs("EO\n", psfp);
+}
+/* this list is used during pass 1 to hold a list of all prologue files */
+
+struct string_list {
+ struct string_list *next;
+ char s[1];
+};
+
+static struct string_list *prologue_list;
+
+/* this is called by special during pass 1 to add a prologue file to
+prologue_list */
+
+
+/* this is called while the prologue is being written to include all the
+prologue files that have been specified in the document */
+
+void p_special_prologues(psfp)
+FILE *psfp;
+{
+ while (prologue_list != NULL) {
+ struct string_list *temp = prologue_list;
+ if (include_file(prologue_list->s, psfp) == EOF)
+ message(ERROR, "can't open prologue file %s: ignoring it",
+ prologue_list->s);
+ prologue_list = prologue_list->next;
+ free((char *)temp);
+ }
+}
+
+#ifdef PROTO
+typedef void special_t(int pass, char *arg, integer x, integer y);
+static special_t landscape_special;
+static special_t magnification_special;
+static special_t prolog_special;
+static special_t inline_special;
+static special_t import_special;
+static special_t rotate_special;
+static special_t transform_special;
+static special_t origin_special;
+static special_t begin_special;
+static special_t end_special;
+static special_t form_special;
+static special_t hsbcolor_special;
+static special_t rgbcolor_special;
+static special_t gray_special;
+#else
+static void landscape_special();
+static void magnification_special();
+static void prolog_special();
+static void inline_special();
+static void import_special();
+static void rotate_special();
+static void transform_special();
+static void origin_special();
+static void begin_special();
+static void end_special();
+static void form_special();
+static void hsbcolor_special();
+static void rgbcolor_special();
+static void gray_special();
+#endif
+
+
+static struct {
+ char *name;
+#ifdef PROTO
+ special_t *proc;
+#else
+ void (*proc)();
+#endif
+} special_table[] = {
+ "landscape", landscape_special,
+ "magnification", magnification_special,
+ "prolog", prolog_special,
+ "inline", inline_special,
+ "import", import_special,
+ "rotate", rotate_special,
+ "transform", transform_special,
+ "origin", origin_special,
+ "begin", begin_special,
+ "end", end_special,
+ "form", form_special,
+ "rgbcolor", rgbcolor_special,
+ "hsbcolor", hsbcolor_special,
+ "gray", gray_special,
+ NULL
+};
+
+static void landscape_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ if (pass == PASS2)
+ landscape = TRUE;
+}
+
+static void magnification_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ if (pass == PASS2) {
+ int n;
+ n = atoi(arg);
+ if (n <= 0)
+ message(ERROR, "bad magnification");
+ else
+ magnification = n;
+ }
+}
+
+
+static void prolog_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ char *p = arg;
+ struct string_list *ptr;
+ if (pass != PASS1)
+ return;
+ while (!isspace(*p) && *p != '\0')
+ p++;
+ *p = '\0';
+ for (ptr = prologue_list; ptr != NULL; ptr = ptr->next)
+ if (strcmp(arg, ptr->s) == 0)
+ return;
+ if ((ptr = (struct string_list *)
+ malloc(sizeof(struct string_list) + strlen(arg))) == NULL)
+ out_of_memory();
+ strcpy(ptr->s, arg);
+ ptr->next = prologue_list;
+ prologue_list = ptr;
+}
+
+
+static void inline_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x;
+integer y;
+{
+ struct inline_code *p;
+ if (pass != PASS2)
+ return;
+ p = (struct inline_code *)
+ malloc(sizeof(struct inline_code) + strlen(arg));
+ if (p == NULL)
+ out_of_memory();
+ p->h = x;
+ p->v = y;
+ p->region = current_region;
+ strcpy(p->s, arg);
+ p->next = inline_list;
+ inline_list = p;
+}
+
+
+
+static void import_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ if (pass == PASS2) {
+ struct import *p;
+ if ((p = (struct import *)
+ malloc(sizeof(struct import)+strlen(arg))) == NULL)
+ out_of_memory();
+ p->x = x;
+ p->y = y;
+ p->region = current_region;
+ strcpy(p->arg, arg);
+ p->next = import_list;
+ import_list = p;
+ }
+ else
+ read_import_file(strtok(arg, " \n\t\r"));
+}
+
+/* x and y are 0 on PASS1 */
+
+void special(pass, s, x, y)
+int pass;
+char *s;
+integer x, y;
+{
+ char *q;
+ int i;
+ char *p = s;
+ if (pass != PASS1 && pass != PASS2)
+ cant_happen();
+#ifdef TPIC_SUPPORT
+ if (tpic_special(pass, s, x, y))
+ return;
+#endif
+ while (isspace(*p))
+ p++;
+ q = p;
+ while (*q != '\0' && *q != ':') {
+ *q = isupper(*q) ? tolower(*q) : *q;
+ q++;
+ }
+ if (*q == '\0') {
+ if (pass == PASS2)
+ message(WARNING,
+ "a \\special without the `dvitops:' tag was ignored");
+ return;
+ }
+ *q++ = '\0';
+ if (strcmp(p, "dvitops") != 0) {
+ if (pass == PASS2)
+ message(WARNING,
+ "a \\special without the `dvitops:' tag was ignored");
+ return;
+ }
+ while (isspace(*q))
+ q++;
+ p = q;
+ while (*q != '\0' && !isspace(*q)) {
+ *q = isupper(*q) ? tolower(*q) : *q;
+ q++;
+ }
+ if (*q != '\0')
+ *q++ = '\0';
+ for (i = 0; special_table[i].name != NULL; i++)
+ if (strcmp(p, special_table[i].name) == 0) {
+ (*special_table[i].proc)(pass, q, x, y);
+ return;
+ }
+ if (pass == PASS2)
+ message(ERROR, "\\special keyword not recognised: %s", p);
+}
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979324
+#endif
+
+#define REGION_MAX 256
+#define RNAME_MAX 128
+static char *WS = " \n\r\t";
+/* we represent a two-dimensional transformation with the `matrix'
+structure; it represents the matrix
+|a b |
+|c d |
+*/
+
+typedef struct {
+ double a, b, c, d;
+} matrix_t;
+
+
+enum color_type { NO_COLOR, RGB_COLOR, HSB_COLOR, GRAY_COLOR };
+
+typedef struct {
+ char name[RNAME_MAX];
+ integer origin_x;
+ integer origin_y;
+ matrix_t matrix;
+ enum color_type color_type;
+ double color[3];
+} region_t;
+
+static region_t *region[REGION_MAX];
+#ifdef PROTO
+static int lookup_region(char *name);
+static void multiply(matrix_t *m, matrix_t *n, matrix_t *mn);
+#else
+static int lookup_region();
+static void multiply();
+#endif
+
+/* m, n and mn must all be distinct */
+
+static void multiply(m, n, mn)
+matrix_t *m, *n, *mn;
+{
+ mn->a = m->a*n->a + m->b*n->c;
+ mn->b = m->a*n->b + m->b*n->d;
+ mn->c = m->c*n->a + m->d*n->c;
+ mn->d = m->c*n->b + m->d*n->d;
+}
+
+
+static int lookup_region(name)
+char *name;
+{
+ int i;
+ for (i = 0; i < nregions; i++) {
+ if (region[i] == NULL)
+ cant_happen();
+ if (strncmp(region[i]->name, name, RNAME_MAX) == 0)
+ return i;
+ }
+ if (nregions >= REGION_MAX)
+ message(FATAL_ERROR, "too many regions");
+ if (region[nregions] == NULL
+ && (region[nregions] = (region_t *)
+ malloc(sizeof(region_t))) == NULL)
+ out_of_memory();
+ strncpy(region[nregions]->name, name, RNAME_MAX);
+ region[nregions]->origin_x = 0;
+ region[nregions]->origin_y = 0;
+ region[nregions]->matrix.a = 1.0;
+ region[nregions]->matrix.b = 0.0;
+ region[nregions]->matrix.c = 0.0;
+ region[nregions]->matrix.d = 1.0;
+ region[nregions]->color_type = NO_COLOR;
+ return nregions++;
+}
+
+
+static void rotate_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ char name[128];
+ int n;
+ double theta;
+ matrix_t m;
+ matrix_t temp;
+ if (pass != PASS2)
+ return;
+ if (sscanf(arg, "%127s %lf", name, &theta) != 2) {
+ message(ERROR, "rotate \\special syntax error");
+ return;
+ }
+ n = lookup_region(name);
+ theta *= M_PI/180.0;
+ m.a = cos(theta);
+ m.b = sin(theta);
+ m.c = -sin(theta);
+ m.d = cos(theta);
+ multiply(&(region[n]->matrix), &m, &temp);
+ memcpy((char *)&(region[n]->matrix), (char *)&temp, sizeof(matrix_t));
+}
+
+
+static void transform_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ char name[128];
+ int n;
+ matrix_t m, temp;
+ if (pass != PASS2)
+ return;
+ if (sscanf(arg, " %127s %lf %lf %lf %lf", name,
+ &m.a, &m.b, &m.c, &m.d) != 5) {
+ message(ERROR, "transform \\special syntax error");
+ return;
+ }
+ n = lookup_region(name);
+ multiply(&(region[n]->matrix), &m, &temp);
+ memcpy((char *)&(region[n]->matrix), (char *)&temp, sizeof(matrix_t));
+}
+
+static void rgbcolor_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ double color[3];
+ char name[128];
+ int i, n;
+ int bad = FALSE;
+ if (pass != PASS2)
+ return;
+ if (sscanf(arg, "%127s %lf %lf %lf", name, color, color + 1, color + 2)
+ != 4) {
+ message(ERROR, "rgbcolor \\special syntax error");
+ return;
+ }
+ n = lookup_region(name);
+ for (i = 0; i < 3 && !bad; i++)
+ if (color[i] < 0.0 || color[i] > 1.0) {
+ bad = TRUE;
+ message(ERROR, "color parameter must be between 0.0 and 1.0");
+ }
+ else
+ region[n]->color[i] = color[i];
+ region[n]->color_type = bad ? NO_COLOR : RGB_COLOR;
+}
+
+static void hsbcolor_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ double color[3];
+ char name[128];
+ int i, n;
+ int bad = FALSE;
+ if (pass != PASS2)
+ return;
+ if (sscanf(arg, "%127s %lf %lf %lf", name, color, color + 1, color + 2)
+ != 4) {
+ message(ERROR, "rgbcolor \\special syntax error");
+ return;
+ }
+ n = lookup_region(name);
+ for (i = 0; i < 3 && !bad; i++)
+ if (color[i] < 0.0 || color[i] > 1.0) {
+ bad = TRUE;
+ message(ERROR, "color parameter must be between 0.0 and 1.0");
+ }
+ else
+ region[n]->color[i] = color[i];
+ region[n]->color_type = bad ? NO_COLOR : RGB_COLOR;
+}
+
+static void gray_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ double gray;
+ char name[128];
+ int n;
+ if (pass != PASS2)
+ return;
+ if (sscanf(arg, "%127s %lf", name, &gray) != 2) {
+ message(ERROR, "gray \\special syntax error");
+ return;
+ }
+ n = lookup_region(name);
+ if (gray < 0.0 || gray > 1.0) {
+ message(ERROR, "gray parameter must be between 0.0 and 1.0");
+ region[n]->color_type = NO_COLOR;
+ }
+ else {
+ region[n]->color[0] = gray;
+ region[n]->color_type = GRAY_COLOR;
+ }
+}
+
+
+static void origin_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ int n;
+ if (pass != PASS2)
+ return;
+ arg = strtok(arg, WS);
+ if (arg == NULL)
+ message(ERROR, "origin \\special syntax error");
+ n = lookup_region(arg);
+ if (region[n]->origin_x != 0 || region[n]->origin_y != 0)
+ message(WARNING, "multiple origins for object %s", arg);
+ region[n]->origin_x = x;
+ region[n]->origin_y = y;
+}
+
+
+
+static void begin_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ if (pass != PASS2)
+ return;
+ arg = strtok(arg, WS);
+ if (current_region != NO_REGION)
+ message(ERROR, "can't have nested begin \\special");
+ current_region = lookup_region(arg);
+}
+
+static void end_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x, y;
+{
+ if (pass != PASS2)
+ return;
+ if (current_region == NO_REGION)
+ message(ERROR, "end with no begin");
+ else
+ current_region = NO_REGION;
+}
+
+void do_transform(n, origin_x, origin_y, psfp)
+int n;
+integer *origin_x, *origin_y;
+FILE *psfp;
+{
+ if (n >= nregions)
+ message(FATAL_ERROR, "too many regions");
+ *origin_x = region[n]->origin_x;
+ *origin_y = region[n]->origin_y;
+ if (*origin_x != 0 || *origin_y != 0) {
+ put_dim((long)*origin_x, psfp);
+ putc(' ', psfp);
+ put_dim((long)*origin_y, psfp);
+ fputs(" translate\n", psfp);
+ }
+ fprintf(psfp, "[%g %g %g %g 0 0] concat\n",
+ region[n]->matrix.a, region[n]->matrix.b,
+ region[n]->matrix.c, region[n]->matrix.d);
+ switch(region[n]->color_type) {
+ case GRAY_COLOR:
+ fprintf(psfp, "%g setgray\n", region[n]->color[0]);
+ break;
+ case RGB_COLOR:
+ fprintf(psfp, "%g %g %g setrgbcolor\n", region[n]->color[0],
+ region[n]->color[1], region[n]->color[2]);
+ break;
+ case HSB_COLOR:
+ fprintf(psfp, "%g %g %g sethsbcolor\n", region[n]->color[0],
+ region[n]->color[1], region[n]->color[2]);
+ break;
+ case NO_COLOR:
+ break;
+ default:
+ cant_happen();
+ }
+}
+
+int strprefix(prefix, s)
+char *prefix, *s;
+{
+ while (*prefix != '\0')
+ if (*prefix++ != *s++)
+ return FALSE;
+ return TRUE;
+}
+
+/* this needs rewriting */
+
+static void read_import_file(filename)
+char *filename;
+{
+ FILE *fp;
+ char buf[256];
+ struct import_file *p;
+ struct depend_list *q;
+ int atend = FALSE, had_bb = FALSE, in_body = FALSE;
+ int in_trailer = FALSE;
+ p = (struct import_file *)
+ malloc(sizeof(struct import_file) + strlen(filename));
+ if (p == NULL)
+ out_of_memory();
+ strcpy(p->file, filename);
+ p->font = NULL;
+ p->next = doc_import_list;
+ if ((fp = xfopen(filename, FALSE, texinputs, (char *)NULL)) == NULL) {
+ message(ERROR, "can't open %s", filename);
+ return;
+ }
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ message(WARNING, "empty import file %s", filename);
+ fclose(fp);
+ return;
+ }
+ if (!strprefix("%!", buf)) {
+ message(ERROR, "%s not PostScript: doesn't start with %%!", filename);
+ fclose(fp);
+ return;
+ }
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ message(WARNING, "empty import file %s", filename);
+ fclose(fp);
+ return;
+ }
+ for (;;) {
+ char *k;
+ k = strtok(buf + 2, ": \t\r\n");
+ if (k == NULL || !strprefix("%%", buf)
+ || strcmp(k, "EndComments") == 0) {
+ if (atend) {
+ in_body = TRUE;
+ }
+ else
+ break;
+ }
+ else if (in_body && !in_trailer) {
+ if (strcmp(k, "Trailer") == 0)
+ in_trailer = TRUE;
+ }
+ else if (strcmp(k, "DocumentFonts") == 0) {
+ for (;;) {
+ struct postscript_f_list *f;
+ char *ptr = strtok((char *)NULL, " \t\r\n");
+ if (ptr != NULL && strcmp(ptr, "(atend)") == 0) {
+ atend = TRUE;
+ break;
+ }
+ while (ptr == NULL) {
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ buf[0] = '\0';
+ goto out;
+ }
+ if (memcmp(buf, "%%+", 3) != 0)
+ goto out;
+ ptr = strtok(buf+3, "\n\r\t ");
+ }
+ f = add_postscript_font(ptr);
+ q = (struct depend_list *)malloc(sizeof(struct depend_list));
+ q->f = f;
+ q->next = p->font;
+ p->font = q;
+ }
+ out: continue; /* don't read a line */
+ }
+ else if (strcmp(k, "BoundingBox") == 0) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ char *ptr = strtok((char *)NULL, "\r\t\n ");
+ double x;
+ if (ptr == NULL) {
+ message(ERROR, "BoundingBox comment empty");
+ fclose(fp);
+ return;
+ }
+ if (i == 0 && strcmp(ptr, "(atend)") == 0) {
+ atend = TRUE;
+ break;
+ }
+ had_bb = TRUE;
+ x = atof(ptr);
+ switch(i) {
+ case 0:
+ p->bb.llx = x;
+ break;
+ case 1:
+ p->bb.lly = x;
+ break;
+ case 2:
+ p->bb.urx = x;
+ break;
+ case 3:
+ p->bb.ury = x;
+ break;
+ default:
+ cant_happen();
+ }
+ }
+ }
+ if (fgets(buf, sizeof(buf), fp) == NULL)
+ break;
+ }
+ if (!had_bb) {
+ message(ERROR, "%s: no BoundingBox comment", filename);
+ fclose(fp);
+ return;
+ }
+ doc_import_list = p;
+ fclose(fp);
+}
+
+static struct string_list *form_list;
+
+static void form_special(pass, arg, x, y)
+int pass;
+char *arg;
+integer x;
+integer y;
+{
+ struct string_list *s;
+ if (pass != PASS2)
+ return;
+ if ((s = (struct string_list *)malloc(sizeof(struct string_list) + strlen(arg))) == NULL)
+ out_of_memory();
+ s->next = form_list;
+ form_list = s;
+ strcpy(s->s, arg);
+}
+
+void p_form_list(psfp)
+FILE *psfp;
+{
+ while (form_list != NULL) {
+ struct string_list *s = form_list;
+ fputs("/showpage {} def\n", psfp);
+ fprintf(psfp, "/--save-- save def\n%%%%BeginDocument: %s\n", s->s);
+ if (include_file(s->s, psfp) == EOF)
+ message(ERROR, "can't find %s", s->s);
+ fputs("\n%%EndDocument\n--save-- restore\n", psfp);
+ form_list = s->next;
+ free((char *)s);
+ }
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 0
+c-label-offset: -4
+tab-width: 4
+End:
+*/
+