rsalz@bbn.com (Rich Salz) (08/31/90)
Submitted-by: Micah Beck <beck@cs.cornell.edu> Posting-number: Volume 23, Issue 17 Archive-name: transfig/part04 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 6)." # Contents: transfig/fig2dev/dev/genlatex.c # transfig/fig2dev/dev/genps.c # Wrapped by beck@rocky on Thu May 17 15:56:13 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'transfig/fig2dev/dev/genlatex.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'transfig/fig2dev/dev/genlatex.c'\" else echo shar: Extracting \"'transfig/fig2dev/dev/genlatex.c'\" \(20332 characters\) sed "s/^X//" >'transfig/fig2dev/dev/genlatex.c' <<'END_OF_FILE' X/* X * genlatex.c : LaTeX driver for fig2dev X * X * Author: Frank Schmuck, Cornell University 6/88 X * Converted from fig2latex 5/89 by Micah Beck X * X*/ X#ifdef hpux X#include <sys/types.h> X#endif X#include <sys/file.h> X#include <stdio.h> X#include <math.h> X#include "object.h" X#include "fig2dev.h" X#include "texfonts.h" X Xextern char *strchr(); Xextern void printf(), fprintf(); Xextern double rad2deg, sin(), cos(), acos(), fabs(), atan(); X X#ifdef hpux X#define rint(a) floor((a)+0.5) /* close enough? */ X#endif X X#ifdef gould X#define rint(a) floor((a)+0.5) /* close enough? */ X#endif X X/* X * Installation dependent constants: X * X * THINDOT latex command for generating a dot if line width = \thinlines X * THICKDOT latex command for generating a dot if line width = \thicklines X * MIN_LEN shortest slanted line that latex can produce; shorter lines will X * we translated into a sequence of dots generated by \multiput. X * THICK_LDOT latex command for generating the dot for making short slanted X * lines if line width = \thinlines X * THIN_LDOT ... if line width = \thicklines X */ X#define THICKDOT "\\tenrm ." X#define THINDOT "\\sevrm ." Xdouble THIN_XOFF = (0.1/72.0); Xdouble THIN_YOFF = (0.7/72.0); Xdouble THICK_XOFF = (0.4/72.0); Xdouble THICK_YOFF = (0.6/72.0); X#define THICK_LDOT "\\sevrm ." X#define THIN_LDOT "\\fivrm ." Xdouble THIN_LXOFF = (0.1/72.0); Xdouble THIN_LYOFF = (0.7/72.0); Xdouble THICK_LXOFF = (0.4/72.0); Xdouble THICK_LYOFF = (0.6/72.0); X#define MIN_LEN (13.0/72.0) /* 13 points */ X X/* X * other constants and macros X */ X#define TOP 840 X#define THINLINES 1 X#define THICKLINES 2 X X/* X * Cornell DVI-to-IP has trouble with circles of radius greater than 8pt. X */ X#ifdef CORNELL X#define MAXCIRCLEDIA 16 X#else X#define MAXCIRCLEDIA 80 X#endif X#define MAXCIRCLERAD ((MAXCIRCLEDIA-0.5)/(2*72.27)) X X#define SWAP(x,y) {tmp=x; x=y; y=tmp;} X#define TRANS(x,y) (*translate_coordinates)(&x,&y) X#define TRANS2(x1,y1,x2,y2) (*translate_coordinates)(&x1,&y1); \ X (*translate_coordinates)(&x2,&y2) X#define TRANSD(x,y) (*translate_coordinates_d)(&x,&y) X#define MIN(x,y) (((x) <= (y))? (x): (y)) X#define MAX(x,y) (((x) >= (y))? (x): (y)) X#define ABS(x) (((x) >= 0)? (x): -(x)) X#define round(x) ((int) ((x) + ((x >= 0)? 0.5: -0.5))) X#define round4(x) ((round(10000.0*(x))/10000.0)) X Xchar thindot [] = THINDOT; Xchar thickdot[] = THICKDOT; Xchar thin_ldot [] = THIN_LDOT; Xchar thick_ldot[] = THICK_LDOT; X Xint coord_system; Xint verbose = 0; Xdouble dash_mag = 1.0; Xint thick_width = 1; Xdouble tolerance = 2.0; Xdouble arc_tolerance = 1.0; Xint (*translate_coordinates)() = NULL; Xint (*translate_coordinates_d)() = NULL; Xdouble unitlength; Xint cur_thickness = -1; Xdouble ldot_diameter = 1.0/72.0; Xchar *dot_cmd = thindot; Xchar *ldot_cmd = thin_ldot; Xdouble dot_xoffset; Xdouble dot_yoffset; Xdouble ldot_xoffset; Xdouble ldot_yoffset; X Xstatic translate1(xp, yp) Xint *xp, *yp; X{ X *xp = *xp + 1; X *yp = *yp + 1; X } X Xstatic translate2(xp, yp) Xint *xp, *yp; X{ X *xp = *xp + 1; X *yp = TOP - *yp -1; X } X Xstatic translate1_d(xp, yp) Xdouble *xp, *yp; X{ X *xp = *xp + 1.0; X *yp = *yp + 1.0; X } X Xstatic translate2_d(xp, yp) Xdouble *xp, *yp; X{ X *xp = *xp + 1.0; X *yp = (double)TOP - *yp -1.0; X } X Xvoid genlatex_option(opt, optarg) Xchar opt, *optarg; X{ X switch (opt) { X case 'f': /* set default text font */ X { int i; X X for ( i = 1; i <= MAXFONT + 1; i++ ) X if ( !strcmp(optarg, fontnames[i]) ) break; X X if ( i > MAXFONT + 1 ) X fprintf(stderr, X "warning: non-standard font name %s\n", optarg); X } X X fontnames[0] = fontnames[1] = optarg; X break; X X case 'l': /* set thin/thick line threshold */ X thick_width = atoi(optarg); X break; X X case 'd': X dash_mag = atof(optarg); /* set dash magnification */ X break; X X case 'v': X verbose = 1; /* verbose mode */ X break; X X case 's': X if (font_size <= 0 || font_size > MAXFONTSIZE) { X fprintf(stderr, X "warning: font size %d out of bounds\n", font_size); X } X break; X X case 'm': X case 'L': X break; X X default: X put_msg(Err_badarg, opt, "latex"); X exit(1); X break; X } X} X Xvoid genlatex_start(objects) XF_compound *objects; X{ X int tmp; X X fontsizes[0] = fontsizes[1] = TEXFONTSIZE(font_size); X X coord_system = objects->nwcorner.y; X unitlength = mag/objects->nwcorner.x; X X switch (coord_system) { X case 1: X translate_coordinates = translate1; X translate_coordinates_d = translate1_d; X break; X case 2: X translate_coordinates = translate2; X translate_coordinates_d = translate2_d; X break; X default: X fprintf(stderr, "Wrong coordinate system; cannot continue\n"); X return; X } X X TRANS2(llx, lly, urx, ury); X if (llx > urx) SWAP(llx, urx) X if (lly > ury) SWAP(lly, ury) X X /* LaTeX start */ X fprintf(tfp, "\\setlength{\\unitlength}{%.4fin}%%\n", X round4(unitlength)); X fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n", X urx-llx, ury-lly, llx, lly); X} X Xvoid genlatex_end() X{ X /* LaTeX ending */ X fprintf(tfp, "\\end{picture}\n"); X} X Xstatic set_linewidth(w) Xint w; X{ X int latex_w; X X if (w == 0) return; X /* latex only knows thin lines or thick lines */ X latex_w = (w >= thick_width)? THICKLINES: THINLINES; X if (latex_w != cur_thickness) { X cur_thickness = latex_w; X if (cur_thickness == THICKLINES) { X fprintf(tfp, "\\thicklines\n"); X dot_cmd = thickdot; X dot_xoffset = round4(THICK_XOFF/unitlength); X dot_yoffset = round4(THICK_YOFF/unitlength); X ldot_cmd = thick_ldot; X ldot_xoffset = round4(THICK_LXOFF/unitlength); X ldot_yoffset = round4(THICK_LYOFF/unitlength); X } X else { X fprintf(tfp, "\\thinlines\n"); X dot_cmd = thin_ldot; X dot_xoffset = round4(THIN_XOFF/unitlength); X dot_yoffset = round4(THIN_YOFF/unitlength); X ldot_cmd = thin_ldot; X ldot_xoffset = round4(THIN_LXOFF/unitlength); X ldot_yoffset = round4(THIN_LYOFF/unitlength); X } X } X } X Xvoid genlatex_line(l) XF_line *l; X{ X F_point *p, *q; X int x, y, llx, lly, urx, ury, arrow; X X if (verbose) fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n"); X X set_linewidth(l->thickness); X X p = l->points; X q = p->next; X X if (q == NULL) { /* A single point line */ X x = p->x; y = p->y; X TRANS(x, y); X fprintf(tfp, "\\put(%3d,%3d){\\makebox(%.4f,%.4f){%s}}\n", X x, y, dot_xoffset, dot_yoffset, dot_cmd); X return; X } X X if (l->type == T_BOX) { /* A box */ X x = p->x; y = p->y; X TRANS(x, y); X llx = urx = x; X lly = ury = y; X while (q != NULL) { X x = q->x; y = q->y; X TRANS(x, y); X if (x < llx) llx = x; X if (y < lly) lly = y; X if (x > urx) urx = x; X if (y > ury) ury = y; X q = q->next; X } X put_box (llx, lly, urx, ury, l->style, l->style_val); X return; X } X X while (q != NULL) { X arrow = 0; X if (l->for_arrow && q->next == NULL) X arrow = 1; X if (l->back_arrow && p == l->points) X arrow = (arrow)? 2: -1; X single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val); X p = q; X q = q->next; X } X X if (l->area_fill && (int)l->area_fill != DEFAULT) X fprintf(stderr, "Line area fill not implemented\n"); X } X Xstatic single_line (x1, y1, x2, y2, arrow, style, val) Xint x1, y1, x2, y2, arrow, style; Xdouble val; X{ X int dx, dy, sx, sy; X double l, m, deviation; X X TRANS2(x1, y1, x2, y2); X dx = x2-x1; X dy = y2-y1; X /*** compute direction vector ***/ X get_slope(dx, dy, &sx, &sy, arrow); X /*** compute line length in x-direction ***/ X if (sx == 0) { X l = (double)abs(dy); X } else { X m = (double)abs(sy) / (double)abs(sx); X l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m); X deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy)); X if (deviation > tolerance) X fprintf(stderr, X "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n", X dx, dy, deviation); X } X l = round4(l); X /*** output letex command ***/ X switch (style) { X case SOLID_LINE: X put_solidline(x1, y1, sx, sy, l, arrow); X break; X case DASH_LINE: X put_dashline(x1, y1, sx, sy, l, arrow, val); X break; X case DOTTED_LINE: X put_dotline(x1, y1, sx, sy, l, arrow, val); X break; X } X } X X X/* X * draw box X */ Xstatic put_box (llx, lly, urx, ury, style, val) Xint llx, lly, urx, ury, style; Xdouble val; X{ X int dlen; X X switch (style) { X case SOLID_LINE: X fprintf(tfp, "\\put(%3d,%3d){\\framebox(%d,%d){}}\n", X llx, lly, urx-llx, ury-lly); X break; X case DASH_LINE: X dlen = round(val*dash_mag); X fprintf(tfp, "\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n", X llx, lly, dlen, urx-llx, ury-lly); X break; X case DOTTED_LINE: X put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val); X put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val); X put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val); X put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val); X break; X } X return; X } X X/* X * draw a solid line given latex slope X */ Xstatic put_solidline (x, y, sx, sy, l, arrow) Xint x, y, sx, sy, arrow; Xdouble l; X{ X double cosine; /* cosine of line angle */ X double dx, dy; X int x2, y2, n; X X if (sx) { X cosine = (double)abs(sx) / hypot((double)sx, (double)sy); X x2 = (sx >= 0)? x + round(l): x - round(l); X y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx); X } X else { X cosine = 1.0; X x2 = x; X y2 = (sy >= 0)? y + round(l): y - round(l); X } X if (sx == 0 || sy == 0 || (l/cosine)*unitlength >= MIN_LEN) { X switch (arrow) { X case 0: /* simple line */ X fprintf(tfp, "\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy); X break; X case 1: /* forward arrow */ X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy); X break; X case -1: /* backward arrow */ X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy); X break; X case 2: /* double arrow */ X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){ 0}}\n", x,y,-sx,-sy); X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy); X break; X } X if (l == floor(l)) X fprintf(tfp, "{%3.0f}}\n", l); X else X fprintf(tfp, "{%7.3f}}\n", l); X } X else { X n = 2 * (l/cosine) / (ldot_diameter/unitlength); X fprintf(stderr, "Line too short; will do %d dots\n", n); X dx = l / (double)n; X if (sx < 0) dx = -dx; X dy = dx * (double)sy / (double)sx; X fprintf(tfp, X "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n", X x, y, dx, dy, n+1, ldot_xoffset, ldot_yoffset, ldot_cmd); X if (arrow == 1 || arrow == 2) /* forward arrow */ X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy); X if (arrow == -1 || arrow == 2) /* backward arrow */ X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy); X } X } X X/* X * draw a dashed line given latex slope X */ Xstatic put_dashline (x, y, sx, sy, l, arrow, val) Xint x, y, sx, sy, arrow; Xdouble l; Xdouble val; X{ X double cosine; /* cosine of line angle */ X double nd; /* number of dashes and gaps fitting on line */ X int n; /* nd rounded to the nearest odd integer */ X double dl; /* actual x-length of each dash */ X double dg; /* actual x-length of each gap */ X double dx, dy; /* step between dashes */ X int x2, y2; X X X if (sx) { X cosine = (double)abs(sx) / hypot((double)sx, (double)sy); X x2 = (sx >= 0)? x + round(l): x - round(l); X y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx ); X } X else { X cosine = 1.0; X x2 = x; X y2 = (sy >= 0)? y + round(l): y - round(l); X } X /*** compute number of dashes, length of dashes and gaps ***/ X nd = l / (val*dash_mag*cosine); X n = (int) (rint((nd + 1.0)/2.0)*2 - 1); X dl = l / (double)n; X if (sx && sy && (dl/cosine)*unitlength < MIN_LEN) { X fprintf(stderr, "Dash too small; using larger dash\n"); X dl = MIN_LEN/unitlength * cosine; X nd = l / dl; X n = (int) (rint((nd + 1.0)/2.0)*2 - 1); X } X if (2*dl >= l || (sx && sy && (l/cosine)*unitlength < MIN_LEN)) { X fprintf(stderr, "Dashed line too short; drawing solid line\n"); X put_solidline (x, y, sx, sy, l, arrow); X return; X } X dg = (l - (n/2+1)*dl) / (double)(n/2); X if (sx) { X dx = dl+dg; X if (sx < 0) dx = -dx; X dy = dx * (double)sy / (double)sx; X } X else { X dx = 0.0; X dy = dl+dg; X if (sy < 0) dy = -dy; X } X /*** draw dashed line ***/ X fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\line(%2d,%2d){%7.3f}}\n", X x, y, dx, dy, n/2+1, sx, sy, dl); X /*** draw arrow heads ***/ X if (arrow == 1 || arrow == 2) X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); X if (arrow == -1 || arrow == 2) X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); X } X X/* X * draw a dotted line given latex slope X */ Xstatic put_dotline (x, y, sx, sy, l, arrow, val) Xint x, y, sx, sy, arrow; Xdouble l; Xdouble val; X{ X double cosine; /* cosine of line angle */ X double nd; /* number of dots fitting on line */ X int n; /* nd rounded to the nearest integer */ X double dx, dy; /* step between dashes */ X int x2, y2; X X X cosine = (sx)? (double)abs(sx) / hypot((double)sx, (double)sy): 1.0; X /*** compute step width ***/ X nd = l / (3*val*cosine); X n = rint(nd); X dx = l / (double)n; X if (sx) { X dx = l / (double)n; X if (sx < 0) dx = -dx; X dy = dx * (double)sy / (double)sx; X } X else { X dx = 0.0; X dy = l / (double)n; X if (sy < 0) dy = -dy; X } X /*** draw arrow heads ***/ X if (arrow == 1 || arrow == 2) { X /* forward arrow */ X if (sx) { X x2 = (sx >= 0)? x + round(l): x - round(l); X y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx ); X } X else { X x2 = x; X y2 = (sy >= 0)? y + round(l): y - round(l); X } X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); X n--; X } X if (arrow == -1 || arrow == 2) { X fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); X x = round(x + dx); X y = round(y + dy); X n--; X } X /*** draw dotted line ***/ X fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n", X x, y, dx, dy, n+1, dot_xoffset, dot_yoffset, dot_cmd); X } X Xvoid genlatex_spline(s) XF_spline *s; X{ X fprintf(stderr, "Can't generate spline; omitting object\n"); X } X Xvoid genlatex_ellipse(e) XF_ellipse *e; X{ X int x, y, d, dx, dy; X X if (verbose) fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n"); X X set_linewidth(e->thickness); X switch (e->style) { X case SOLID_LINE: X break; X case DASH_LINE: X fprintf(stderr, "Dashed circles and elipses not supported\n"); X break; X case DOTTED_LINE: X fprintf(stderr, "Dotted circles and elipses not supported\n"); X break; X } X X x = e->center.x; X y = e->center.y; X TRANS(x, y); X if ((e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA) X && e->radiuses.x*unitlength <= MAXCIRCLERAD) { X X d = 2 * e->radiuses.x; X if (e->area_fill == BLACK_FILL) X fprintf(tfp, "\\put(%3d,%3d){\\circle*{%d}}\n", x, y, d); X else { X fprintf(tfp, "\\put(%3d,%3d){\\circle{%d}}\n", x, y, d); X if (e->area_fill && (int)e->area_fill != DEFAULT) X fprintf(stderr, "Circle area fill not implemented\n"); X } X X } else { X dx = 2 * e->radiuses.x; X dy = 2 * e->radiuses.y; X fprintf(tfp, "\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy); X if (e->area_fill && (int)e->area_fill != DEFAULT) X fprintf(stderr, "Ellipse area fill not implemented\n"); X } X } X Xvoid genlatex_text(t) XF_text *t; X{ X int x, y; X char *tpos, *cp; X X if (verbose) fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n"); X X x = t->base_x; X y = t->base_y; X TRANS(x, y); X X switch (t->type) { X X case T_LEFT_JUSTIFIED: X case DEFAULT: X tpos = "[lb]"; X break; X X case T_CENTER_JUSTIFIED: X tpos = "[b]"; X break; X X case T_RIGHT_JUSTIFIED: X tpos = "[rb]"; X break; X X default: X fprintf(stderr, "Text incorrectly positioned\n"); X } X X /* raisebox is used to position text at baseline */ X fprintf(tfp, X "\\put(%3d,%3d){\\makebox(0,0)%s{\\raisebox{0pt}[0pt][0pt]", X x, y, tpos); X fprintf(tfp, "{\\%s%s ", TEXFONTSIZE(t->size), TEXFONT(t->font)); X X if (t->font && t->font !=DEFAULT) X X /* this loop escapes characters "$&%#_{}" */ X /* and deleted characters "~^\" */ X for(cp = t->cstring; *cp; cp++) { X if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp); X if (strchr("~^\\", *cp)) X fprintf(stderr, X "Bad character in text object '%c'\n" ,*cp); X else X (void)fputc(*cp, tfp); X } X else X fprintf(tfp, "%s", t->cstring); X X fprintf(tfp, "}}}\n"); X } X Xvoid genlatex_arc(a) XF_arc *a; X/* X * Approximates an arc by a sequence of quarter ovals. X * X * Example: X * X * Arc with center at (0,0) and radius 10 from +45 degree to +225 degree X * (arc from p1 = (7.07, 7.07) to p2 = (-7.07, -7.07) counterclockwise). X * This arc is approximated by three quarter ovals, one for each quadrant X * through which the arc goes: X * X * 1. quarter oval from p1 to the intersection of arc and y-axis, X * i.e., from (7.07, 7.07) to (0, 10) in quadrant 0 X * X * \put(0, 7.07){\oval(14.14, 5.86)[tr]} X * X * 2. quarter oval from intersection arc/y-axis to intersection arc/x-axis X * i.e., from (0, 10) to (-10, 0) in quadrant 1 X * X * \put(0, 0){\oval(20,20)[tl]} X * X * 3. quarter oval from p1 to the intersection of arc and y-axis, X * i.e., from (-10, 0) to (-7.07, -7.07) in quadrant 2 X * X * \put(-7.07, 0){\oval(5.86, 14.14)[bl]} X */ X{ X F_pos p1, p2, pq[4]; X double cx, cy; X double v1x, v1y, v2x, v2y; X double r, angle1, angle2; X int q1, q2; X int p1_arrow, p2_arrow; X static char *ad1[4] = { " 0,-1", " 1, 0", " 0, 1", "-1, 0" }; X static char *ad2[4] = { "-1, 0", " 0,-1", " 1, 0", " 0, 1" }; X X set_linewidth(a->thickness); X switch (a->style) { X case SOLID_LINE: X break; X case DASH_LINE: X fprintf(stderr, "Dashed arcs not supported\n"); X break; X case DOTTED_LINE: X fprintf(stderr, "Dotted arcs not supported\n"); X break; X } X if (a->direction == 1) { X p1 = a->point[0]; X p2 = a->point[2]; X p1_arrow = (a->back_arrow != NULL); X p2_arrow = (a->for_arrow != NULL); X } X else { X p1 = a->point[2]; X p2 = a->point[0]; X p1_arrow = (a->for_arrow != NULL); X p2_arrow = (a->back_arrow != NULL); X } X cx = a->center.x; X cy = a->center.y; X TRANS2(p1.x, p1.y, p2.x, p2.y); X TRANSD(cx, cy); X /*** compute vectors and angles from arc center to p1, p2 ***/ X v1x = (double)p1.x - cx; X v1y = (double)p1.y - cy; X v2x = (double)p2.x - cx; X v2y = (double)p2.y - cy; X angle1 = atan2(v1y, v1x) * rad2deg; X angle2 = atan2(v2y, v2x) * rad2deg; X if (angle1 < 0.0) X angle1 += 360.0; X if (angle2 < 0.0) X angle2 += 360.0; X /* compute arc radius */ X r = hypot(v1x, v1y); X /*** compute intersection of arc with x and y axis (origin at cx, cy) */ X pq[0].x = round(cx); X pq[0].y = round(cy + r); X pq[1].x = round(cx - r); X pq[1].y = round(cy); X pq[2].x = round(cx); X pq[2].y = round(cy - r); X pq[3].x = round(cx + r); X pq[3].y = round(cy); X /*** compute in which quadrants p1 and p2 are located ***/ X q1 = (int)(angle1/90.0); X q2 = (int)(angle2/90.0); X if (fabs(angle1 - 90.0*q1) > arc_tolerance X || fabs(angle2 - 90.0*q2) > arc_tolerance) X fprintf(stderr, "Approximating arc by ovals\n"); X /*** Draw arc ***/ X if (p1_arrow) X fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p1.x, p1.y, ad1[q1]); X while (q1 != q2) { X put_quarter(p1, pq[q1], q1); X p1 = pq[q1]; X q1 = (q1 + 1) % 4; X } X put_quarter(p1, p2, q1); X if (p2_arrow) X fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p2.x, p2.y, ad2[q2]); X X if (a->area_fill && (int)a->area_fill != DEFAULT) X fprintf(stderr, "Arc area fill not implemented\n"); X } X Xstatic put_quarter(p1, p2, q) XF_pos p1, p2; Xint q; X/* X * Draw quarter oval from p1 to p2 in quadrant q X */ X{ X char *opt; X int px, py, dx, dy; X X dx = 2*ABS(p1.x - p2.x); X dy = 2*ABS(p1.y - p2.y); X if (dx == 0 && dy == 0) X return; X switch (q) { X case 0: X px = MIN(p1.x, p2.x); X py = MIN(p1.y, p2.y); X opt = "tr"; X break; X case 1: X px = MAX(p1.x, p2.x); X py = MIN(p1.y, p2.y); X opt = "tl"; X break; X case 2: X px = MAX(p1.x, p2.x); X py = MAX(p1.y, p2.y); X opt = "bl"; X break; X case 3: X px = MIN(p1.x, p2.x); X py = MAX(p1.y, p2.y); X opt = "br"; X break; X } X fprintf(tfp, "\\put(%3d,%3d){\\oval(%3d,%3d)[%s]}\n", px, py, dx, dy, opt); X } X Xstruct driver dev_latex = { X genlatex_option, X genlatex_start, X genlatex_arc, X genlatex_ellipse, X genlatex_line, X genlatex_spline, X genlatex_text, X genlatex_end, X EXCLUDE_TEXT X}; END_OF_FILE if test 20332 -ne `wc -c <'transfig/fig2dev/dev/genlatex.c'`; then echo shar: \"'transfig/fig2dev/dev/genlatex.c'\" unpacked with wrong size! fi # end of 'transfig/fig2dev/dev/genlatex.c' fi if test -f 'transfig/fig2dev/dev/genps.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'transfig/fig2dev/dev/genps.c'\" else echo shar: Extracting \"'transfig/fig2dev/dev/genps.c'\" \(17407 characters\) sed "s/^X//" >'transfig/fig2dev/dev/genps.c' <<'END_OF_FILE' X/* X * genps.c: PostScript driver for fig2dev X * X*/ X#ifdef hpux X#include <sys/types.h> X#endif X#include <sys/file.h> X#include <stdio.h> X#include <math.h> X#include "pi.h" X#include <pwd.h> X#include "object.h" X#include "fig2dev.h" X Xextern x_flag; X X#define PAGE_WIDTH 612 /* points; 8.5" */ X#define PAGE_HEIGHT 792 /* points; 11" */ X#define TRUE 1 X#define FALSE 0 X#define POINT_PER_INCH 72 X#define ULIMIT_FONT_SIZE 300 X Xint coord_system; Xint show_page = 0; Xint cur_thickness; Xint center = 0; Xint landscape = 0; X Xstatic char *fontnames_x[] = { X "Times-Roman", "Times-Roman", /* default */ X "Times-Italic", /* italic */ X "Times-Bold", /* bold */ X "Times-BoldItalic", X "AvantGarde", X "AvantGarde-BookOblique", X "AvantGarde-Demi", X "AvantGarde-DemiOblique", X "Bookman-Light", X "Bookman-LightItalic", X "Bookman-Demi", X "Bookman-DemiItalic", X "Courier", X "Courier-Oblique", X "Courier-Bold", X "Courier-BoldItalic", X "Helvetica", X "Helvetica-Oblique", X "Helvetica-Bold", X "Helvetica-BoldOblique", X "Helvetica-Narrow", X "Helvetica-Narrow-Oblique", X "Helvetica-Narrow-Bold", X "Helvetica-Narrow-BoldOblique", X "NewCenturySchlbk-Roman", X "NewCenturySchlbk-Italic", X "NewCenturySchlbk-Bold", X "NewCenturySchlbk-BoldItalic", X "Palatino-Roman", X "Palatino-Italic", X "Palatino-Bold", X "Palatino-BoldItalic", X "Symbol", X "ZapfChancery-MediumItalic", X "ZapfDingbats" X }; X Xstatic char *fontnames_sv[] = { X "Times-Roman", "Times-Roman", /* default */ X "Times-Roman", /* roman */ X "Times-Bold", /* bold */ X "Times-Italic", /* italic */ X "Helvetica", /* sans serif */ X "Courier" /* typewriter */ X }; X#define MAXFONT (x_flag ? 35 : 5) X X#define PS_FONTNAMES (x_flag ? fontnames_x : fontnames_sv) X X#define PSFONT(F) \ X ((F) <= MAXFONT ? PS_FONTNAMES[(F)+1] : PS_FONTNAMES[0]) X X#define PSFONTSIZE(S) (((S) > 0 ? \ X ((S) <= ULIMIT_FONT_SIZE ? \ X (S) : \ X ULIMIT_FONT_SIZE) : \ X font_size)/mag) X X#define GRAYVAL(F) (x_flag ? ((int)(F) <= 21 ? \ X (21 - (int)(F))/20.0 : 0.0) : \ X ((int)(F) <= 5 ? ((int)(F) - 1)/4.0 : 0.0)) X X#define BEGIN_PROLOG "\ X/$F2psDict 32 dict def \ X$F2psDict begin\ X $F2psDict /mtrx matrix put\ X" X#define ELLIPSE_PS " \ X/DrawEllipse {\ X /endangle exch def\ X /startangle exch def\ X /yrad exch def\ X /xrad exch def\ X /y exch def\ X /x exch def\ X /savematrix mtrx currentmatrix def\ X x y translate xrad yrad scale 0 0 1 startangle endangle arc\ X savematrix setmatrix\ X } def\ X" X/* The original PostScript definition for adding a spline section to the X * current path uses recursive bisection. The following definition using the X * curveto operator is more efficient since it executes at compiled rather X * than interpreted code speed. The Bezier control points are 2/3 of the way X * from z1 (and z3) to z2. X * X * ---Rene Llames, 21 July 1988. X */ X#define SPLINE_PS " \ X/DrawSplineSection {\ X /y3 exch def\ X /x3 exch def\ X /y2 exch def\ X /x2 exch def\ X /y1 exch def\ X /x1 exch def\ X /xa x1 x2 x1 sub 0.666667 mul add def\ X /ya y1 y2 y1 sub 0.666667 mul add def\ X /xb x3 x2 x3 sub 0.666667 mul add def\ X /yb y3 y2 y3 sub 0.666667 mul add def\ X x1 y1 lineto\ X xa ya xb yb x3 y3 curveto\ X } def\ X" X#define END_PROLOG "\ X end\ X /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def\ X /$F2psEnd {$F2psEnteredState restore end} def\ X %%EndProlog\ X" X Xvoid genps_option(opt, optarg) Xchar opt; Xchar *optarg; X{ X int i; X X switch (opt) { X X case 'f': X for ( i = 1; i <= MAXFONT + 1; i++ ) X if ( !strcmp(optarg, PS_FONTNAMES[i]) ) break; X X if ( i > MAXFONT + 1 ) X fprintf(stderr, X "warning: non-standard font name %s\n", optarg); X X fontnames_sv[0] = fontnames_sv[1] = optarg; X fontnames_x[0] = fontnames_x[1] = optarg; X break; X X case 'c': X center = 1; X break; X X case 's': X if (font_size <= 0 || font_size > ULIMIT_FONT_SIZE) { X fprintf(stderr, X "warning: font size %d out of bounds\n", font_size); X } X break; X X case 'P': X show_page = 1; X break; X X case 'm': X case 'L': X break; X X case 'l': X landscape = 1; X break; X X default: X put_msg(Err_badarg, opt, "ps"); X exit(1); X break; X } X} X Xvoid genps_start(objects) XF_compound *objects; X{ X char host[256]; X struct passwd *who; X long when; X extern char *ctime(), *strcpy(); X extern long time(); X double tx, scalex, scaley; X double dx, dy, origx, origy; X int itmp; X X coord_system = objects->nwcorner.y; X scalex = scaley = mag * POINT_PER_INCH / (double)objects->nwcorner.x; X /* convert to point unit */ X llx = (int)ceil(llx * scalex); lly = (int)ceil(lly * scaley); X urx = (int)ceil(urx * scalex); ury = (int)ceil(ury * scaley); X if (landscape) /* swap x,y */ X { X itmp = llx; llx = lly; lly = itmp; X itmp = urx; urx = ury; ury = itmp; X } X if (center) { X dx = urx - llx; X dy = ury - lly; X tx = (PAGE_WIDTH - dx) / 2.0; X if (landscape) X origx=0; X else X origx = tx - llx; X urx = (llx=tx) + dx; X ury = (PAGE_HEIGHT + dy) / 2.0; X if (coord_system == 2) X origy = ury + lly; X else X origy = ury - dy - lly; X lly = ury - dy; X } X else { X origx = 0.0; X origy = PAGE_HEIGHT; X } X X if (coord_system == 2) scaley = -scaley; X X fprintf(tfp, "%%!\n"); /* PostScript magic strings */ X who = getpwuid(getuid()); X if (-1 == gethostname(host, sizeof(host))) X (void)strcpy(host, "unknown-host!?!?"); X (void) time(&when); X fprintf(tfp, "%%%%Title: %s\n", ((from) ? from : "stdin")); X fprintf(tfp, "%%%%Creator: %s\n", prog); X fprintf(tfp, "%%%%CreationDate: %s", ctime(&when)); X fprintf(tfp, "%%%%For: %s@%s (%s)\n", X who->pw_name, host, who->pw_gecos); X fprintf(tfp, "%%%%Pages: %d\n", show_page); X X if (show_page) X fprintf(tfp, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); X else X fprintf(tfp, "%%%%BoundingBox: 0 0 %d %d\n", urx-llx, ury-lly); X X fprintf(tfp, "%%%%EndComments\n"); X fprintf(tfp, "%s\n", BEGIN_PROLOG); X if (ellipse_exist(objects)) fprintf(tfp, "%s\n", ELLIPSE_PS); X if (normal_spline_exist(objects)) fprintf(tfp, "%s\n", SPLINE_PS); X fprintf(tfp, "%s\n", END_PROLOG); X fprintf(tfp, "$F2psBegin\n"); X fprintf(tfp, "1 setlinecap 1 setlinejoin\n"); X X if (!show_page) fprintf(tfp, "%d %d translate\n", -llx, lly); X fprintf(tfp, "%f %f translate %.3f %.3f scale\n", X origx, (show_page ? origy : ury-lly), scalex, scaley); X X /* **** Land scape mode ****/ X if (landscape) X fprintf(tfp, "%d 0 translate 90 rotate\n", PAGE_WIDTH); X X /* if ((t = PAGE_HEIGHT / SCALE / WIDTH) < 1.0) X * fprintf(tfp, "%f %f scale\n", t, t); X * } X *else if ((t = PAGE_HEIGHT / SCALE / HEIGHT) < 1.0) X * fprintf(tfp, "%f %f scale\n", t, t); X */ X X } X Xvoid genps_end() X{ X if (show_page) fprintf(tfp, "showpage\n"); X fprintf(tfp, "$F2psEnd\n"); X } X Xstatic set_style(s, v) Xint s; Xdouble v; X{ X if (s == DASH_LINE) { X if (v > 0.0) fprintf(tfp, "\t[%f] 0 setdash\n", v); X } X else if (s == DOTTED_LINE) { X if (v > 0.0) fprintf(tfp, "\t[1 %f] 0 setdash\n", v); X } X } X Xstatic reset_style(s, v) Xint s; Xdouble v; X{ X if (s == DASH_LINE) { X if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n"); X } X else if (s == DOTTED_LINE) { X if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n"); X } X } X Xstatic set_linewidth(w) Xint w; X{ X extern int cur_thickness; X X if (w != cur_thickness) { X cur_thickness = w; X fprintf(tfp, "%.3f setlinewidth\n", 1.0 * cur_thickness); X } X } X Xvoid genps_line(l) XF_line *l; X{ X F_point *p, *q; X /* JNT */ X int radius; X X set_linewidth(l->thickness); X radius = l->radius; /* radius of rounded-corner boxes */ X p = l->points; X q = p->next; X if (q == NULL) { /* A single point line */ X fprintf(tfp, "newpath %d %d moveto %d %d lineto stroke\n", X p->x, p->y, p->x, p->y); X return; X } X if (l->back_arrow) X draw_arrow_head((double)q->x, (double)q->y, (double)p->x, X (double)p->y, l->back_arrow->ht, l->back_arrow->wid); X set_style(l->style, l->style_val); X fprintf(tfp, "%% Polyline\n"); X /* JNT */ X if (l->type == T_ARC_BOX) X { X register int xmin,xmax,ymin,ymax; X X xmin = xmax = p->x; X ymin = ymax = p->y; X while (p->next != NULL) /* find lower left and upper right corne Xrs */ X { X p=p->next; X if (xmin > p->x) X xmin = p->x; X else if (xmax < p->x) X xmax = p->x; X if (ymin > p->y) X ymin = p->y; X else if (ymax < p->y) X ymax = p->y; X } X fprintf(tfp, "newpath %d %d moveto",xmin+radius, ymin); X fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", X xmin, ymin, xmin, ymax-radius, radius); X fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro Xugh bl to br */ X xmin, ymax, xmax-radius, ymax, radius); X fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro Xugh br to tr */ X xmax, ymax, xmax, ymin+radius, radius); X fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro Xugh tr to tl */ X xmax, ymin, xmin+radius, ymin, radius); X } X else X { X fprintf(tfp, "newpath %d %d moveto", p->x, p->y); X while (q->next != NULL) { X p = q; X q = q->next; X fprintf(tfp, " %d %d lineto", p->x, p->y); X } X } X if (l->type == T_POLYLINE) X fprintf(tfp, " %d %d lineto stroke\n", q->x, q->y); X else X fprintf(tfp, " closepath "); X if (l->area_fill && (int)l->area_fill != DEFAULT) X fprintf(tfp, "gsave %6.3f setgray fill grestore ", X GRAYVAL(l->area_fill)); X fprintf(tfp, "stroke\n"); X reset_style(l->style, l->style_val); X if (l->for_arrow) X draw_arrow_head((double)p->x, (double)p->y, (double)q->x, X (double)q->y, l->for_arrow->ht, l->for_arrow->wid); X } X Xvoid genps_spline(s) XF_spline *s; X{ X if (int_spline(s)) X genps_itp_spline(s); X else X genps_ctl_spline(s); X } X Xgenps_itp_spline(s) XF_spline *s; X{ X F_point *p, *q; X F_control *a, *b; X X set_linewidth(s->thickness); X a = s->controls; X p = s->points; X if (s->back_arrow) X draw_arrow_head(a->rx, a->ry, (double)p->x, X (double)p->y, s->back_arrow->ht, s->back_arrow->wid); X X set_style(s->style, s->style_val); X fprintf(tfp, "%% Interpolated spline\n"); X fprintf(tfp, "newpath %d %d moveto\n", p->x, p->y); X for (q = p->next; q != NULL; p = q, q = q->next) { X b = a->next; X fprintf(tfp, "\t%.3f %.3f %.3f %.3f %d %d curveto\n", X a->rx, a->ry, b->lx, b->ly, q->x, q->y); X a = b; X b = b->next; X } X if (closed_spline(s)) fprintf(tfp, " closepath "); X if (s->area_fill && (int)s->area_fill != DEFAULT) X fprintf(tfp, "gsave %6.3f setgray fill grestore ", X GRAYVAL(s->area_fill)); X fprintf(tfp, " stroke\n"); X reset_style(s->style, s->style_val); X X if (s->for_arrow) X draw_arrow_head(a->lx, a->ly, (double)p->x, X (double)p->y, s->for_arrow->ht, s->for_arrow->wid); X } X Xgenps_ctl_spline(s) XF_spline *s; X{ X double a, b, c, d, x1, y1, x2, y2, x3, y3; X F_point *p, *q; X X /* X if (first) { X first = FALSE; X fprintf(tfp, "%s\n", SPLINE_PS); X } X */ X X p = s->points; X x1 = p->x; y1 = p->y; X p = p->next; X c = p->x; d = p->y; X set_linewidth(s->thickness); X x3 = a = (x1 + c) / 2; X y3 = b = (y1 + d) / 2; X if (s->back_arrow) { X draw_arrow_head(c, d, x1, y1, s->back_arrow->ht, s->back_arrow->wid); X } X set_style(s->style, s->style_val); X if (! closed_spline(s)) { X fprintf(tfp, "%% Open spline\n"); X fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto\n", X x1, y1, x3, y3); X } X else { X fprintf(tfp, "%% Closed spline\n"); X fprintf(tfp, "newpath %.3f %.3f moveto\n", a, b); X } X for (q = p->next; q != NULL; p = q, q = q->next) { X x1 = x3; y1 = y3; X x2 = c; y2 = d; X c = q->x; d = q->y; X x3 = (x2 + c) / 2; X y3 = (y2 + d) / 2; X fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection\n", X x1, y1, x2, y2, x3, y3); X } X /* X * At this point, (x2,y2) and (c,d) are the position of the X * next-to-last and last point respectively, in the point list X */ X if (closed_spline(s)) { X fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection closepath ", X x3, y3, c, d, a, b); X } X else { X fprintf(tfp, "\t%.3f %.3f lineto ", c, d); X } X if (s->area_fill && (int)s->area_fill != DEFAULT) X fprintf(tfp, "gsave %6.3f setgray fill grestore ", X GRAYVAL(s->area_fill)); X fprintf(tfp, "stroke\n"); X reset_style(s->style, s->style_val); X if (s->for_arrow) { X draw_arrow_head(x2, y2, c, d, s->for_arrow->ht, X s->for_arrow->wid); X } X } X Xvoid genps_ellipse(e) XF_ellipse *e; X{ X set_linewidth(e->thickness); X set_style(e->style, e->style_val); X if (e->angle == 0) X { X fprintf(tfp, "%% Ellipse\n"); X fprintf(tfp, "newpath %d %d %d %d 0 360 DrawEllipse ", X e->center.x, e->center.y, e->radiuses.x, e->radiuses.y); X } X else X { X fprintf(tfp, "%% Rotated Ellipse\n"); X fprintf(tfp, "gsave\n"); X fprintf(tfp, "%d %d translate\n",e->center.x, e->center.y); X fprintf(tfp, "%6.3f rotate\n",e->angle*180/M_PI); X fprintf(tfp, "newpath 0 0 %d %d 0 360 DrawEllipse ", X e->radiuses.x, e->radiuses.y); X } X if (e->area_fill && (int)e->area_fill != DEFAULT) X fprintf(tfp, "gsave %6.3f setgray fill grestore ", X GRAYVAL(e->area_fill)); X fprintf(tfp, "stroke\n"); X if (e->angle != 0) X fprintf(tfp, "grestore\n"); X reset_style(e->style, e->style_val); X } X X#define TEXT_PS "\ X/%s findfont %.3f scalefont setfont\n\ X" Xvoid genps_text(t) XF_text *t; X{ X char *cp; X X fprintf(tfp, TEXT_PS, PSFONT(t->font), PSFONTSIZE(t->size)); X X fprintf(tfp, "%d %d moveto \n", t->base_x, t->base_y); X if (coord_system == 2) fprintf(tfp, "1 -1 scale\n"); X X /* this loop escapes characters '(', ')', and '\' */ X fputc('(', tfp); X for(cp = t->cstring; *cp; cp++) { X if (strchr("()\\", *cp)) fputc('\\', tfp); X fputc(*cp, tfp); X } X fputc(')', tfp); X X if ((t->type == T_CENTER_JUSTIFIED) || (t->type == T_RIGHT_JUSTIFIED)){ X X fprintf(tfp, "dup stringwidth pop "); X if (t->type == T_CENTER_JUSTIFIED) fprintf(tfp, "2 div "); X fprintf(tfp, "neg 0 rmoveto "); X } X X else if ((t->type != T_LEFT_JUSTIFIED) && (t->type != DEFAULT)) X fprintf(stderr, "Text incorrectly positioned\n"); X X fprintf(tfp, " gsave %6.3f rotate show grestore ", t->angle*180/M_PI); X if (coord_system == 2) fprintf(tfp, "1 -1 scale\n"); X X } X Xvoid genps_arc(a) XF_arc *a; X{ X double angle1, angle2, dx, dy, radius, x, y; X double cx, cy, sx, sy, ex, ey; X int direction; X X cx = a->center.x; cy = a->center.y; X sx = a->point[0].x; sy = a->point[0].y; X ex = a->point[2].x; ey = a->point[2].y; X X if (coord_system == 2) X direction = !a->direction; X else X direction = a->direction; X set_linewidth(a->thickness); X if (a->for_arrow) { X arc_tangent(cx, cy, ex, ey, direction, &x, &y); X draw_arrow_head(x, y, ex, ey, a->for_arrow->ht, a->for_arrow->wid); X } X if (a->back_arrow) { X arc_tangent(cx, cy, sx, sy, !direction, &x, &y); X draw_arrow_head(x, y, sx, sy, a->back_arrow->ht, a->back_arrow->wid); X } X dx = cx - sx; X dy = cy - sy; X radius = hypot(dx, dy); X angle1 = atan2(sy-cy, sx-cx) * 180 / M_PI; X angle2 = atan2(ey-cy, ex-cx) * 180 / M_PI; X /* direction = 1 -> Counterclockwise */ X set_style(a->style, a->style_val); X fprintf(tfp, "newpath %.3f %.3f %.3f %.3f %.3f %s\n", X cx, cy, radius, angle1, angle2, X ((direction == 1) ? "arc" : "arcn")); X if (a->area_fill && (int)a->area_fill != DEFAULT) X fprintf(tfp, "gsave %6.3f setgray fill grestore ", X GRAYVAL(a->area_fill)); X fprintf(tfp, "stroke\n"); X reset_style(a->style, a->style_val); X } X Xstatic arc_tangent(x1, y1, x2, y2, direction, x, y) Xdouble x1, y1, x2, y2, *x, *y; Xint direction; X{ X if (direction) { /* counter clockwise */ X *x = x2 + (y2 - y1); X *y = y2 - (x2 - x1); X } X else { X *x = x2 - (y2 - y1); X *y = y2 + (x2 - x1); X } X } X X/* draw arrow heading from (x1, y1) to (x2, y2) */ X Xstatic draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid) Xdouble x1, y1, x2, y2, arrowht, arrowwid; X{ X double x, y, xb, yb, dx, dy, l, sina, cosa; X double xc, yc, xd, yd; X X dx = x2 - x1; dy = y1 - y2; X l = hypot(dx, dy); X sina = dy / l; cosa = dx / l; X xb = x2*cosa - y2*sina; X yb = x2*sina + y2*cosa; X x = xb - arrowht; X y = yb - arrowwid / 2; X xc = x*cosa + y*sina; X yc = -x*sina + y*cosa; X y = yb + arrowwid / 2; X xd = x*cosa + y*sina; X yd = -x*sina + y*cosa; X fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto %.3f %.3f lineto stroke\n", X xc, yc, x2, y2, xd, yd); X } X Xstatic ellipse_exist(ob) XF_compound *ob; X{ X F_compound *c; X X if (NULL != ob->ellipses) return(1); X X for (c = ob->compounds; c != NULL; c = c->next) { X if (ellipse_exist(c)) return(1); X } X X return(0); X } X Xstatic normal_spline_exist(ob) XF_compound *ob; X{ X F_spline *s; X F_compound *c; X X for (s = ob->splines; s != NULL; s = s->next) { X if (normal_spline(s)) return(1); X } X X for (c = ob->compounds; c != NULL; c = c->next) { X if (normal_spline_exist(c)) return(1); X } X X return(0); X } X Xstruct driver dev_ps = { X genps_option, X genps_start, X genps_arc, X genps_ellipse, X genps_line, X genps_spline, X genps_text, X genps_end, X INCLUDE_TEXT X}; END_OF_FILE if test 17407 -ne `wc -c <'transfig/fig2dev/dev/genps.c'`; then echo shar: \"'transfig/fig2dev/dev/genps.c'\" unpacked with wrong size! fi # end of 'transfig/fig2dev/dev/genps.c' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.