plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

pltroff.c (7600B)


      1 #include <stdio.h>
      2 #include <math.h>
      3 #include <string.h>
      4 #include "pic.h"
      5 extern int dbg;
      6 
      7 #define	abs(n)	(n >= 0 ? n : -(n))
      8 #define	max(x,y)	((x)>(y) ? (x) : (y))
      9 
     10 char	*textshift = "\\v'.2m'";	/* move text this far down */
     11 
     12 /* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
     13 /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
     14 /* default output is 6x6 inches */
     15 
     16 
     17 double	xscale;
     18 double	yscale;
     19 
     20 double	hpos	= 0;	/* current horizontal position in output coordinate system */
     21 double	vpos	= 0;	/* current vertical position; 0 is top of page */
     22 
     23 double	htrue	= 0;	/* where we really are */
     24 double	vtrue	= 0;
     25 
     26 double	X0, Y0;		/* left bottom of input */
     27 double	X1, Y1;		/* right top of input */
     28 
     29 double	hmax;		/* right end of output */
     30 double	vmax;		/* top of output (down is positive) */
     31 
     32 extern	double	deltx;
     33 extern	double	delty;
     34 extern	double	xmin, ymin, xmax, ymax;
     35 
     36 double	xconv(double), yconv(double), xsc(double), ysc(double);
     37 void	space(double, double, double, double);
     38 void	hgoto(double), vgoto(double), hmot(double), vmot(double);
     39 void	move(double, double), movehv(double, double);
     40 void	cont(double, double);
     41 
     42 void openpl(char *s)	/* initialize device; s is residue of .PS invocation line */
     43 {
     44 	double maxw, maxh, ratio = 1;
     45 	double odeltx = deltx, odelty = delty;
     46 
     47 	hpos = vpos = 0;
     48 	maxw = getfval("maxpswid");
     49 	maxh = getfval("maxpsht");
     50 	if (deltx > maxw) {	/* shrink horizontal */
     51 		ratio = maxw / deltx;
     52 		deltx *= ratio;
     53 		delty *= ratio;
     54 	}
     55 	if (delty > maxh) {	/* shrink vertical */
     56 		ratio = maxh / delty;
     57 		deltx *= ratio;
     58 		delty *= ratio;
     59 	}
     60 	if (ratio != 1) {
     61 		fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty);
     62 		fprintf(stderr, " %g X %g\n", deltx, delty);
     63 	}
     64 	space(xmin, ymin, xmax, ymax);
     65 	printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
     66 	printf("... %.3fi %.3fi %.3fi %.3fi\n",
     67 		xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
     68 	printf(".nr 00 \\n(.u\n");
     69 	printf(".nf\n");
     70 	printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
     71 		/* assumes \n comes as part of s */
     72 }
     73 
     74 void space(double x0, double y0, double x1, double y1)	/* set limits of page */
     75 {
     76 	X0 = x0;
     77 	Y0 = y0;
     78 	X1 = x1;
     79 	Y1 = y1;
     80 	xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
     81 	yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
     82 }
     83 
     84 double xconv(double x)	/* convert x from external to internal form */
     85 {
     86 	return (x-X0) * xscale;
     87 }
     88 
     89 double xsc(double x)	/* convert x from external to internal form, scaling only */
     90 {
     91 
     92 	return (x) * xscale;
     93 }
     94 
     95 double yconv(double y)	/* convert y from external to internal form */
     96 {
     97 	return (Y1-y) * yscale;
     98 }
     99 
    100 double ysc(double y)	/* convert y from external to internal form, scaling only */
    101 {
    102 	return (y) * yscale;
    103 }
    104 
    105 void closepl(char *PEline)	/* clean up after finished */
    106 {
    107 	movehv(0.0, 0.0);	/* get back to where we started */
    108 	if (strchr(PEline, 'F') == NULL) {
    109 		printf(".sp 1+%.3fi\n", yconv(ymin));
    110 	}
    111 	printf("%s\n", PEline);
    112 	printf(".if \\n(00 .fi\n");
    113 }
    114 
    115 void move(double x, double y)	/* go to position x, y in external coords */
    116 {
    117 	hgoto(xconv(x));
    118 	vgoto(yconv(y));
    119 }
    120 
    121 void movehv(double h, double v)	/* go to internal position h, v */
    122 {
    123 	hgoto(h);
    124 	vgoto(v);
    125 }
    126 
    127 void hmot(double n)	/* generate n units of horizontal motion */
    128 {
    129 	hpos += n;
    130 }
    131 
    132 void vmot(double n)	/* generate n units of vertical motion */
    133 {
    134 	vpos += n;
    135 }
    136 
    137 void hgoto(double n)
    138 {
    139 	hpos = n;
    140 }
    141 
    142 void vgoto(double n)
    143 {
    144 	vpos = n;
    145 }
    146 
    147 void hvflush(void)	/* get to proper point for output */
    148 {
    149 	if (fabs(hpos-htrue) >= 0.0005) {
    150 		printf("\\h'%.3fi'", hpos - htrue);
    151 		htrue = hpos;
    152 	}
    153 	if (fabs(vpos-vtrue) >= 0.0005) {
    154 		printf("\\v'%.3fi'", vpos - vtrue);
    155 		vtrue = vpos;
    156 	}
    157 }
    158 
    159 void flyback(void)	/* return to upper left corner (entry point) */
    160 {
    161 	printf(".sp -1\n");
    162 	htrue = vtrue = 0;
    163 }
    164 
    165 void printlf(int n, char *f)
    166 {
    167 	if (f)
    168 		printf(".lf %d %s\n", n, f);
    169 	else
    170 		printf(".lf %d\n", n);
    171 }
    172 
    173 void troff(char *s)	/* output troff right here */
    174 {
    175 	printf("%s\n", s);
    176 }
    177 
    178 void label(char *s, int t, int nh)	/* text s of type t nh half-lines up */
    179 {
    180 	int q;
    181 	char *p;
    182 
    183 	if (!s)
    184 		return;
    185 	hvflush();
    186 	dprintf("label: %s %o %d\n", s, t, nh);
    187 	printf("%s", textshift);	/* shift down and left */
    188 	if (t & ABOVE)
    189 		nh++;
    190 	else if (t & BELOW)
    191 		nh--;
    192 	if (nh)
    193 		printf("\\v'%du*\\n(.vu/2u'", -nh);
    194 	/* just in case the text contains a quote: */
    195 	q = 0;
    196 	for (p = s; *p; p++)
    197 		if (*p == '\'') {
    198 			q = 1;
    199 			break;
    200 		}
    201 	t &= ~(ABOVE|BELOW);
    202 	if (t & LJUST) {
    203 		printf("%s", s);
    204 	} else if (t & RJUST) {
    205 		if (q)
    206 			printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
    207 		else
    208 			printf("\\h'-\\w'%s'u'%s", s, s);
    209 	} else {	/* CENTER */
    210 		if (q)
    211 			printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
    212 		else
    213 			printf("\\h'-\\w'%s'u/2u'%s", s, s);
    214 	}
    215 	printf("\n");
    216 	flyback();
    217 }
    218 
    219 void line(double x0, double y0, double x1, double y1)	/* draw line from x0,y0 to x1,y1 */
    220 {
    221 	move(x0, y0);
    222 	cont(x1, y1);
    223 }
    224 
    225 void arrow(double x0, double y0, double x1, double y1, double w, double h,
    226 	 double ang, int nhead) 	/* draw arrow (without shaft) */
    227 {
    228 	double alpha, rot, drot, hyp;
    229 	double dx, dy;
    230 	int i;
    231 
    232 	rot = atan2(w / 2, h);
    233 	hyp = sqrt(w/2 * w/2 + h * h);
    234 	alpha = atan2(y1-y0, x1-x0) + ang;
    235 	if (nhead < 2)
    236 		nhead = 2;
    237 	dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
    238 	for (i = nhead-1; i >= 0; i--) {
    239 		drot = 2 * rot / (double) (nhead-1) * (double) i;
    240 		dx = hyp * cos(alpha + PI - rot + drot);
    241 		dy = hyp * sin(alpha + PI - rot + drot);
    242 		dprintf("dx,dy = %g,%g\n", dx, dy);
    243 		line(x1+dx, y1+dy, x1, y1);
    244 	}
    245 }
    246 
    247 double lastgray = 0;
    248 
    249 void fillstart(double v)	/* this works only for postscript, obviously. */
    250 {				/* uses drechsler's dpost conventions... */
    251 	hvflush();
    252 	printf("\\X'BeginObject %g setgray'\n", v);
    253 	lastgray = v;
    254 	flyback();
    255 }
    256 
    257 void fillend(int vis, int fill)
    258 {
    259 	hvflush();
    260 	printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
    261 		!vis ? lastgray : 0.0,
    262 		vis ? "stroke" : "");
    263 	/* for dashed: [50] 0 setdash just before stroke. */
    264 	lastgray = 0;
    265 	flyback();
    266 }
    267 
    268 void box(double x0, double y0, double x1, double y1)
    269 {
    270 	move(x0, y0);
    271 	cont(x0, y1);
    272 	cont(x1, y1);
    273 	cont(x1, y0);
    274 	cont(x0, y0);
    275 }
    276 
    277 void cont(double x, double y)	/* continue line from here to x,y */
    278 {
    279 	double h1, v1;
    280 	double dh, dv;
    281 
    282 	h1 = xconv(x);
    283 	v1 = yconv(y);
    284 	dh = h1 - hpos;
    285 	dv = v1 - vpos;
    286 	hvflush();
    287 	printf("\\D'l%.3fi %.3fi'\n", dh, dv);
    288 	flyback();	/* expensive */
    289 	hpos = h1;
    290 	vpos = v1;
    291 }
    292 
    293 void circle(double x, double y, double r)
    294 {
    295 	move(x-r, y);
    296 	hvflush();
    297 	printf("\\D'c%.3fi'\n", xsc(2 * r));
    298 	flyback();
    299 }
    300 
    301 void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
    302 {
    303 	int i;
    304 	double dx, dy;
    305 	double xerr, yerr;
    306 
    307 	move(x, y);
    308 	hvflush();
    309 	xerr = yerr = 0.0;
    310 	printf("\\D'~");
    311 	for (i = 0; i < 2 * n; i += 2) {
    312 		dx = xsc(xerr += p[i]);
    313 		xerr -= dx/xscale;
    314 		dy = ysc(yerr += p[i+1]);
    315 		yerr -= dy/yscale;
    316 		printf(" %.3fi %.3fi", dx, -dy);	/* WATCH SIGN */
    317 	}
    318 	printf("'\n");
    319 	flyback();
    320 }
    321 
    322 void ellipse(double x, double y, double r1, double r2)
    323 {
    324 	double ir1, ir2;
    325 
    326 	move(x-r1, y);
    327 	hvflush();
    328 	ir1 = xsc(r1);
    329 	ir2 = ysc(r2);
    330 	printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
    331 	flyback();
    332 }
    333 
    334 void arc(double x, double y, double x0, double y0, double x1, double y1)	/* draw arc with center x,y */
    335 {
    336 
    337 	move(x0, y0);
    338 	hvflush();
    339 	printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
    340 		xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y));	/* WATCH SIGNS */
    341 	flyback();
    342 }
    343 
    344 void dot(void) {
    345 	hvflush();
    346 	/* what character to draw here depends on what's available. */
    347 	/* on the 202, l. is good but small. */
    348 	/* in general, use a smaller, shifted period and hope */
    349 
    350 	printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
    351 	flyback();
    352 }