1 /* hgraph.c 1.15 (Berkeley) 86/04/14
2 *
3 * This file contains the graphics routines for converting gremlin
4 * pictures to troff input.
5 */
6
7 #include "gprint.h"
8
9
10 #define MAXVECT 40
11 #define pi 3.14159265358979324
12 #define twopi (2.0 * pi)
13 #define len(a, b) sqrt((b.x-a.x) * (b.x-a.x) + (b.y-a.y) * (b.y-a.y))
14
15
16 extern int style[]; /* line and character styles */
17 extern int thick[];
18 extern char *tfont[];
19 extern int tsize[];
20 extern int stipple_index[]; /* stipple font index for stipples 1 - 8 */
21 extern char *stipple; /* stipple type (cf or ug) */
22 extern int oldstipmap; /* use old-style stipple mapping */
23
24
25 extern double troffscale; /* imports from main.c */
26 extern point();
27 extern int linethickness;
28 extern int linmod;
29 extern int lastx;
30 extern int lasty;
31 extern int lastyline;
32 extern int ytop;
33 extern int ybottom;
34 extern int xleft;
35 extern int xright;
36
37
38 /*----------------------------------------------------------------------------*
39 | Routine: HGPrintElt (element_pointer, baseline)
40 |
41 | Results: examines a picture element and calls the appropriate
42 | routine(s) to print them according to their type.
43 | After the picture is drawn, current position is (lastx, lasty).
44 *----------------------------------------------------------------------------*/
45
HGPrintElt(element,baseline)46 HGPrintElt(element, baseline)
47 ELT *element;
48 int baseline;
49 {
50 register POINT *p1;
51 register POINT *p2;
52 register int length;
53 static int didstipple = 1; /* flag to prevent multipe messages about no */
54 /* stipple font requested from being printed */
55 float firstx, firsty; /* for completing polygons */
56
57 if ( !DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) {
58 /* p1 always has first point */
59 if (TEXT(element->type)) {
60 HGSetFont(element->brushf, element->size);
61 HGPutText(element->type, *p1, element->textpt);
62 } else {
63 if (element->brushf) { /* if there is a brush, the */
64 HGSetBrush(element->brushf); /* graphics need it set */
65 }
66 switch (element->type) {
67
68 case ARC: p2 = PTNextPoint(p1);
69 doarc(*p1, *p2, element->size);
70 break;
71
72 case CURVE: tmove(p1);
73 printf("\\D'g");
74 while (!Nullpoint((p1 = PTNextPoint(p1)))) {
75 dx((double) p1->x);
76 dy((double) p1->y);
77 } /* end while */;
78 putchar('\'');
79 cr();
80 break;
81
82 case VECTOR: length = 1; /* keep track of line length */
83 tmove(p1); /* so single lines don't get long */
84 while (!Nullpoint((p1 = PTNextPoint(p1)))) {
85 printf("\\D'l");
86 dx((double) p1->x);
87 dy((double) p1->y);
88 putchar('\'');
89 if (length++ > MAXVECT) {
90 cr();
91 tmove (p1);
92 length = 1;
93 }
94 } /* end while */
95 cr();
96 break;
97
98 case POLYGON: tmove(p1);
99 if (stipple) {
100 didstipple = 1;
101 printf(element->brushf ? "\\D'p %d":"\\D'P %d",
102 (element->size > NSTIPPLES ||
103 oldstipmap == FALSE) ? element->size :
104 stipple_index[element->size - 1]);
105 } else {
106 if (didstipple) {
107 error("no stipple for picture at line %d",
108 baseline);
109 didstipple = 0;
110 }
111 printf("\\D'p 0");
112 }
113
114 firstx = p1->x;
115 firsty = p1->y;
116 while (!Nullpoint((PTNextPoint(p1)))) {
117 p1 = PTNextPoint(p1);
118 dx((double) p1->x);
119 dy((double) p1->y);
120 } /* end while */;
121
122 /* close polygon if not done so by user */
123 if ((firstx != p1->x) || (firsty != p1->y)) {
124 dx((double) firstx);
125 dy((double) firsty);
126 }
127
128 putchar('\'');
129 cr();
130 break;
131 } /* end switch */
132 } /* end else Text */
133 } /* end if */
134 } /* end PrintElt */
135
136
137 /*----------------------------------------------------------------------------*
138 | Routine: HGPutText (justification, position_point, string)
139 |
140 | Results: given the justification, a point to position with, and a
141 | string to put, HGPutText first sends the string into a
142 | diversion, moves to the positioning point, then outputs local
143 | vertical and horizontal motions as needed to justify the text.
144 | After all motions are done, the diversion is printed out.
145 *----------------------------------------------------------------------------*/
146
HGPutText(justify,pnt,string)147 HGPutText(justify,pnt,string)
148 int justify;
149 POINT pnt;
150 register char *string;
151 {
152 int savelasty = lasty; /* vertical motion for text is to be */
153 /* ignored. save current y here */
154
155 printf(".nr g8 \\n(.d\n"); /* save current vertical position. */
156 printf(".ds g9 \""); /* define string containing the text. */
157 while (*string) { /* put out the string */
158 if (*string == '\\' && *(string+1) == '\\') { /* one character at a */
159 printf("\\\\\\"); /* time replacing // */
160 string++; /* by //// to prevent */
161 } /* interpretation at */
162 printf("%c", *(string++)); /* printout time */
163 }
164 printf("\n");
165 tmove(&pnt); /* move to positioning point */
166 switch (justify) {
167 /* local vertical motions */
168 /* (the numbers here are used to be */
169 /* somewhat compatible with gprint) */
170 case CENTLEFT:
171 case CENTCENT:
172 case CENTRIGHT: printf("\\v'0.85n'"); /* down half */
173 break;
174
175 case TOPLEFT:
176 case TOPCENT:
177 case TOPRIGHT: printf("\\v'1.7n'"); /* down whole */
178 }
179
180 switch (justify) {
181 /* local horizontal motions */
182 case BOTCENT:
183 case CENTCENT:
184 case TOPCENT: printf("\\h-\\w\\*(g9u/2u"); /* back half */
185 break;
186
187 case BOTRIGHT:
188 case CENTRIGHT:
189 case TOPRIGHT: printf("\\h-\\w\\*(g9u"); /* back whole */
190 }
191
192 printf("\\&\\*(g9\n"); /* now print the text. */
193 printf(".sp |\\n(g8u\n"); /* restore vertical position */
194 lasty = savelasty; /* vertical position restored to where it was */
195 lastx = xleft; /* before text, also horizontal is at left */
196 } /* end HGPutText */
197
198
199 /*----------------------------------------------------------------------------*
200 | Routine: doarc (center_point, start_point, angle)
201 |
202 | Results: produces either drawarc command or a drawcircle command
203 | depending on the angle needed to draw through.
204 *----------------------------------------------------------------------------*/
205
doarc(cp,sp,angle)206 doarc (cp, sp, angle)
207 POINT cp;
208 POINT sp;
209 int angle;
210 {
211 double radius = len(cp, sp);
212 double radians;
213
214
215 if (angle) { /* arc with angle */
216 tmove (&sp); /* starting point first */
217 printf("\\D'a");
218 dx((double) cp.x); /* move to center */
219 dy((double) cp.y);
220
221 radians = acos((sp.x - cp.x) / radius); /* angle of ending */
222 if (cp.y - sp.y < 0.0) /* point calculated */
223 radians = twopi - radians; /* from start point */
224 radians += ((double) angle) * (pi / 180.0); /* and arc's angle */
225 if (radians > twopi) radians -= twopi;
226
227 dx(cp.x + cos(radians) * radius); /* move to ending point */
228 dy(cp.y - sin(radians) * radius);
229
230 } else { /* a full circle (angle == 0) */
231 cp.x -= radius;
232 tmove(&cp); /* move to the left point first */
233 /* draw circle with given diameter */
234 printf("\\D'c %du", (int) ((radius + radius) * troffscale));
235 }
236 putchar('\''); /* finish the command */
237 cr();
238 }
239
240
241 /*----------------------------------------------------------------------------*
242 | Routine: HGSetFont (font_number, Point_size)
243 |
244 | Results: ALWAYS outputs a .ft and .ps directive to troff. This is
245 | done because someone may change stuff inside a text string.
246 *----------------------------------------------------------------------------*/
247
HGSetFont(font,size)248 HGSetFont(font, size)
249 int font, size;
250 {
251 printf(".ft %s\n.ps %d\n", tfont[font-1], tsize[size-1]);
252 }
253
254
255 /*----------------------------------------------------------------------------*
256 | Routine: HGSetBrush (line_mode)
257 |
258 | Results: generates the troff commands to set up the line width and
259 | style of subsequent lines. Does nothing if no change is needed.
260 |
261 | Side Efct: sets "linmode" and "linethicknes"
262 *----------------------------------------------------------------------------*/
263
HGSetBrush(mode)264 HGSetBrush(mode)
265 int mode;
266 {
267 register int printed = 0;
268
269 if (linmod != style[--mode]) {
270 printf ("\\D's %du'", linmod = style[mode]);
271 printed = 1;
272 }
273 if (linethickness != thick[mode]) {
274 printf ("\\D't %du'", linethickness = thick[mode]);
275 printed = 1;
276 }
277 if (printed)
278 cr();
279 }
280
281
282 /*----------------------------------------------------------------------------*
283 | Routine: dx (x_destination)
284 |
285 | Results: scales and outputs a number for delta x (with a leading space)
286 | given "lastx" and x_destination.
287 |
288 | Side Efct: resets "lastx" to x_destination.
289 *----------------------------------------------------------------------------*/
290
dx(x)291 dx(x)
292 double x;
293 {
294 register int ix = (int) (x * troffscale);
295
296 printf(" %du", ix - lastx);
297 lastx = ix;
298 }
299
300
301 /*----------------------------------------------------------------------------*
302 | Routine: dy (y_destination)
303 |
304 | Results: scales and outputs a number for delta y (with a leading space)
305 | given "lastyline" and y_destination.
306 |
307 | Side Efct: resets "lastyline" to y_destination. Since "line" vertical
308 | motions don't affect "page" ones, "lasty" isn't updated.
309 *----------------------------------------------------------------------------*/
310
dy(y)311 dy(y)
312 double y;
313 {
314 register int iy = (int) (y * troffscale);
315
316 printf(" %du", iy - lastyline);
317 lastyline = iy;
318 }
319
320
321 /*----------------------------------------------------------------------------*
322 | Routine: tmove (point_pointer)
323 |
324 | Results: produces horizontal and vertical moves for troff given the
325 | pointer of a point to move to and knowing the current position.
326 | Also puts out a horizontal move to start the line.
327 *----------------------------------------------------------------------------*/
328
tmove(ptr)329 tmove(ptr)
330 POINT *ptr;
331 {
332 register int ix = (int) (ptr->x * troffscale);
333 register int iy = (int) (ptr->y * troffscale);
334 register int dx;
335 register int dy;
336
337 if (dy = iy - lasty) {
338 printf(".sp %du\n", dy);
339 }
340 lastyline = lasty = iy; /* lasty is always set to current */
341 if (dx = ix - lastx) {
342 printf("\\h'%du'", dx);
343 lastx = ix;
344 }
345 }
346
347
348 /*----------------------------------------------------------------------------*
349 | Routine: cr ( )
350 |
351 | Results: Ends off an input line. ".sp -1" is also added to counteract
352 | the vertical move done at the end of text lines.
353 |
354 | Side Efct: sets "lastx" to "xleft" for troff's return to left margin
355 *----------------------------------------------------------------------------*/
356
cr()357 cr()
358 {
359 printf("\n.sp -1\n");
360 lastx = xleft;
361 }
362