/* psttoxdoc.c 0.1.0 Thu 19 Dec 1996 */ /* by Adam M. Costello */ /* This is ANSI C code. */ /* Reads the output of pstext.ps with VERBOSE and CHARSET=Latin-1 or */ /* CHARSET=ASCII, and writes XDOC 10.0. */ /* To do: Pull things out of main(). */ #include #include #include #include #define null ((void *) 0) static const char version[] = "psttoxdoc 0.1.0"; /* To convert from units of PostScript points to */ /* units of 0.1mm, multiply by unitsperpoint. */ static const double unitsperpoint = 254.0 / 72.0; enum { maxfonts = 200, maxmetrics = 200, maxencodings = 200, maxnamelen = 80, }; #define nameformat "%80s" static const char * const outofmem = "Out of memory.\n"; void fail(const char *msg) { fputs(msg,stderr); exit(EXIT_FAILURE); } void usage(void) { fputs("options:\n" " -w (in inches, default = 8.5)\n" " -h (in inches, default = 11.0)\n" " -d \n" " -p \n" , stderr); exit(EXIT_FAILURE); } void printstring(const char *s) /* Copy s to stdout, doubling quotation marks. */ { const char *p; for (p = s; *p; ++p) { if (*p == '"') printf("\"\""); else putchar(*p); } } void printtext(const char *s) /* Copy s to stdout, doubling left brackets. */ { const char *p; for (p = s; *p; ++p) { if (*p == '[') printf("[["); else putchar(*p); } } void startofpage(int pagenum, double pagewidth, double pageheight) { printf("[p;%d;P;1;?;0;9999;0;0;%d;%d]\n", pagenum, (int) (pagewidth * 254), (int) (pageheight * 254) ); printf("[t;1;1;0;%d;A;\"\";\"\";\"\";0;0;%d;%d;1]\n", (int) (pageheight * 254), (int) (pagewidth * 254), (int) (pageheight * 254) ); } void endofpage(double pagewidth, double pageheight) { printf("[g;9999;0;0;%d;%d]\n", (int) (pagewidth * 254), (int) (pageheight * 254) ); } void printspace(double x0, double y0, double x1, double y1, int numspaces) /* x0, y0 is the finishing point of the last word finished, and x1, */ /* y1 is the starting point of the word just starting. */ { printf("[h;%d;%d", (int) x0, (int) (x1 - x0)); if (numspaces > 1) printf(";%d]\n", numspaces); else printf("]\n"); } void startofline(double x, double y, int fontID) { printf("[s;1;%d;0;%d;p;%d]\n", (int) x, (int) y, fontID); } void endofline(double x, double y) { printf("[y;%d;0;%d;1;H]\n", (int) x, (int) y ); } void multiply(double ix, double iy, double jx, double jy, double tx, double ty, double *pix, double *piy, double *pjx, double *pjy, double *ptx, double *pty ) /* First matrix x second matrix -> second matrix */ { double ix1, iy1, jx1, jy1, tx1, ty1; ix1 = ix * *pix + iy * *pjx; iy1 = ix * *piy + iy * *pjy; jx1 = jx * *pix + jy * *pjx; jy1 = jx * *piy + jy * *pjy; tx1 = tx * *pix + ty * *pjx + *ptx; ty1 = tx * *piy + ty * *pjy + *pty; *pix = ix1; *piy = iy1; *pjx = jx1; *pjy = jy1; *ptx = tx1; *pty = ty1; } int main(int argc, char *argv[]) { double pagewidth = 8.5, pageheight = 11.0; /* inches */ char *docname = "unknown"; int c, r, n, m, e, f, i, j, k, x0, y0, x1, y1, pagenum = 1, nextfontID = 1, currentfont = -1, inword = 0, inline = 0, inpage = 0, numspaces; double left, bottom, right, top, x, y, sum, X, ix, iy, jx, jy, wordendx, wordendy; char d[2], name[maxnamelen + 1], *text, **argp; double bboxtop[maxmetrics], bboxbottom[maxmetrics], avgwidth[maxmetrics]; int fontencoding[maxfonts], fontbad[maxfonts]; char **encodings[maxencodings]; /* Map from pstext font IDs to XDOC font IDs: */ int fontIDmap[maxfonts]; /* Transformation from device coords to XDOC coords: */ double DXix = 1.0, DXiy = 0.0, DXjx = 0.0, DXjy = 1.0, DXtx = 0.0, DXty = 0.0; for (i = 0; i < maxencodings; ++i) encodings[i] = null; for (i = 0; i < maxfonts; ++i) fontbad[i] = 0; for (argp = argv + 1; *argp; ++argp) { if (!strcmp(*argp, "-w")) { if (!*++argp) fail("-w needs an argument\n"); pagewidth = atof(*argp); } else if (!strcmp(*argp, "-h")) { if (!*++argp) fail("-h needs an argument\n"); pageheight = atof(*argp); } else if (!strcmp(*argp, "-d")) { if (!*++argp) fail("-d needs an argument\n"); docname = *argp; } else if (!strcmp(*argp, "-p")) { if (!*++argp) fail("-d needs an argument\n"); pagenum = atoi(*argp) - 1; } else { fprintf(stderr, "unrecognized option: %s\n", *argp); usage(); } } c = getchar(); assert(c == 'I'); r = scanf("%lf %lf %lf %lf %lf %lf", &DXix, &DXiy, &DXjx, &DXjy, &DXtx, &DXty); assert(r == 6); if (DXiy != 0.0 || DXjx != 0.0) fail("Sorry, I can't handle rotated pages.\n"); multiply(unitsperpoint, 0.0, 0.0, -unitsperpoint, 0.0, 254 * pageheight, &DXix, &DXiy, &DXjx, &DXjy, &DXtx, &DXty); /* fprintf(stderr, "DX = [ %f %f %f %f %f %f ]\n", /* DEBUG */ /* DXix, DXiy, DXjx, DXjy, DXtx, DXty ); /* DEBUG */ printf("[a;\"XDOC.10.0\";E;\"%s\"]\n", version); printf("[d;\""); printstring(docname); printf("\"]\n"); for (;;) { r = scanf("%1s", d); if (r == EOF) break; assert(r == 1); switch (d[0]) { case 'M': r = scanf("%d %lf %lf %lf %lf %d", &m, &left, &bottom, &right, &top, &n); assert(r == 6); bboxtop[m] = top; bboxbottom[m] = bottom; for (i = 0, k = 0, sum = 0.0; i < n; ++i) { r = scanf("%lf %lf", &x, &y); assert(r == 2); if (x != 0.0) { sum += x; ++k; } avgwidth[m] = sum / k; /* Note that I have ignored y, which is probably wrong, but */ /* XDOC doesn't seem to deal with non-horizontal text either. */ } break; case 'E': r = scanf("%d %d", &e, &n); assert(r == 2); /* Free old encoding if necessary. */ if (encodings[e]) { k = sizeof encodings[e] / sizeof (char *); for (i = 0; i < k; ++i) free(encodings[e][i]); free(encodings[e]); } encodings[e] = malloc(n * sizeof (char *)); if (!encodings[e]) fail(outofmem); /* Read in new encoding. */ for (i = 0; i < n; ++i) { r = scanf("%*s %d", &k); assert(r == 1); if (k == -1) { encodings[e][i] = null; } else { encodings[e][i] = malloc((k + 1) * sizeof (char)); if (!encodings[e][i]) fail(outofmem); for (j = 0; j < k; ++j) { r = scanf("%d", &c); assert(r == 1); encodings[e][i][j] = c; } encodings[e][i][k] = '\0'; } } break; case 'F': r = scanf("%d %lf %lf %lf %lf %d %d" nameformat, &f, &ix, &iy, &jx, &jy, &e, &m, &name); assert(r == 8); fontIDmap[f] = nextfontID++; if (iy != 0.0 || jx != 0.0) { /* Just fail for non-horizontal fonts. */ fontbad[f] = 1; } else { fontencoding[f] = e; printf("[f;%d;\"", fontIDmap[f]); printstring(name); top = bboxtop[m] * jy * DXjy; bottom = bboxbottom[m] * jy * DXjy; x = 2.0 / 3.0 * top; /* x is fabricated, but MVD only cares about the total height, */ /* which it will calculate accurately (the x will cancel out). */ printf("\";R;u;%d;V;%d;%d;%d;%d;100]\n", (int) (avgwidth[m] * jx * DXjx), (int) -top, (int) (bottom - x), (int) -x, (int) ((bottom - top) / unitsperpoint) ); /* Notice that in the XDOC coordinate system, y */ /* increases downward, so we must do (bottom - */ /* top) to get a positive difference. */ } break; case 'G': r = scanf("%d %d %d %d %d %d", &f, &c, &x0, &y0, &x1, &y1); assert(r == 6); text = encodings[fontencoding[f]][c]; if (text && !strcmp(text, " ")) { if (inword) { inword = 0; numspaces = 1; printf("\n"); } else ++numspaces; } else { if (!inpage) { inpage = 1; startofpage(++pagenum, pagewidth, pageheight); } if (inline) { if (!inword) { printspace(wordendx, wordendy, x0 / 100.0 * DXix + DXtx, y0 / 100.0 * DXjy + DXty, numspaces ); } } else { startofline(x0 / 100.0 * DXix + DXtx, y0 / 100.0 * DXjy + DXty, fontIDmap[f] ); } inline = 1; inword = 1; wordendx = x1 / 100.0 * DXix + DXtx; wordendy = y1 / 100.0 * DXjy + DXty; if (f != currentfont) { currentfont = f; printf("[c;%d]", f); } printtext(text); } break; case 'W': if (inword) printf("\n"); inword = 0; break; case 'L': if (inword) printf("\n"); if (inline) endofline(wordendx, wordendy); inword = 0; inline = 0; break; case 'P': r = scanf("%d", &n); assert(r == 1); if (inword) printf("\n"); if (inpage) endofpage(pagewidth, pageheight); inword = 0; inline = 0; inpage = 0; currentfont = -1; break; default: break; } } printf("[Z\n"); return EXIT_SUCCESS; }