|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T f
Length: 15112 (0x3b08) Types: TextFile Names: »fig2latex.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./tex82/TeXgraphics/fig2latex/fig2latex.c«
/* * Fig2latex : Fig-to-LaTeX translator * * Modified 4/88 from f2p, the Fig-to-pic translator * Modified 6/88 from fig2tex, the Fig-to-PiCTeX translator * * Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU) * January 1985. * 1st revision : October 1985. * 2nd revision : March 1988 - read fig 1.4 * converted : April 1988 - produce PiCTeX output * by Micah Beck, Cornell Univ. (beck@svax.cs.cornell.edu) * converted : June 1988 - produce LaTeX picture environment output * by Frank Schmuck, Cornell Univ. (schmuck@svax.cs.cornell.edu) * * %W %G% */ #include <sys/file.h> #include <stdio.h> #include <math.h> #include "object.h" #include "fig2latex.h" #define TOP 840 #define THINLINES 1 #define THICKLINES 2 #define SWAP(x,y) {tmp=x; x=y; y=tmp;} #define round(x) ((rint(1000.0*(x))/1000.0)) #define TRANS(x,y) translate_coordinates(&x,&y) #define TRANS2(x1,y1,x2,y2) translate_coordinates(&x1,&y1); \ translate_coordinates(&x2,&y2) extern int getopt(); extern char *optarg; extern int optind; extern double sin(), cos(), acos(), fabs(); char Usage[] = "Usage: fig2latex [-f font] [-l thick] [-m mag] [-d dashm] [-Lvo] [in_file [out_file]]\n"; char Err_incomp[] = "Incomplete %s object at line %d."; char Err_mem[] = "Running out of memory."; char *from = NULL, *to = NULL; int verbose = 0; int oval = 0; float mag = 1.0; float dash_mag = 1.0; char textfont[64] = "\\twltt "; int thick_width = 2; double tolerance = 2.0; int (*translate_coordinates)() = NULL; double ppi; double unitlength; int cur_thickness = -1; double dot_diameter = THINDOT; double ldot_diameter = THIN_LDOT; put_msg(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8; { fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } translate1(xp, yp) int *xp, *yp; { *xp = *xp + 1; *yp = *yp + 1; } translate2(xp, yp) int *xp, *yp; { *xp = *xp + 1; *yp = TOP - *yp -1; } get_args(argc, argv) int argc; char *argv[]; { char c; while ((c = getopt(argc, argv, "f:l:Lm:d:ov")) != EOF) switch (c) { case 'f': /* set text font */ if (strcmp(optarg, ":")) { strncpy(textfont, optarg, 62); strcat(textfont, " "); } else textfont[0] = '\0'; break; case 'l': /* set thin/thick line threshold */ thick_width = atoi(optarg); break; case 'L': thick_width = 0; /* thick lines only */ break; case 'm': mag = atof(optarg); /* set magnification */ break; case 'd': dash_mag = atof(optarg); /* set dash magnification */ break; case 'o': oval = 1; /* make circle from ovals */ break; case 'v': verbose = 1; /* verbose mode */ break; case '?': fprintf(stderr, Usage); exit(1); break; } if (optind < argc) from = argv[optind++]; /* from file */ if (optind < argc) to = argv[optind]; /* to file */ } main(argc, argv) int argc; char *argv[]; { F_compound objects; int status; char c; get_args(argc, argv); if (from != NULL && freopen(from, "r", stdin) == NULL) { perror(from); exit(-1); } if (to != NULL && freopen(to, "w", stdout) == NULL) { perror(to); exit(-1); } c = fgetc(stdin); ungetc(c, stdin); if (c == '#') status = read_objects(stdin, &objects); else status = read_1_3_objects(stdin, &objects); if (status != 0) { if (from) read_fail_message(from, status); exit(0); } gentex_objects(&objects); } gentex_objects(objects) F_compound *objects; { int coord_system; F_arc *a; F_compound *c; F_ellipse *e; F_line *l; F_spline *s; F_text *t; int llx, lly, urx, ury; int tmp; if (0 == (ppi = (double)objects->nwcorner.x)) { fprintf(stderr, "Resolution is zero!! default to 80 ppi\n"); ppi = 80.0; } unitlength = mag/ppi; coord_system = objects->nwcorner.y; switch (coord_system) { case 1: translate_coordinates = translate1; break; case 2: translate_coordinates = translate2; break; default: fprintf(stderr, "Wrong coordinate system; cannot continue\n"); return; } compound_bound(objects, &llx, &lly, &urx, &ury); TRANS2(llx, lly, urx, ury); if (llx > urx) SWAP(llx, urx) if (lly > ury) SWAP(lly, ury) /* LaTeX start */ printf("\\setlength{\\unitlength}{%.3fin}\n", round(unitlength)); printf("\\begin{picture}(%d,%d)(%d,%d)\n", urx-llx, ury-lly+15, llx, lly-10); for (a = objects->arcs; a != NULL; a = a->next) gentex_arc(a); for (c = objects->compounds; c != NULL; c = c->next) gentex_compound(c); for (e = objects->ellipses; e != NULL; e = e->next) gentex_ellipse(e); for (l = objects->lines; l != NULL; l = l->next) gentex_line(l); for (s = objects->splines; s != NULL; s = s->next) gentex_spline(s); for (t = objects->texts; t != NULL; t = t->next) gentex_text(t); /* LaTeX ending */ printf("\\end{picture}\n"); } set_linewidth(w) int w; { int latex_w; if (w == 0) return; /* latex only knows thin lines or thick lines */ latex_w = (w >= thick_width)? THICKLINES: THINLINES; if (latex_w != cur_thickness) { cur_thickness = latex_w; if (cur_thickness == THICKLINES) { printf("\\thicklines\n"); dot_diameter = THICKDOT; ldot_diameter = THICK_LDOT; } else { printf("\\thinlines\n"); dot_diameter = THINDOT; ldot_diameter = THIN_LDOT; } } } gentex_compound(com) F_compound *com; { F_arc *a; F_compound *c; F_ellipse *e; F_line *l; F_spline *s; F_text *t; for (a = com->arcs; a != NULL; a = a->next) gentex_arc(a); for (c = com->compounds; c != NULL; c = c->next) gentex_compound(c); for (e = com->ellipses; e != NULL; e = e->next) gentex_ellipse(e); for (l = com->lines; l != NULL; l = l->next) gentex_line(l); for (s = com->splines; s != NULL; s = s->next) gentex_spline(s); for (t = com->texts; t != NULL; t = t->next) gentex_text(t); } gentex_line(l) F_line *l; { F_point *p, *q; int x, y, llx, lly, urx, ury, arrow; if (verbose) printf("%%\n%% Fig POLYLINE object\n%%\n"); set_linewidth(l->thickness); p = l->points; q = p->next; if (q == NULL) { /* A single point line */ x = p->x; y = p->y; TRANS(x, y); printf("\\put(%3d,%3d){\\circle*{%.3}}\n", x, y, dot_diameter/unitlength); return; } if (l->type == T_BOX) { /* A box */ x = p->x; y = p->y; TRANS(x, y); llx = urx = x; lly = ury = y; while (q != NULL) { x = q->x; y = q->y; TRANS(x, y); if (x < llx) llx = x; if (y < lly) lly = y; if (x > urx) urx = x; if (y > ury) ury = y; q = q->next; } put_box (llx, lly, urx, ury, l->style, l->style_val); return; } while (q != NULL) { arrow = 0; if (l->for_arrow && q->next == NULL) arrow = 1; if (l->back_arrow && p == l->points) arrow = (arrow)? 2: -1; single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val); p = q; q = q->next; } } single_line (x1, y1, x2, y2, arrow, style, val) int x1, y1, x2, y2, arrow, style; float val; { int dx, dy, sx, sy; double l, m, deviation; TRANS2(x1, y1, x2, y2); dx = x2-x1; dy = y2-y1; /*** compute direction vector ***/ get_slope(dx, dy, &sx, &sy, arrow); /*** compute line length in x-direction ***/ if (sx == 0) { l = (double)abs(dy); } else { m = (double)abs(sy) / (double)abs(sx); l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m); deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy)); if (deviation > tolerance) fprintf(stderr, "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n", dx, dy, deviation); } l = round(l); /*** output letex command ***/ switch (style) { case SOLID_LINE: put_solidline(x1, y1, sx, sy, l, arrow); break; case DASH_LINE: put_dashline(x1, y1, sx, sy, l, arrow, val); break; case DOTTED_LINE: put_dotline(x1, y1, sx, sy, l, arrow, val); break; } } /* * draw box */ put_box (llx, lly, urx, ury, style, val) int llx, lly, urx, ury, style; float val; { int dlen; switch (style) { case SOLID_LINE: printf("\\put(%3d,%3d){\\framebox(%d,%d){}}\n", llx, lly, urx-llx, ury-lly); break; case DASH_LINE: dlen = (int)(val*dash_mag + 0.5); printf("\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n", llx, lly, dlen, urx-llx, ury-lly); break; case DOTTED_LINE: put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val); put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val); put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val); put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val); break; } return; } /* * draw a solid line given latex slope */ put_solidline (x, y, sx, sy, l, arrow) int x, y, sx, sy, arrow; double l; { double cosine; /* cosine of line angle */ double dx, dy; int x2, y2, n; if (sx) { cosine = (double)abs(sx) / sqrt((double)(sx*sx + sy*sy)); x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5); y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5); } else { cosine = 1.0; x2 = x; y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5); } if (sx == 0 || sy == 0 || (l/cosine)*unitlength >= MIN_LEN) { switch (arrow) { case 0: /* simple line */ printf("\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy); break; case 1: /* forward arrow */ printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy); break; case -1: /* backward arrow */ printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy); break; case 2: /* double arrow */ printf("\\put(%3d,%3d){\\vector(%2d,%2d){ 0}}\n", x,y,-sx,-sy); printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy); break; } if (l == floor(l)) printf("{%3.0f}}\n", l); else printf("{%7.3f}}\n", l); } else { n = 2 * (l/cosine) / (ldot_diameter/unitlength); fprintf(stderr, "Line too short; will do %d dots\n", n); dx = l / (double)n; if (sx < 0) dx = -dx; dy = dx * (double)sy / (double)sx; printf("\\multiput(%3d,%3d)(%.4f,%.4f){%d}{\\circle*{%.4f}}\n", x, y, dx, dy, n+1, ldot_diameter/unitlength); if (arrow == 1 || arrow == 2) /* forward arrow */ printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy); if (arrow == -1 || arrow == 2) /* backward arrow */ printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy); } } /* * draw a dashed line given latex slope */ put_dashline (x, y, sx, sy, l, arrow, val) int x, y, sx, sy, arrow; double l; float val; { double cosine; /* cosine of line angle */ double nd; /* number of dashes and gaps fitting on line */ int n; /* nd rounded to the nearest odd integer */ double dl; /* actual x-length of each dash */ double dg; /* actual x-length of each gap */ double dx, dy; /* step between dashes */ int x2, y2; if (sx) { cosine = (double)abs(sx) / sqrt((double)(sx*sx + sy*sy)); x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5); y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5); } else { cosine = 1.0; x2 = x; y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5); } /*** compute number of dashes, length of dashes and gaps ***/ nd = l / (val*dash_mag*cosine); n = (int) (rint((nd + 1.0)/2.0)*2 - 1); dl = l / (double)n; if (sx && sy && (dl/cosine)*unitlength < MIN_LEN) { fprintf(stderr, "Dash too small; using larger dash\n"); dl = MIN_LEN/unitlength * cosine; nd = l / dl; n = (int) (rint((nd + 1.0)/2.0)*2 - 1); } if (2*dl >= l || (sx && sy && (l/cosine)*unitlength < MIN_LEN)) { fprintf(stderr, "Dashed line too short; drawing solid line\n"); put_solidline (x, y, sx, sy, l, arrow); return; } dg = (l - (n/2+1)*dl) / (double)(n/2); if (sx) { dx = dl+dg; if (sx < 0) dx = -dx; dy = dx * (double)sy / (double)sx; } else { dx = 0.0; dy = dl+dg; if (sy < 0) dy = -dy; } /*** draw dashed line ***/ printf("\\multiput(%3d,%3d)(%7.3f,%7.3f){%d}{\\line(%2d,%2d){%7.3f}}\n", x, y, dx, dy, n/2+1, sx, sy, dl); /*** draw arrow heads ***/ if (arrow == 1 || arrow == 2) printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); if (arrow == -1 || arrow == 2) printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); } /* * draw a dotted line given latex slope */ put_dotline (x, y, sx, sy, l, arrow, val) int x, y, sx, sy, arrow; double l; float val; { double cosine; /* cosine of line angle */ double nd; /* number of dots fitting on line */ int n; /* nd rounded to the nearest integer */ double dx, dy; /* step between dashes */ int x2, y2; cosine = (sx)? (double)abs(sx) / sqrt((double)(sx*sx + sy*sy)): 1.0; /*** compute step width ***/ nd = l / (3*val*cosine); n = rint(nd); dx = l / (double)n; if (sx) { dx = l / (double)n; if (sx < 0) dx = -dx; dy = dx * (double)sy / (double)sx; } else { dx = 0.0; dy = l / (double)n; if (sy < 0) dy = -dy; } /*** draw arrow heads ***/ if (arrow == 1 || arrow == 2) { /* forward arrow */ if (sx) { x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5); y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5); } else { x2 = x; y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5); } printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); n--; } if (arrow == -1 || arrow == 2) { printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); x = x + dx + 0.5; y = y + dy + 0.5; n--; } /*** draw dotted line ***/ printf("\\multiput(%3d,%3d)(%7.3f,%7.3f){%d}{\\circle*{%7.3f}}\n", x, y, dx, dy, n+1, dot_diameter/unitlength); } gentex_spline(s) F_spline *s; { fprintf(stderr, "Can't generate spline; omitting object\n"); } gentex_ellipse(e) F_ellipse *e; { int x, y, d, dx, dy; if (verbose) printf("%%\n%% Fig ELLIPSE\n%%\n"); set_linewidth(e->thickness); switch (e->style) { case SOLID_LINE: break; case DASH_LINE: fprintf(stderr, "Dashed circles and elipses not supported\n"); break; case DOTTED_LINE: fprintf(stderr, "Dotted circles and elipses not supported\n"); break; } x = e->center.x; y = e->center.y; TRANS(x, y); if (e->radiuses.x == e->radiuses.y) { d = 2 * e->radiuses.x; if (oval) printf("\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, d, d); else printf("\\put(%3d,%3d){\\circle{%d}}\n", x, y, d); } else { fprintf(stderr, "Can't generate ellipse; approximating by oval\n"); dx = 2 * e->radiuses.x; dy = 2 * e->radiuses.y; printf("\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy); } } gentex_text(t) F_text *t; { int x, y; if (verbose) printf("%%\n%% Fig TEXT object\n%%\n"); x = t->base_x; y = t->base_y; /* + font_size ? XXX */ TRANS(x, y); printf("\\put(%3d,%3d){%s%s}\n", x, y, textfont, t->cstring); } gentex_arc(a) F_arc *a; { fprintf(stderr, "Can't generate arc; omitting object\n"); }