|
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: 15970 (0x3e62) Types: TextFile Names: »genps.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z« └─⟦c58930e5c⟧ └─⟦this⟧ »TeX3.14/TeXgraphics/transfig/fig2dev/dev/genps.c«
/* * genps.c: PostScript driver for fig2dev * */ #if defined(hpux) || defined(SYSV) #include <sys/types.h> #endif #include <sys/file.h> #include <stdio.h> #include <math.h> #include <pwd.h> #include "pi.h" #include "object.h" #include "fig2dev.h" #include "psfonts.h" #define PAGE_WIDTH 612 /* points; 8.5" */ #define PAGE_HEIGHT 792 /* points; 11" */ #define TRUE 1 #define FALSE 0 #define POINT_PER_INCH 72 #define ULIMIT_FONT_SIZE 300 int coord_system; int show_page = 0; int cur_thickness; int center = 0; int landscape = 0; extern int v2_flag, v21_flag; #define GRAYVAL(F) ((F) <= 21 ? (21-(F))/20.0 : 0.0) #define BEGIN_PROLOG "\ /$F2psDict 32 dict def \n\ $F2psDict begin\n\ $F2psDict /mtrx matrix put\n\ " #define ELLIPSE_PS " \ /DrawEllipse {\n\ /endangle exch def\n\ /startangle exch def\n\ /yrad exch def\n\ /xrad exch def\n\ /y exch def\n\ /x exch def\n\ /savematrix mtrx currentmatrix def\n\ x y translate xrad yrad scale 0 0 1 startangle endangle arc\n\ savematrix setmatrix\n\ } def\n\ " /* The original PostScript definition for adding a spline section to the * current path uses recursive bisection. The following definition using the * curveto operator is more efficient since it executes at compiled rather * than interpreted code speed. The Bezier control points are 2/3 of the way * from z1 (and z3) to z2. * * ---Rene Llames, 21 July 1988. */ #define SPLINE_PS " \ /DrawSplineSection {\n\ /y3 exch def\n\ /x3 exch def\n\ /y2 exch def\n\ /x2 exch def\n\ /y1 exch def\n\ /x1 exch def\n\ /xa x1 x2 x1 sub 0.666667 mul add def\n\ /ya y1 y2 y1 sub 0.666667 mul add def\n\ /xb x3 x2 x3 sub 0.666667 mul add def\n\ /yb y3 y2 y3 sub 0.666667 mul add def\n\ x1 y1 lineto\n\ xa ya xb yb x3 y3 curveto\n\ } def\n\ " #define END_PROLOG "\ end\n\ /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def\n\ /$F2psEnd {$F2psEnteredState restore end} def\n\ %%EndProlog\n\ " void genps_option(opt, optarg) char opt; char *optarg; { int i; switch (opt) { case 'f': for ( i = 1; i <= MAX_PSFONT + 1; i++ ) if ( !strcmp(optarg, PSfontnames[i]) ) break; if ( i > MAX_PSFONT + 1 ) fprintf(stderr, "warning: non-standard font name %s\n", optarg); psfontnames[0] = psfontnames[1] = optarg; PSfontnames[0] = PSfontnames[1] = optarg; break; case 'c': center = 1; break; case 's': if (font_size <= 0 || font_size > ULIMIT_FONT_SIZE) { fprintf(stderr, "warning: font size %d out of bounds\n", font_size); } break; case 'P': show_page = 1; break; case 'm': case 'L': break; case 'l': landscape = 1; break; default: put_msg(Err_badarg, opt, "ps"); exit(1); break; } } void genps_start(objects) F_compound *objects; { char host[256]; struct passwd *who; long when; extern char *ctime(), *strcpy(); extern long time(); double tx, scalex, scaley; double dx, dy, origx, origy; int itmp; coord_system = objects->nwcorner.y; scalex = scaley = mag * POINT_PER_INCH / (double)objects->nwcorner.x; /* convert to point unit */ llx = (int)ceil(llx * scalex); lly = (int)ceil(lly * scaley); urx = (int)ceil(urx * scalex); ury = (int)ceil(ury * scaley); if (landscape) /* swap x,y */ { itmp = llx; llx = lly; lly = itmp; itmp = urx; urx = ury; ury = itmp; } if (center) { dx = urx - llx; dy = ury - lly; tx = (PAGE_WIDTH - dx) / 2.0; if (landscape) origx=0; else origx = tx - llx; urx = (llx=tx) + dx; ury = (PAGE_HEIGHT + dy) / 2.0; if (coord_system == 2) origy = ury + lly; else origy = ury - dy - lly; lly = ury - dy; } else { origx = 0.0; origy = PAGE_HEIGHT; } if (coord_system == 2) scaley = -scaley; fprintf(tfp, "%%!\n"); /* PostScript magic strings */ who = getpwuid(getuid()); if (-1 == gethostname(host, sizeof(host))) (void)strcpy(host, "unknown-host!?!?"); (void) time(&when); fprintf(tfp, "%%%%Title: %s\n", ((from) ? from : "stdin")); fprintf(tfp, "%%%%Creator: %s\n", prog); fprintf(tfp, "%%%%CreationDate: %s", ctime(&when)); fprintf(tfp, "%%%%For: %s@%s (%s)\n", who->pw_name, host, who->pw_gecos); fprintf(tfp, "%%%%Pages: %d\n", show_page); if (show_page) fprintf(tfp, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); else fprintf(tfp, "%%%%BoundingBox: 0 0 %d %d\n", urx-llx, ury-lly); fprintf(tfp, "%%%%EndComments\n"); fprintf(tfp, "%s\n", BEGIN_PROLOG); if (ellipse_exist(objects)) fprintf(tfp, "%s\n", ELLIPSE_PS); if (normal_spline_exist(objects)) fprintf(tfp, "%s\n", SPLINE_PS); fprintf(tfp, "%s\n", END_PROLOG); fprintf(tfp, "$F2psBegin\n"); fprintf(tfp, "1 setlinecap 1 setlinejoin\n"); if (!show_page) fprintf(tfp, "%d %d translate\n", -llx, lly); fprintf(tfp, "%f %f translate %.3f %.3f scale\n", origx, (show_page ? origy : ury-lly), scalex, scaley); /* **** Land scape mode ****/ if (landscape) fprintf(tfp, "%d 0 translate 90 rotate\n", PAGE_WIDTH); /* if ((t = PAGE_HEIGHT / SCALE / WIDTH) < 1.0) * fprintf(tfp, "%f %f scale\n", t, t); * } *else if ((t = PAGE_HEIGHT / SCALE / HEIGHT) < 1.0) * fprintf(tfp, "%f %f scale\n", t, t); */ } void genps_end() { if (show_page) fprintf(tfp, "showpage\n"); fprintf(tfp, "$F2psEnd\n"); } static set_style(s, v) int s; double v; { if (s == DASH_LINE) { if (v > 0.0) fprintf(tfp, "\t[%f] 0 setdash\n", v); } else if (s == DOTTED_LINE) { if (v > 0.0) fprintf(tfp, "\t[1 %f] 0 setdash\n", v); } } static reset_style(s, v) int s; double v; { if (s == DASH_LINE) { if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n"); } else if (s == DOTTED_LINE) { if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n"); } } static set_linewidth(w) int w; { extern int cur_thickness; if (w != cur_thickness) { cur_thickness = w; fprintf(tfp, "%.3f setlinewidth\n", 1.0 * cur_thickness); } } void genps_line(l) F_line *l; { F_point *p, *q; /* JNT */ int radius; set_linewidth(l->thickness); radius = l->radius; /* radius of rounded-corner boxes */ p = l->points; q = p->next; if (q == NULL) { /* A single point line */ fprintf(tfp, "newpath %d %d moveto %d %d lineto stroke\n", p->x, p->y, p->x, p->y); return; } if (l->back_arrow) draw_arrow_head((double)q->x, (double)q->y, (double)p->x, (double)p->y, l->back_arrow->ht, l->back_arrow->wid); set_style(l->style, l->style_val); fprintf(tfp, "%% Polyline\n"); /* JNT */ if (l->type == 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 corne rs */ { 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, "newpath %d %d moveto",xmin+radius, ymin); fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", xmin, ymin, xmin, ymax-radius, radius); fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro ugh bl to br */ xmin, ymax, xmax-radius, ymax, radius); fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro ugh br to tr */ xmax, ymax, xmax, ymin+radius, radius); fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro ugh tr to tl */ xmax, ymin, xmin+radius, ymin, radius); } else { fprintf(tfp, "newpath %d %d moveto", p->x, p->y); while (q->next != NULL) { p = q; q = q->next; fprintf(tfp, " %d %d lineto", p->x, p->y); } } if (l->type == T_POLYLINE) fprintf(tfp, " %d %d lineto stroke\n", q->x, q->y); else fprintf(tfp, " closepath "); if (l->area_fill && (int)l->area_fill != DEFAULT) fprintf(tfp, "gsave %6.3f setgray fill grestore ", GRAYVAL(l->area_fill)); fprintf(tfp, "stroke\n"); reset_style(l->style, l->style_val); if (l->for_arrow) draw_arrow_head((double)p->x, (double)p->y, (double)q->x, (double)q->y, l->for_arrow->ht, l->for_arrow->wid); } void genps_spline(s) F_spline *s; { if (int_spline(s)) genps_itp_spline(s); else genps_ctl_spline(s); } genps_itp_spline(s) F_spline *s; { F_point *p, *q; F_control *a, *b; set_linewidth(s->thickness); a = s->controls; p = s->points; if (s->back_arrow) draw_arrow_head(a->rx, a->ry, (double)p->x, (double)p->y, s->back_arrow->ht, s->back_arrow->wid); set_style(s->style, s->style_val); fprintf(tfp, "%% Interpolated spline\n"); fprintf(tfp, "newpath %d %d moveto\n", p->x, p->y); for (q = p->next; q != NULL; p = q, q = q->next) { b = a->next; fprintf(tfp, "\t%.3f %.3f %.3f %.3f %d %d curveto\n", a->rx, a->ry, b->lx, b->ly, q->x, q->y); a = b; b = b->next; } if (closed_spline(s)) fprintf(tfp, " closepath "); if (s->area_fill && (int)s->area_fill != DEFAULT) fprintf(tfp, "gsave %6.3f setgray fill grestore ", GRAYVAL(s->area_fill)); fprintf(tfp, " stroke\n"); reset_style(s->style, s->style_val); if (s->for_arrow) draw_arrow_head(a->lx, a->ly, (double)p->x, (double)p->y, s->for_arrow->ht, s->for_arrow->wid); } genps_ctl_spline(s) F_spline *s; { double a, b, c, d, x1, y1, x2, y2, x3, y3; F_point *p, *q; /* if (first) { first = FALSE; fprintf(tfp, "%s\n", SPLINE_PS); } */ p = s->points; x1 = p->x; y1 = p->y; p = p->next; c = p->x; d = p->y; set_linewidth(s->thickness); x3 = a = (x1 + c) / 2; y3 = b = (y1 + d) / 2; if (s->back_arrow) { draw_arrow_head(c, d, x1, y1, s->back_arrow->ht, s->back_arrow->wid); } set_style(s->style, s->style_val); if (! closed_spline(s)) { fprintf(tfp, "%% Open spline\n"); fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto\n", x1, y1, x3, y3); } else { fprintf(tfp, "%% Closed spline\n"); fprintf(tfp, "newpath %.3f %.3f moveto\n", a, b); } for (q = p->next; q != NULL; p = q, q = q->next) { x1 = x3; y1 = y3; x2 = c; y2 = d; c = q->x; d = q->y; x3 = (x2 + c) / 2; y3 = (y2 + d) / 2; fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection\n", x1, y1, x2, y2, x3, y3); } /* * At this point, (x2,y2) and (c,d) are the position of the * next-to-last and last point respectively, in the point list */ if (closed_spline(s)) { fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection closepath ", x3, y3, c, d, a, b); } else { fprintf(tfp, "\t%.3f %.3f lineto ", c, d); } if (s->area_fill && (int)s->area_fill != DEFAULT) fprintf(tfp, "gsave %6.3f setgray fill grestore ", GRAYVAL(s->area_fill)); fprintf(tfp, "stroke\n"); reset_style(s->style, s->style_val); if (s->for_arrow) { draw_arrow_head(x2, y2, c, d, s->for_arrow->ht, s->for_arrow->wid); } } void genps_ellipse(e) F_ellipse *e; { set_linewidth(e->thickness); set_style(e->style, e->style_val); if (e->angle == 0) { fprintf(tfp, "%% Ellipse\n"); fprintf(tfp, "newpath %d %d %d %d 0 360 DrawEllipse ", e->center.x, e->center.y, e->radiuses.x, e->radiuses.y); } else { fprintf(tfp, "%% Rotated Ellipse\n"); fprintf(tfp, "gsave\n"); fprintf(tfp, "%d %d translate\n",e->center.x, e->center.y); fprintf(tfp, "%6.3f rotate\n",e->angle*180/M_PI); fprintf(tfp, "newpath 0 0 %d %d 0 360 DrawEllipse ", e->radiuses.x, e->radiuses.y); } if (e->area_fill && (int)e->area_fill != DEFAULT) fprintf(tfp, "gsave %6.3f setgray fill grestore ", GRAYVAL(e->area_fill)); fprintf(tfp, "stroke\n"); if (e->angle != 0) fprintf(tfp, "grestore\n"); reset_style(e->style, e->style_val); } #define TEXT_PS "\ /%s findfont %.3f scalefont setfont\n\ " void genps_text(t) F_text *t; { char *cp; fprintf(tfp, TEXT_PS, PSFONT(t), PSFONTMAG(t)); fprintf(tfp, "%d %d moveto \n", t->base_x, t->base_y); if (coord_system == 2) fprintf(tfp, "1 -1 scale\n"); /* this loop escapes characters '(', ')', and '\' */ fputc('(', tfp); for(cp = t->cstring; *cp; cp++) { if (strchr("()\\", *cp)) fputc('\\', tfp); fputc(*cp, tfp); } fputc(')', tfp); if ((t->type == T_CENTER_JUSTIFIED) || (t->type == T_RIGHT_JUSTIFIED)){ fprintf(tfp, "dup stringwidth pop "); if (t->type == T_CENTER_JUSTIFIED) fprintf(tfp, "2 div "); fprintf(tfp, "neg 0 rmoveto "); } else if ((t->type != T_LEFT_JUSTIFIED) && (t->type != DEFAULT)) fprintf(stderr, "Text incorrectly positioned\n"); fprintf(tfp, " gsave %6.3f rotate show grestore ", t->angle*180/M_PI); if (coord_system == 2) fprintf(tfp, "1 -1 scale\n"); } void genps_arc(a) F_arc *a; { double angle1, angle2, dx, dy, radius, x, y; double cx, cy, sx, sy, ex, ey; int direction; cx = a->center.x; cy = a->center.y; sx = a->point[0].x; sy = a->point[0].y; ex = a->point[2].x; ey = a->point[2].y; if (coord_system == 2) direction = !a->direction; else direction = a->direction; set_linewidth(a->thickness); if (a->for_arrow) { arc_tangent(cx, cy, ex, ey, direction, &x, &y); draw_arrow_head(x, y, ex, ey, a->for_arrow->ht, a->for_arrow->wid); } if (a->back_arrow) { arc_tangent(cx, cy, sx, sy, !direction, &x, &y); draw_arrow_head(x, y, sx, sy, a->back_arrow->ht, a->back_arrow->wid); } dx = cx - sx; dy = cy - sy; radius = hypot(dx, dy); angle1 = atan2(sy-cy, sx-cx) * 180 / M_PI; angle2 = atan2(ey-cy, ex-cx) * 180 / M_PI; /* direction = 1 -> Counterclockwise */ set_style(a->style, a->style_val); fprintf(tfp, "newpath %.3f %.3f %.3f %.3f %.3f %s\n", cx, cy, radius, angle1, angle2, ((direction == 1) ? "arc" : "arcn")); if (a->area_fill && (int)a->area_fill != DEFAULT) fprintf(tfp, "gsave %6.3f setgray fill grestore ", GRAYVAL(a->area_fill)); fprintf(tfp, "stroke\n"); reset_style(a->style, a->style_val); } 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); } } /* draw arrow heading from (x1, y1) to (x2, y2) */ static draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid) double x1, y1, x2, y2, arrowht, arrowwid; { double x, y, xb, yb, dx, dy, l, sina, cosa; double xc, yc, xd, yd; dx = x2 - x1; dy = y1 - y2; l = hypot(dx, dy); sina = dy / l; cosa = dx / l; xb = x2*cosa - y2*sina; yb = x2*sina + y2*cosa; x = xb - arrowht; y = yb - arrowwid / 2; xc = x*cosa + y*sina; yc = -x*sina + y*cosa; y = yb + arrowwid / 2; xd = x*cosa + y*sina; yd = -x*sina + y*cosa; fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto %.3f %.3f lineto stroke\n", xc, yc, x2, y2, xd, yd); } static ellipse_exist(ob) F_compound *ob; { F_compound *c; if (NULL != ob->ellipses) return(1); for (c = ob->compounds; c != NULL; c = c->next) { if (ellipse_exist(c)) return(1); } return(0); } static normal_spline_exist(ob) F_compound *ob; { F_spline *s; F_compound *c; for (s = ob->splines; s != NULL; s = s->next) { if (normal_spline(s)) return(1); } for (c = ob->compounds; c != NULL; c = c->next) { if (normal_spline_exist(c)) return(1); } return(0); } struct driver dev_ps = { genps_option, genps_start, genps_arc, genps_ellipse, genps_line, genps_spline, genps_text, genps_end, INCLUDE_TEXT };