/* * fig2MF -- convert fig to mfpic METAFONT code * * copyright (c) 1993 Anthony Starks (ajs@merck.com) * You may do anything you want with this code except sell it * or claim that you wrote it. * * Version 0.00 -- Incorporate Tobin's small suggestions * Version 0.01 -- Change scaling to inches, * default [x-y]scale is 1/8 inch * slight format changes in cinit() * Version 0.02 -- Fixed pen switching bug * Version 0.03 -- Support new arcthree mode * Version 0.04 -- Token support for text */ #include #define put_msg(x) fputs(x, stderr); \ fprintf(stderr, \ " at line %d of file \"%s\" \n", line, curfile) #define dofill() 1.2-((double)area_fill/(double)FILL_BLACK) #define dopen(x) ((x-1)*PEN_INCR)+DEF_PEN #define VERSION 0.04 #define BUF_SIZE 1024 #define O_ELLIPSE 1 #define O_POLYLINE 2 #define O_SPLINE 3 #define O_TEXT 4 #define O_ARC 5 #define O_COMP 6 #define O_ECOMP -6 #define FILL_BLACK 21 #define N_CURVE 11 #define N_POLYLINE 12 #define N_ELLIPSE 19 #define N_ARC 20 #define DEF_PEN 0.5 #define PEN_INCR 0.10 #define DEF_BFILE "graphbase.mf" char buf[BUF_SIZE]; typedef struct { char *keyword; double *value; } Options; int line; double ppi; double mag; double code; double mfpen; double xscale; double yscale; double xl; double yl; double xu; double yu; double maxy; char *progname; char *curfile; char basefile[100]; Options opts[] = { {"-mag", &mag}, {"-code", &code}, {"-pen", &mfpen}, {"-xscale", &xscale}, {"-yscale", &yscale}, {"-xneg", &xl}, {"-xpos", &xu}, {"-yneg", &yl}, {"-ypos", &yu}, {"-top", &maxy}, {NULL, NULL} }; main(argc, argv) int argc; char *argv[]; { FILE *fp; int i; progname = argv[0]; curfile = "Standard Input"; strcpy(basefile, DEF_BFILE); line=1; mag=1000.0; code=32.0; mfpen=0.5; xscale=0.125; yscale=0.125; xl=0.0; xu=8.0; yl=0.0; yu=8.0; maxy=8.0; if (argc < 2) process("-"); else { for (i=1; i < argc; i++) { parse(argv[i]); } } ffin(); exit(0); } parse(s) char *s; { int i, n; char *strchr(); double atof(); for (i=0; opts[i].keyword != NULL; i++) { if (strncmp(s, opts[i].keyword, strlen(opts[i].keyword)) == 0) { *opts[i].value = atof(strchr(s, '=')+1); return; } } process(s); } process(filename) char *filename; { FILE *fp; int coord_sys, object; if (filename[0] == '-') { curfile = "Standard Input"; fp = stdin; } else { curfile=filename; if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%s: cannot open the input file \"%s\"\n", progname, filename); return; } } line = 1; fgets(buf, sizeof(buf), fp); if (strncmp(buf, "#FIG 2.1", 8) != 0) { put_msg("Not a fig 2.1 file"); return; } get_line(fp); if (sscanf(buf, "%lf%d\n", &ppi, &coord_sys) != 2) { put_msg("Incomplete data"); return; } cinit(); while (get_line(fp) > 0) { if (sscanf(buf, "%d", &object) != 1) { put_msg("Incorrect format"); return; } switch(object) { case O_COMP: case O_ECOMP: break; case O_ELLIPSE: ellipse(fp); break; case O_POLYLINE: polyline(fp); break; case O_SPLINE: curve(fp); break; case O_TEXT: text(fp); break; case O_ARC: arc(fp); break; default: fprintf(stderr, "%d is an ", object); put_msg("unknown object"); break; } } cfin(); if (fp != stdin) fclose(fp); } polyline(fp) FILE *fp; { int c, n, type, subtype, style, radius, thickness, color, depth, pen, area_fill, fa, ba, at, as, eflag; double style_val, athick, awidth, aht; char epsfile[100]; c = 0; n = sscanf(buf, "%d%d%d%d%d%d%d%d%lf%d%d%d", &type, &subtype, &style, &thickness, &color, &depth, &pen, &area_fill, &style_val, &radius, &fa, &ba); if (n != N_POLYLINE) { put_msg("Malformed polyline"); return c; } if (subtype == 5) fscanf(fp, "%d%s", &eflag, epsfile); if (fa) fscanf(fp, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); if (ba) fscanf(fp, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", dopen(thickness)); if (area_fill == FILL_BLACK) printf(" cycleshade(0, false,\n"); else if (area_fill < FILL_BLACK && area_fill > 0) printf(" cycleshade(%lfpt, false,\n", dofill()); else printf(" curve(false, false,\n"); c = coords(type, fp); if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", mfpen); return c; } curve(fp) FILE *fp; { int n, c, i, type, style, subtype, thickness, color, depth, pen, area_fill, fa, ba, at, as; double style_val, athick, awidth, aht, z; c = 0; n = sscanf(buf, "%d%d%d%d%d%d%d%d%lf%d%d", &type, &subtype, &style, &thickness, &color, &depth, &pen, &area_fill, &style_val, &fa, &ba); if (n != N_CURVE) { put_msg("Malformed spline"); return c; } if (fa) fscanf(fp, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); if (ba) fscanf(fp, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", dopen(thickness)); if (area_fill == FILL_BLACK) printf(" cycleshade(0, true,\n"); else if (area_fill < FILL_BLACK && area_fill > 0) printf(" cycleshade(%lfpt, true,\n", dofill()); else printf(" curve(true, false,\n"); c = coords(type, fp); if (subtype > 1) for (i=0; i < c*4; i++) fscanf(fp, "%lf", &z); if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", mfpen); return c; } coords(obj, fp) int obj; FILE *fp; { int c, n, x, y; c = 0; if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) { put_msg("Incomplete object"); return c; } printf(" (%lf, %lf)", x/ppi, maxy-(y/ppi)); for (c = 1;;) { if (fscanf(fp, "%d%d", &x, &y) != 2) { put_msg("Incomplete object"); fputs(buf, stderr); return c; } if (x == 9999) break; printf(",\n (%lf, %lf)", x/ppi, maxy-(y/ppi)); c++; } printf(");\n"); return c; } ellipse(fp) FILE *fp; { int n, type, subtype, style, thickness, color, depth, pen, area_fill, dir, cx, cy, rx, ry, sx, sy, ex, ey; double style_val, angle; n = sscanf(buf, "%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d", &type, &subtype, &style, &thickness, &color, &depth, &pen, &area_fill, &style_val, &dir, &angle, &cx, &cy, &rx, &ry, &sx, &sy, &ex, &ey); if (n != N_ELLIPSE) { put_msg("Malformed circle or ellipse"); return; } if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", dopen(thickness)); if (subtype == 3 || subtype == 4) { if (area_fill == FILL_BLACK) printf(" circshade(0, "); else if (area_fill < FILL_BLACK && area_fill > 0) printf(" circshade(%lfpt, ", dofill()); else printf(" circle("); printf("(%lf,%lf),%lf);\n", cx/ppi, maxy-(cy/ppi), rx/ppi); } else if (subtype == 1 || subtype == 2) { if (area_fill == FILL_BLACK) printf(" ellshade(0, "); else if (area_fill < FILL_BLACK && area_fill > 0) printf(" ellshade(%lfpt, ", dofill()); else printf(" ellipse("); printf("(%lf,%lf),%lf,%lf,0);\n", cx/ppi, maxy-(cy/ppi), rx/ppi, ry/ppi); } if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", mfpen); } arc(fp) FILE *fp; { int n, type, subtype, style, thickness, color, depth, pen, fill, dir, fa, ba, x1, y1, x2, y2, x3, y3; double style_val, cx, cy; n = sscanf(buf, "%d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d", &type, &subtype, &style, &thickness, &color, &depth, &pen, &fill, &style_val, &dir, &fa, &ba, &cx, &cy, &x1, &y1, &x2, &y2, &x3, &y3); if (fa) get_line(fp); if (ba) get_line(fp); if (n != N_ARC) { put_msg("Malformed arc"); return n; } if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", dopen(thickness)); printf(" arcthree((%lf,%lf), (%lf,%lf), (%lf,%lf));\n", x1/ppi, maxy-(y1/ppi), x2/ppi, maxy-(y2/ppi), x3/ppi, maxy-(y3/ppi)); if (thickness > 1) printf(" pickup pencircle scaled %.2lfpt;\n", mfpen); return n; } text(fp) FILE *fp; { int n, x, y; int type, font, size, pen, color, depth, filler, angle, flags, ht, len; char text[80], junk[2], *p, *strrchr(); n = sscanf(buf, "%*d%d%d%d%d%d%d%lf%d%d%d%d%d%[^\1]%[\1]", &type, &font, &size, &pen, &color, &depth, &angle, &flags, &ht, &len, &x, &y, text, junk); if ((n != 13) && (n != 14)) { put_msg("Bad Text"); return 0; } p = &text[1]; printf("%% label((%lf,%lf),%s)\n", x/ppi, maxy-(y/ppi), p); return(strlen(text)); } cinit() { static int once = 0; static int curchar; if (++once == 1) { curchar = (int)code; printf("%%\n%% %s version %.2lf --- Preamble\n%%\n", progname, VERSION); printf("mag:=%g/1000; input %s; code:=%g;\n", mag, basefile, code); printf("mfpicenv;\ninterim hdwdr:=1; interim hdten:=1;\n"); printf("interim penwd:=%.2lfpt;\npickup pencircle scaled penwd;\n", mfpen); } printf("%%\n%% %s (char %d)\n%%\n", curfile, ++curchar); printf("xscale:=%.3lf; yscale:=%.3lf; bounds(%.3lf,%.3lf,%.3lf,%.3lf);\n", xscale, yscale, xl, xu, yl, yu); printf("beginchar(incr code,xscale*(xpos-xneg)*in#,yscale*(ypos-yneg)*in#,0);\n"); printf(" setztr;\n"); printf(" pickup pencircle scaled %.2lfpt;\n", mfpen); } cfin() { printf("endchar;\n"); } ffin() { if (line > 1) printf("endmfpicenv;\nend.\n"); } get_line(fp) FILE *fp; { while (1) { if (NULL == fgets(buf, BUF_SIZE, fp)) { return (-1); } line++; if (*buf != '\n' && *buf != '#') return (1); /* Skip empty and comment lines */ } }