Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / gnu / usr.bin / groff / libXdvi / draw.c
blob5c9f3ac99eca30759ebee1667e5ddc15106ea4fa
1 /*
2 * draw.c
4 * accept dvi function calls and translate to X
5 */
7 #include <X11/Xos.h>
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <math.h>
14 /* math.h on a Sequent doesn't define M_PI, apparently */
15 #ifndef M_PI
16 #define M_PI 3.14159265358979323846
17 #endif
19 #include "DviP.h"
21 HorizontalMove(dw, delta)
22 DviWidget dw;
23 int delta;
25 dw->dvi.state->x += delta;
28 HorizontalGoto(dw, NewPosition)
29 DviWidget dw;
30 int NewPosition;
32 dw->dvi.state->x = NewPosition;
35 VerticalMove(dw, delta)
36 DviWidget dw;
37 int delta;
39 dw->dvi.state->y += delta;
42 VerticalGoto(dw, NewPosition)
43 DviWidget dw;
44 int NewPosition;
46 dw->dvi.state->y = NewPosition;
49 FlushCharCache (dw)
50 DviWidget dw;
52 if (dw->dvi.cache.char_index != 0)
53 XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
54 dw->dvi.cache.start_x, dw->dvi.cache.start_y,
55 dw->dvi.cache.cache, dw->dvi.cache.index + 1);
56 dw->dvi.cache.index = 0;
57 dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
58 if (dw->dvi.noPolyText)
59 dw->dvi.cache.max = 1;
60 dw->dvi.cache.char_index = 0;
61 dw->dvi.cache.cache[0].nchars = 0;
62 dw->dvi.cache.start_x = dw->dvi.cache.x = dw->dvi.state->x;
63 dw->dvi.cache.start_y = dw->dvi.cache.y = dw->dvi.state->y;
66 ClearPage (dw)
67 DviWidget dw;
69 XClearWindow (XtDisplay (dw), XtWindow (dw));
72 static
73 setGC (dw)
74 DviWidget dw;
76 int desired_line_width;
78 if (dw->dvi.line_thickness < 0) {
79 desired_line_width = (((dw->dvi.device_resolution
80 * dw->dvi.state->font_size) + 5*72)
81 / (10*72));
82 if (desired_line_width == 0)
83 desired_line_width = 1;
85 else
86 desired_line_width = dw->dvi.line_thickness;
88 if (desired_line_width != dw->dvi.line_width) {
89 XGCValues values;
90 values.line_width = desired_line_width;
91 XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
92 GCLineWidth, &values);
93 dw->dvi.line_width = desired_line_width;
97 static
98 setFillGC (dw)
99 DviWidget dw;
101 int fill_type;
103 if (dw->dvi.fill == DVI_FILL_MAX)
104 fill_type = DVI_FILL_BLACK;
105 else if (dw->dvi.fill == 0)
106 fill_type = DVI_FILL_WHITE;
107 else
108 fill_type = DVI_FILL_GRAY;
109 if (dw->dvi.fill_type != fill_type) {
110 XGCValues values;
111 switch (fill_type) {
112 case DVI_FILL_WHITE:
113 values.foreground = dw->dvi.background;
114 values.fill_style = FillSolid;
115 break;
116 case DVI_FILL_BLACK:
117 values.foreground = dw->dvi.foreground;
118 values.fill_style = FillSolid;
119 break;
120 case DVI_FILL_GRAY:
121 values.foreground = dw->dvi.foreground;
122 values.fill_style = FillOpaqueStippled;
123 break;
125 XChangeGC(XtDisplay (dw), dw->dvi.fill_GC,
126 GCFillStyle|GCForeground,
127 &values);
128 dw->dvi.fill_type = fill_type;
132 DrawLine (dw, x, y)
133 DviWidget dw;
134 int x, y;
136 setGC (dw);
137 XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
138 dw->dvi.state->x, dw->dvi.state->y,
139 dw->dvi.state->x + x, dw->dvi.state->y + y);
142 DrawCircle (dw, diam)
143 DviWidget dw;
144 int diam;
146 setGC (dw);
147 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
148 dw->dvi.state->x, dw->dvi.state->y - diam/2,
149 diam, diam, 0, 64*360);
152 DrawFilledCircle (dw, diam)
153 DviWidget dw;
154 int diam;
156 setFillGC (dw);
157 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
158 dw->dvi.state->x, dw->dvi.state->y - diam/2,
159 diam, diam, 0, 64*360);
162 DrawEllipse (dw, a, b)
163 DviWidget dw;
164 int a, b;
166 setGC (dw);
167 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
168 dw->dvi.state->x, dw->dvi.state->y - b/2,
169 a, b, 0, 64*360);
172 DrawFilledEllipse (dw, a, b)
173 DviWidget dw;
174 int a, b;
176 setFillGC (dw);
177 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
178 dw->dvi.state->x, dw->dvi.state->y - b/2,
179 a, b, 0, 64*360);
182 DrawArc (dw, x0, y0, x1, y1)
183 DviWidget dw;
184 int x0, y0, x1, y1;
186 int x, y;
187 int angle1, angle2;
188 int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
189 + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
190 if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
191 return;
192 angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
193 angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
195 angle2 -= angle1;
196 if (angle2 < 0)
197 angle2 += 64*360;
199 setGC (dw);
200 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
201 dw->dvi.state->x + x0 - rad, dw->dvi.state->y + y0 - rad,
202 rad*2, rad*2, angle1, angle2);
205 DrawPolygon (dw, v, n)
206 DviWidget dw;
207 int *v;
208 int n;
210 extern char *malloc();
211 XPoint *p;
212 int i;
214 n /= 2;
216 setGC (dw);
217 p = (XPoint *)malloc((n + 2)*sizeof(XPoint));
218 if (p == NULL)
219 return;
220 p[0].x = dw->dvi.state->x;
221 p[0].y = dw->dvi.state->y;
222 for (i = 0; i < n; i++) {
223 p[i + 1].x = v[2*i] + p[i].x;
224 p[i + 1].y = v[2*i + 1] + p[i].y;
226 p[n+1].x = dw->dvi.state->x;
227 p[n+1].y = dw->dvi.state->y;
228 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
229 p, n + 2, CoordModeOrigin);
230 free(p);
234 DrawFilledPolygon (dw, v, n)
235 DviWidget dw;
236 int *v;
237 int n;
239 extern char *malloc();
240 XPoint *p;
241 int i;
243 n /= 2;
244 if (n < 2)
245 return;
247 setFillGC (dw);
248 p = (XPoint *)malloc((n + 1)*sizeof(XPoint));
249 if (p == NULL)
250 return;
251 p[0].x = dw->dvi.state->x;
252 p[0].y = dw->dvi.state->y;
253 for (i = 0; i < n; i++) {
254 p[i + 1].x = v[2*i];
255 p[i + 1].y = v[2*i + 1];
257 XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
258 p, n + 1, Complex, CoordModePrevious);
259 free(p);
262 #define POINTS_MAX 10000
264 static
265 appendPoint(points, pointi, x, y)
266 XPoint *points;
267 int *pointi;
268 int x, y;
270 if (*pointi < POINTS_MAX) {
271 points[*pointi].x = x;
272 points[*pointi].y = y;
273 *pointi += 1;
277 #define FLATNESS 1
279 static
280 flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
281 XPoint *points;
282 int *pointi;
283 int x2, y2, x3, y3, x4, y4;
285 int x1, y1, dx, dy, n1, n2, n;
287 x1 = points[*pointi - 1].x;
288 y1 = points[*pointi - 1].y;
290 dx = x4 - x1;
291 dy = y4 - y1;
293 n1 = dy*(x2 - x1) - dx*(y2 - y1);
294 n2 = dy*(x3 - x1) - dx*(y3 - y1);
295 if (n1 < 0)
296 n1 = -n1;
297 if (n2 < 0)
298 n2 = -n2;
299 n = n1 > n2 ? n1 : n2;
301 if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
302 appendPoint (points, pointi, x4, y4);
303 else {
304 flattenCurve (points, pointi,
305 (x1 + x2)/2, (y1 + y2)/2,
306 (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
307 (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
308 flattenCurve (points, pointi,
309 (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
310 (x3 + x4)/2, (y3 + y4)/2,
311 x4, y4);
316 DrawSpline (dw, v, n)
317 DviWidget dw;
318 int *v;
319 int n;
321 int sx, sy, tx, ty, ux, uy;
322 int i;
323 int pointi;
324 XPoint points[POINTS_MAX];
326 if (n == 0 || (n & 1) != 0)
327 return;
328 setGC (dw);
329 sx = dw->dvi.state->x;
330 sy = dw->dvi.state->y;
331 tx = sx + v[0];
332 ty = sy + v[1];
334 pointi = 0;
336 appendPoint (points, &pointi, sx, sy);
337 appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
339 for (i = 2; i < n; i += 2) {
340 int ux = tx + v[i];
341 int uy = ty + v[i+1];
342 flattenCurve (points, &pointi,
343 (sx + tx*5)/6, (sy + ty*5)/6,
344 (tx*5 + ux)/6, (ty*5 + uy)/6,
345 (tx + ux)/2, (ty + uy)/2);
346 sx = tx;
347 sy = ty;
348 tx = ux;
349 ty = uy;
352 appendPoint (points, &pointi, tx, ty);
354 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
355 points, pointi, CoordModeOrigin);
360 Local Variables:
361 c-indent-level: 8
362 c-continued-statement-offset: 8
363 c-brace-offset: -8
364 c-argdecl-indent: 8
365 c-label-offset: -8
366 c-tab-always-indent: nil
367 End: