Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
double fabs(double x)
148
{
149
	return x < 0 ? -x : x;
150
}
151
 
152
void hvflush(void)	/* get to proper point for output */
153
{
154
	if (fabs(hpos-htrue) >= 0.0005) {
155
		printf("\\h'%.3fi'", hpos - htrue);
156
		htrue = hpos;
157
	}
158
	if (fabs(vpos-vtrue) >= 0.0005) {
159
		printf("\\v'%.3fi'", vpos - vtrue);
160
		vtrue = vpos;
161
	}
162
}
163
 
164
void flyback(void)	/* return to upper left corner (entry point) */
165
{
166
	printf(".sp -1\n");
167
	htrue = vtrue = 0;
168
}
169
 
170
void printlf(int n, char *f)
171
{
172
	if (f)
173
		printf(".lf %d %s\n", n, f);
174
	else
175
		printf(".lf %d\n", n);
176
}
177
 
178
void troff(char *s)	/* output troff right here */
179
{
180
	printf("%s\n", s);
181
}
182
 
183
void label(char *s, int t, int nh)	/* text s of type t nh half-lines up */
184
{
185
	int q;
186
	char *p;
187
 
188
	if (!s)
189
		return;
190
	hvflush();
191
	dprintf("label: %s %o %d\n", s, t, nh);
192
	printf("%s", textshift);	/* shift down and left */
193
	if (t & ABOVE)
194
		nh++;
195
	else if (t & BELOW)
196
		nh--;
197
	if (nh)
198
		printf("\\v'%du*\\n(.vu/2u'", -nh);
199
	/* just in case the text contains a quote: */
200
	q = 0;
201
	for (p = s; *p; p++)
202
		if (*p == '\'') {
203
			q = 1;
204
			break;
205
		}
206
	t &= ~(ABOVE|BELOW);
207
	if (t & LJUST) {
208
		printf("%s", s);
209
	} else if (t & RJUST) {
210
		if (q)
211
			printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
212
		else
213
			printf("\\h'-\\w'%s'u'%s", s, s);
214
	} else {	/* CENTER */
215
		if (q)
216
			printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
217
		else
218
			printf("\\h'-\\w'%s'u/2u'%s", s, s);
219
	}
220
	printf("\n");
221
	flyback();
222
}
223
 
224
void line(double x0, double y0, double x1, double y1)	/* draw line from x0,y0 to x1,y1 */
225
{
226
	move(x0, y0);
227
	cont(x1, y1);
228
}
229
 
230
void arrow(double x0, double y0, double x1, double y1, double w, double h,
231
	 double ang, int nhead) 	/* draw arrow (without shaft) */
232
{
233
	double alpha, rot, drot, hyp;
234
	double dx, dy;
235
	int i;
236
 
237
	rot = atan2(w / 2, h);
238
	hyp = sqrt(w/2 * w/2 + h * h);
239
	alpha = atan2(y1-y0, x1-x0) + ang;
240
	if (nhead < 2)
241
		nhead = 2;
242
	dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
243
	for (i = nhead-1; i >= 0; i--) {
244
		drot = 2 * rot / (double) (nhead-1) * (double) i;
245
		dx = hyp * cos(alpha + PI - rot + drot);
246
		dy = hyp * sin(alpha + PI - rot + drot);
247
		dprintf("dx,dy = %g,%g\n", dx, dy);
248
		line(x1+dx, y1+dy, x1, y1);
249
	}
250
}
251
 
252
double lastgray = 0;
253
 
254
void fillstart(double v)	/* this works only for postscript, obviously. */
255
{				/* uses drechsler's dpost conventions... */
256
	hvflush();
257
	printf("\\X'BeginObject %g setgray'\n", v);
258
	lastgray = v;
259
	flyback();
260
}
261
 
262
void fillend(int vis, int fill)
263
{
264
	hvflush();
265
	printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
266
		!vis ? lastgray : 0.0,
267
		vis ? "stroke" : "");
268
	/* for dashed: [50] 0 setdash just before stroke. */
269
	lastgray = 0;
270
	flyback();
271
}
272
 
273
void box(double x0, double y0, double x1, double y1)
274
{
275
	move(x0, y0);
276
	cont(x0, y1);
277
	cont(x1, y1);
278
	cont(x1, y0);
279
	cont(x0, y0);
280
}
281
 
282
void cont(double x, double y)	/* continue line from here to x,y */
283
{
284
	double h1, v1;
285
	double dh, dv;
286
 
287
	h1 = xconv(x);
288
	v1 = yconv(y);
289
	dh = h1 - hpos;
290
	dv = v1 - vpos;
291
	hvflush();
292
	printf("\\D'l%.3fi %.3fi'\n", dh, dv);
293
	flyback();	/* expensive */
294
	hpos = h1;
295
	vpos = v1;
296
}
297
 
298
void circle(double x, double y, double r)
299
{
300
	move(x-r, y);
301
	hvflush();
302
	printf("\\D'c%.3fi'\n", xsc(2 * r));
303
	flyback();
304
}
305
 
306
void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
307
{
308
	int i;
309
	double dx, dy;
310
	double xerr, yerr;
311
 
312
	move(x, y);
313
	hvflush();
314
	xerr = yerr = 0.0;
315
	printf("\\D'~");
316
	for (i = 0; i < 2 * n; i += 2) {
317
		dx = xsc(xerr += p[i]);
318
		xerr -= dx/xscale;
319
		dy = ysc(yerr += p[i+1]);
320
		yerr -= dy/yscale;
321
		printf(" %.3fi %.3fi", dx, -dy);	/* WATCH SIGN */
322
	}
323
	printf("'\n");
324
	flyback();
325
}
326
 
327
void ellipse(double x, double y, double r1, double r2)
328
{
329
	double ir1, ir2;
330
 
331
	move(x-r1, y);
332
	hvflush();
333
	ir1 = xsc(r1);
334
	ir2 = ysc(r2);
335
	printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
336
	flyback();
337
}
338
 
339
void arc(double x, double y, double x0, double y0, double x1, double y1)	/* draw arc with center x,y */
340
{
341
 
342
	move(x0, y0);
343
	hvflush();
344
	printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
345
		xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y));	/* WATCH SIGNS */
346
	flyback();
347
}
348
 
349
void dot(void) {
350
	hvflush();
351
	/* what character to draw here depends on what's available. */
352
	/* on the 202, l. is good but small. */
353
	/* in general, use a smaller, shifted period and hope */
354
 
355
	printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
356
	flyback();
357
}