|
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 g
Length: 21504 (0x5400) Types: TextFile Names: »gentpic.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z« └─⟦c58930e5c⟧ └─⟦this⟧ »TeX3.14/TeXgraphics/transfig/fig2dev/dev/gentpic.c«
/* * gentpic : TPIC driver for fig2dev * * Author: Conrad Kwok, UC Davis, 12/88 * Modified: Richard Auletta, George Mason Univ., 6/21/89 * Added code comments are marked with "rja". * Added: Support for native pic arrowheads. * Added: Support for arrowheads at both ends of lines, arc, splines. * Modified: Modified from pic to tpic. Baron Grey, UCLA. 10/2/90. * * This driver supports TeX's virtual font mechanism. Any Fig * font whose ordinal number is greater than 6 is treated as * a TeX virtual PostScript font. Virtual PostScript font * names are defined in tpicfonts.h (you should define * corresponding names in Fig in file change.c). Customize to * suit your virtual font availability or your name preferences. * * There are no restrictions on font sizes in this driver, but * keep in mind that TeX only supports fonts up to 2048 points! * Since PostScript fonts are scaleable, virtual PS fonts can have * any point size within the limits imposed by TeX or by your * PostScript interpreter. If you are using * standard predefined LaTeX fonts (assumed to be the first * 6 positions in Fig's ordinal font numbering scheme), font * sizes are mapped into the nearest valid normally-available * LaTeX font sizes -- look at tpicfonts.h to see how this is * done; you can modify it for fonts at your site. * * Additional features of this driver are: * 1) Support for all Fig features except text at nonzero * angles. (In fact, any limitations of this driver are * actually tpic limitations.) * 2) Boxes with rounded corners are supported in two ways. * If (when) tpic is extended to use the "radius" attribute * with a "box" specification, the driver will generate the * appropriate box specification. Otherwise, it creates * rounded-corner boxes from line and arc segments using * existing tpic primitives. In the former case, rounded- * corner boxes can be shaded; in the latter, they can't. * Define TPIC_ARC_BOX for the first case (the default); * undefine it otherwise. * 3) Supports Fig's ability to texture (shade) objects. * Bitmapped PostScript texture patterns are supported; * they are defined in "tpicfonts.h". The tpic ".tx" * primitive is used for this. Your dvi-to-PostScript * driver must be adapted to support them. * 4) If an object's line "thickness" is 0, it is given tpic's * `invis' attribute. That is, tpic will treat it as an * invisible object in the normal tpic sense. * 5) This driver supports tpic 2.0. It will work with tpic 1.0, * but some object attributes will not be available. * 6) The default line thickness is 8 milli inches (in tpic * units). This corresponds to 1 pixel width in Fig. The * formula is: line_thickness = Fig_line_thickness * * default_tpic_line_thickness. * 7) The default font size is (assumed to be) 10 points! */ #include <stdio.h> #include <math.h> #include "object.h" #include "fig2dev.h" #include "tpicfonts.h" /* * Define TPIC_ARC_BOX if your tpic supports rounded-corner boxes * via a "radius" attribute of a box specification. */ #define TPIC_ARC_BOX #define TOP 10.5 /* top of page is 10.5 inch */ static double ppi; static int CONV = 0; static int line_width = 8; /* milli-inches */ static int vfont = 0; /* true if using a virtual TeX font */ void gentpic_ctl_spline(), gentpic_itp_spline(); void gentpic_open_spline(), gentpic_closed_spline(); void gentpic_spline(), gentpic_ellipse(), gentpic_text(); void gentpic_arc(), gentpic_line(), newline(); void gentpic_option(opt, optarg) char opt, *optarg; { switch (opt) { case 'f': /* set default text font */ { int i; for ( i = 1; i <= MAX_TPICFONT; i++ ) if ( !strcmp(optarg, texfontnames[i]) ) break; if ( i > MAX_FONT + 1 ) vfont = 1; /* assume a virtual font */ } texfontnames[0] = optarg; break; case 's': case 'm': case 'L': break; default: put_msg(Err_badarg, opt, "tpic"); exit(1); } } static double convy(a) double a; { return((double)(CONV ? TOP-a : a)); } void gentpic_start(objects) F_compound *objects; { int coord_system; ppi = objects->nwcorner.x/mag; coord_system = objects->nwcorner.y; if (coord_system == 2) CONV = 1; fprintf(tfp, ".PS\n"); /* PIC preamble */ } void gentpic_end() { fprintf(tfp, ".PE\n"); /* PIC ending */ } /* * tpic's line thickness is given in milli-inches with a default of 8 * milli-inches. We simply multiply this default with the Fig pixel width. */ static set_linewidth(w) int w; { static int cur_thickness = -1; if (w == 0) return; if (w != cur_thickness) { cur_thickness = w; fprintf(tfp, ".ps %d\n", cur_thickness * line_width); } } static set_style(s, v) int s; float v; { static float style_val = -1; if (s == DASH_LINE || s == DOTTED_LINE) { if (v == style_val || v == 0.0) return; style_val = v; fprintf(tfp, "dashwid = %.3fi\n", style_val/ppi); } } static set_baseline(b) int b; { static int cur_baseline = -1; if (b != cur_baseline) { fprintf(tfp, ".baseline %d\n", b); cur_baseline = b; } } static set_texture(cur_texture) int cur_texture; { /* * This applies only to bitmapped texture patterns defined in * tpicfonts.h. See set_fill() below for normal shading. */ if (cur_texture <= BLACK_FILL || cur_texture > MAXPATTERNS + BLACK_FILL) return; fprintf(tfp, ".tx 16 %s\n", texture_patterns[cur_texture - BLACK_FILL - 1]); } /* * Set the shade for filling an object. Your dvi-to-postscript driver must * distinguish between a "shaded" attribute with or without a parameter. * If there is no parameter, then it should do a bitmap texture fill; * otherwise, it should do a normal gray-scale fill. Note that the gray- * scale fill parameter is wired for fig2.X (the constant 0.05). */ static set_fill(cur_fill) int cur_fill; { if(cur_fill < WHITE_FILL || cur_fill > BLACK_FILL + MAXPATTERNS) return; switch(cur_fill) { case BLACK_FILL: fprintf(tfp, " black"); break; case WHITE_FILL: fprintf(tfp, " white"); break; default: if (cur_fill > BLACK_FILL) fprintf (tfp, " shaded"); else fprintf(tfp, " shaded %0.3f", (cur_fill-1)*0.05); break; } } #ifdef TPIC_ARC_BOX void gentpic_line(l) F_line *l; { F_point *p, *q; int llx, lly, urx, ury; set_linewidth(l->thickness); set_style(l->style, l->style_val); set_texture(l->area_fill); p = l->points; q = p->next; if (q == NULL) { /* A single point line */ fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f", p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi)); newline(); return; } if (l->type == T_BOX || l->type == T_ARC_BOX) { llx = urx = p->x; lly = ury = p->y; while (q != NULL) { p = q; if (p->x < llx) { llx = p->x; } else if (p->x > urx) { urx = p->x; } if (p->y < lly) { lly = p->y; } else if (p->y > ury) { ury = p->y; } q = q->next; } fprintf(tfp, "box height %.3f width %.3f", (ury-lly)/ppi, (urx-llx)/ppi); switch(l->style) { case SOLID_LINE: break; case DASH_LINE: fprintf(tfp, " dashed"); break; case DOTTED_LINE: fprintf(tfp, " dotted"); break; default: put_msg("Program error! No other line styles allowed.\n"); return; } if (l->thickness == 0) fprintf(tfp, " invis"); fprintf(tfp, " radius %.3f", l->radius/ppi); set_fill(l->area_fill); fprintf(tfp, " with .nw at %.3f,%.3f", llx/ppi, convy(lly/ppi)); newline(); return; } if (l->style == DASH_LINE && l->style_val > 0.0) fprintf(tfp, "line dashed"); else if (l->style == DOTTED_LINE && l->style_val > 0.0) fprintf(tfp, "line dotted"); else fprintf(tfp, "line"); /*rja: Place arrowheads or lack there of on the line*/ if ((l->for_arrow) && (l->back_arrow)) fprintf(tfp, " <-> from"); else if (l->back_arrow) fprintf(tfp, " <- from"); else if (l->for_arrow) fprintf(tfp, " -> from"); else fprintf(tfp, " from "); fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi)); while (q->next != NULL) { p = q; q = q->next; fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi)); } fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi)); if (l->thickness == 0) fprintf(tfp, " invis"); if (l->type == T_POLYGON) set_fill(l->area_fill); newline(); } #else void gentpic_line(l) F_line *l; { F_point *p, *q; int radius = l->radius; char attr[80]; attr[0] = '\0'; set_linewidth(l->thickness); set_style(l->style, l->style_val); set_texture(l->area_fill); p = l->points; q = p->next; if (q == NULL) { /* A single point line */ fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f", p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi)); newline(); return; } if (l->style == DASH_LINE && l->style_val > 0.0) strcat(attr, "dashed"); else if (l->style == DOTTED_LINE && l->style_val > 0.0) strcat(attr, "dotted"); if (l->thickness == 0) strcat(attr, " invis"); if (radius > 0) { /* T_ARC_BOX */ register int xmin,xmax,ymin,ymax; xmin = xmax = p->x; ymin = ymax = p->y; while (p->next != NULL) { /* find lower left and upper right corners */ p=p->next; if (xmin > p->x) xmin = p->x; else if (xmax < p->x) xmax = p->x; if (ymin > p->y) ymin = p->y; else if (ymax < p->y) ymax = p->y; } fprintf(tfp, "line %s from %.3f,%.3f to %.3f, %.3f\n", attr, (xmin+radius)/ppi, convy(ymin/ppi), (xmax-radius)/ppi, convy(ymin/ppi)); fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n", attr, (xmax-radius)/ppi, convy(ymin/ppi), (xmax/ppi), convy((ymin+radius)/ppi), radius/ppi); fprintf(tfp, "line %s from %.3f,%.3f to %.3f, %.3f\n", attr, xmax/ppi, convy((ymin+radius)/ppi), xmax/ppi, convy((ymax-radius)/ppi)); fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n", attr, xmax/ppi, convy((ymax-radius)/ppi), (xmax-radius)/ppi, convy(ymax/ppi), radius/ppi); fprintf(tfp, "line %s from %.3f,%.3f to %.3f, %.3f\n", attr, (xmax-radius)/ppi, convy(ymax/ppi), (xmin+radius)/ppi, convy(ymax/ppi)); fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n", attr, (xmin+radius)/ppi, convy(ymax/ppi), xmin/ppi, convy((ymax-radius)/ppi), radius/ppi); fprintf(tfp, "line %s from %.3f,%.3f to %.3f, %.3f\n", attr, xmin/ppi, convy((ymax-radius)/ppi), xmin/ppi, convy((ymin+radius)/ppi)); fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f", attr, xmin/ppi, convy((ymin+radius)/ppi), (xmin+radius)/ppi, convy(ymin/ppi), radius/ppi); } else { /*rja: Place arrowheads or lack there of on the line*/ fprintf(tfp, "line %s", attr); if ((l->for_arrow) && (l->back_arrow)) fprintf(tfp, " <-> from"); else if (l->back_arrow) fprintf(tfp, " <- from"); else if (l->for_arrow) fprintf(tfp, " -> from"); else fprintf(tfp, " from "); fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi)); while (q->next != NULL) { p = q; q = q->next; fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi)); } fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi)); } if (l->type != T_POLYLINE) set_fill(l->area_fill); newline(); } #endif void gentpic_spline(s) F_spline *s; { if (int_spline(s)) gentpic_itp_spline(s); else gentpic_ctl_spline(s); } void gentpic_ctl_spline(s) F_spline *s; { if (closed_spline(s)) gentpic_closed_spline(s); else gentpic_open_spline(s); } void gentpic_open_spline(s) F_spline *s; { double x1, y1, x2, y2; F_point *p, *q; p = s->points; x1 = p->x/ppi; y1 = convy(p->y/ppi); p = p->next; x2 = p->x/ppi; y2 = convy(p->y/ppi); set_style(s->style, s->style_val); set_linewidth(s->thickness); if (p->next == NULL) { fprintf(tfp, "line"); if (s->style == DASH_LINE && s->style_val > 0.0) fprintf(tfp, " dashed"); else if (s->style == DOTTED_LINE && s->style_val > 0.0) fprintf(tfp, " dotted"); /*rja: Attach arrowhead as required */ if ((s->for_arrow) && (s->back_arrow)) fprintf(tfp, " <->"); else if (s->back_arrow) fprintf(tfp, " <-"); else if (s->for_arrow) fprintf(tfp, " ->"); fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2); newline(); return; } fprintf(tfp, "spline"); if (s->style == DASH_LINE && s->style_val > 0.0) fprintf(tfp, " dashed"); else if (s->style == DOTTED_LINE && s->style_val > 0.0) fprintf(tfp, " dotted"); /*rja: Attach arrowhead as required */ if ((s->for_arrow) && (s->back_arrow)) fprintf(tfp, " <->"); else if (s->back_arrow) fprintf(tfp, " <-"); else if (s->for_arrow) fprintf(tfp, " ->"); fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2); for (q = p->next; q->next != NULL; p = q, q = q->next) fprintf(tfp, " to %.3f,%.3f", q->x/ppi, convy(q->y/ppi)); fprintf(tfp, " to %.3f,%.3f", (x2=q->x/ppi), (y2=convy(q->y/ppi))); newline(); } void gentpic_ellipse(e) F_ellipse *e; { set_linewidth(e->thickness); set_texture(e->area_fill); set_style(e->style, e->style_val); fprintf(tfp, "ellipse"); if (e->style == DASH_LINE && e->style_val > 0.0) fprintf(tfp, " dashed"); else if (e->style == DOTTED_LINE && e->style_val > 0.0) fprintf(tfp, " dotted"); fprintf(tfp, " at %.3f,%.3f wid %.3f ht %.3f", e->center.x/ppi, convy(e->center.y/ppi), 2 * e->radiuses.x/ppi, 2 * e->radiuses.y/ppi); if (e->thickness == 0) fprintf(tfp, " invis"); set_fill(e->area_fill); newline(); } /* Text is displayed on the screen with the base line starting at (base_x, base_y); some characters extend below this line. Pic displays the center of the height of text at the given coordinate. HT_OFFSET is used to compensate all the above factors so text position in fig should be at the same position on the screen as on the hard copy. THIS IS A HACK. tpic should be modified to put text with its baseline at the given coordinates as does fig -- Baron. */ #define HT_OFFSET (0.25 / 72.0) void gentpic_text(t) F_text *t; { float y; char *tpos; int virtual_font = 0; /* * If a font size is specified and the current text font size * is the default, then use the specified font size. */ if (t->size == 0 && font_size) t->size = font_size; /* * tpic is informed of the baseline spacing here. Not particularly * useful in this version of the driver. */ set_baseline(t->size); unpsfont(t); if (t->font > MAX_FONT+1 || vfont) virtual_font = 1; /* must be a virtual font */ if (virtual_font) /* * NOTE. Virtual fonts are defined dynamically using * TeX's font definition machinery. */ fprintf(tfp, "\"\\font\\fig%s=%s at %dpt \\fig%s ", TEXFONT(t->font), TEXFONT(t->font), t->size, TEXFONT(t->font)); else #ifdef FST fprintf(tfp, "\"\\%spt\\%s ", TEXFONTMAG(t), TEXFONT(t->font)); #else fprintf(tfp, "\"\\%s%s ", TEXFONTMAG(t), TEXFONT(t->font)); #endif switch (t->type) { case T_LEFT_JUSTIFIED: case DEFAULT: tpos = "ljust"; break; case T_CENTER_JUSTIFIED: tpos = ""; break; case T_RIGHT_JUSTIFIED: tpos = "rjust"; break; default: fprintf(stderr, "unknown text position type\n"); exit(1); } y = convy(t->base_y/ppi) + (TEXFONTMAGINT(t) * HT_OFFSET); fprintf(tfp, "%s\" at %.3f,%.3f %s", t->cstring, t->base_x/ppi, y, tpos); newline(); } void gentpic_arc(a) F_arc *a; { double x, y; double cx, cy, sx, sy, ex, ey; cx = a->center.x/ppi; cy = convy(a->center.y/ppi); sx = a->point[0].x/ppi; sy = convy(a->point[0].y/ppi); ex = a->point[2].x/ppi; ey = convy(a->point[2].y/ppi); set_texture(a->area_fill); set_linewidth(a->thickness); set_style(a->style, a->style_val); fprintf(tfp, "arc"); if (a->style == DASH_LINE && a->style_val > 0.0) fprintf(tfp, " dashed"); else if (a->style == DOTTED_LINE && a->style_val > 0.0) fprintf(tfp, " dotted"); /*rja: Attach arrowhead as required */ if ((a->for_arrow) && (a->back_arrow)) fprintf(tfp, " <->"); else if (a->back_arrow) fprintf(tfp, " <-"); else if (a->for_arrow) fprintf(tfp, " ->"); if (a->direction) fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f", cx, cy, sx, sy, ex, ey); else fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f cw", cx, cy, sx, sy, ex, ey); if (a->thickness == 0) fprintf(tfp, " invis"); set_fill(a->area_fill); newline(); } static arc_tangent(x1, y1, x2, y2, direction, x, y) double x1, y1, x2, y2, *x, *y; int direction; { if (direction) { /* counter clockwise */ *x = x2 + (y2 - y1); *y = y2 - (x2 - x1); } else { *x = x2 - (y2 - y1); *y = y2 + (x2 - x1); } } #define THRESHOLD .05 /* inch */ static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4) double a1, b1, a2, b2, a3, b3, a4, b4; { double x1, y1, x4, y4; double xmid, ymid; x1 = a1; y1 = b1; x4 = a4; y4 = b4; xmid = (a2 + a3) / 2; ymid = (b2 + b3) / 2; if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD) { fprintf(tfp, "\tto %.3f,%.3f\\\n", xmid, ymid); } else { quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2), ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid); } if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) { fprintf(tfp, "\tto %.3f,%.3f\\\n", x4, y4); } else { quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4), ((a3+x4)/2), ((b3+y4)/2), x4, y4); } } void gentpic_closed_spline(s) F_spline *s; { F_point *p; double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; double x1, y1, x2, y2; p = s->points; x1 = p->x/ppi; y1 = convy(p->y/ppi); p = p->next; x2 = p->x/ppi; y2 = convy(p->y/ppi); cx1 = (x1 + x2) / 2; cy1 = (y1 + y2) / 2; cx2 = (x1 + 3 * x2) / 4; cy2 = (y1 + 3 * y2) / 4; set_linewidth(s->thickness); set_texture(s->area_fill); /* probably won't work! */ set_style(s->style, s->style_val); for (p = p->next; p != NULL; p = p->next) { fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1); x1 = x2; y1 = y2; x2 = p->x/ppi; y2 = convy(p->y/ppi); cx3 = (3 * x1 + x2) / 4; cy3 = (3 * y1 + y2) / 4; cx4 = (x1 + x2) / 2; cy4 = (y1 + y2) / 2; quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); newline(); /* fprintf(tfp, "\n"); */ cx1 = cx4; cy1 = cy4; cx2 = (x1 + 3 * x2) / 4; cy2 = (y1 + 3 * y2) / 4; } x1 = x2; y1 = y2; p = s->points->next; x2 = p->x/ppi; y2 = convy(p->y/ppi); cx3 = (3 * x1 + x2) / 4; cy3 = (3 * y1 + y2) / 4; cx4 = (x1 + x2) / 2; cy4 = (y1 + y2) / 2; fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1); quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); if (s->thickness == 0) fprintf(tfp, " invis"); set_fill(s->area_fill); newline(); /* fprintf(tfp, "\n"); */ } void gentpic_itp_spline(s) F_spline *s; { F_point *p1, *p2, *pfirst; F_control *cp1, *cp2; double x1, x2, y1, y2; set_style(s->style, s->style_val); set_texture(s->area_fill); /* probably won't work! */ set_linewidth(s->thickness); p1 = s->points; cp1 = s->controls; cp2 = cp1->next; x2 = p1->x/ppi; y2 = convy(p1->y/ppi); pfirst = p1->next;/*save first to test in loop*/ for (p2 = p1->next, cp2 = cp1->next; p2 != NULL; p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) { fprintf(tfp, "line "); /*rja: Attach arrowhead as required */ if ((s->back_arrow) && (p2 == pfirst)) fprintf(tfp, " <- "); else if ((s->for_arrow) && (p2->next == NULL)) fprintf(tfp, " -> "); fprintf(tfp, " from %.3f,%.3f ", x2, y2); x1 = x2; y1 = y2; x2 = p2->x/ppi; y2 = convy(p2->y/ppi); bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi), (double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2); /* fprintf(tfp, "\n"); */ newline(); } } static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3) double a0, b0, a1, b1, a2, b2, a3, b3; { double x0, y0, x3, y3; double sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid; x0 = a0; y0 = b0; x3 = a3; y3 = b3; if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD) { fprintf(tfp, "\tto %.3f,%.3f\\\n", x3, y3); } else { tx = (a1 + a2) / 2; ty = (b1 + b2) / 2; sx1 = (x0 + a1) / 2; sy1 = (y0 + b1) / 2; sx2 = (sx1 + tx) / 2; sy2 = (sy1 + ty) / 2; tx2 = (a2 + x3) / 2; ty2 = (b2 + y3) / 2; tx1 = (tx2 + tx) / 2; ty1 = (ty2 + ty) / 2; xmid = (sx2 + tx1) / 2; ymid = (sy2 + ty1) / 2; bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid); bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3); } } static void newline() { /* * A vestige from another version of this driver. */ fprintf(tfp, "\n"); } struct driver dev_tpic = { gentpic_option, gentpic_start, gentpic_arc, gentpic_ellipse, gentpic_line, gentpic_spline, gentpic_text, gentpic_end, INCLUDE_TEXT };