Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / groff / src / xditview / draw.c
1 /*
2  * draw.c
3  *
4  * accept dvi function calls and translate to X
5  */
6
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>
13
14 /* math.h on a Sequent doesn't define M_PI, apparently */
15 #ifndef M_PI
16 #define M_PI    3.14159265358979323846
17 #endif
18
19 #include "DviP.h"
20
21 #define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
22 #define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
23                   (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
24 #define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
25
26 static int FakeCharacter();
27
28 HorizontalMove(dw, delta)
29         DviWidget       dw;
30         int             delta;
31 {
32         dw->dvi.state->x += delta;
33 }
34
35 HorizontalGoto(dw, NewPosition)
36         DviWidget       dw;
37         int             NewPosition;
38 {
39         dw->dvi.state->x = NewPosition;
40 }
41
42 VerticalMove(dw, delta)
43         DviWidget       dw;
44         int             delta;
45 {
46         dw->dvi.state->y += delta;
47 }
48
49 VerticalGoto(dw, NewPosition)
50         DviWidget       dw;
51         int             NewPosition;
52 {
53         dw->dvi.state->y = NewPosition;
54 }
55
56 AdjustCacheDeltas (dw)
57         DviWidget       dw;
58 {
59         int extra;
60         int nadj;
61         int i;
62
63         nadj = 0;
64         extra = DeviceToX(dw, dw->dvi.text_device_width)
65                 - dw->dvi.text_x_width;
66         if (extra == 0)
67                 return;
68         for (i = 0; i <= dw->dvi.cache.index; i++)
69                 if (dw->dvi.cache.adjustable[i])
70                         ++nadj;
71         if (nadj == 0)
72                 return;
73         dw->dvi.text_x_width += extra;
74         for (i = 0; i <= dw->dvi.cache.index; i++)
75                 if (dw->dvi.cache.adjustable[i]) {
76                         int x;
77                         int *deltap;
78
79                         x = extra/nadj;
80                         deltap = &dw->dvi.cache.cache[i].delta;
81 #define MIN_DELTA 2
82                         if (*deltap > 0 && x + *deltap < MIN_DELTA) {
83                                 x = MIN_DELTA - *deltap;
84                                 if (x <= 0)
85                                         *deltap = MIN_DELTA;
86                                 else
87                                         x = 0;
88                         }
89                         else
90                                 *deltap += x;
91                         extra -= x;
92                         --nadj;
93                         dw->dvi.cache.adjustable[i] = 0;
94                 }
95 }
96
97 FlushCharCache (dw)
98         DviWidget       dw;
99 {
100         if (dw->dvi.cache.char_index != 0) {
101                 AdjustCacheDeltas (dw);
102                 XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
103                            dw->dvi.cache.start_x, dw->dvi.cache.start_y,
104                            dw->dvi.cache.cache, dw->dvi.cache.index + 1);
105         }       
106         dw->dvi.cache.index = 0;
107         dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
108 #if 0
109         if (dw->dvi.noPolyText)
110             dw->dvi.cache.max = 1;
111 #endif
112         dw->dvi.cache.char_index = 0;
113         dw->dvi.cache.cache[0].nchars = 0;
114         dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
115         dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
116 }
117
118 Newline (dw)
119         DviWidget       dw;
120 {
121         FlushCharCache (dw);
122         dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
123         dw->dvi.word_flag = 0;
124 }
125
126 Word (dw)
127         DviWidget       dw;
128 {
129         dw->dvi.word_flag = 1;
130 }
131
132 #define charWidth(fi,c) (\
133     (fi)->per_char ?\
134         (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
135     :\
136         (fi)->max_bounds.width\
137 )
138  
139
140 static
141 int charExists (fi, c)
142         XFontStruct     *fi;
143         int             c;
144 {
145         XCharStruct *p;
146
147         if (fi->per_char == NULL ||
148             c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
149                 return 0;
150         p = fi->per_char + (c - fi->min_char_or_byte2);
151         return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
152                 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
153 }
154
155 static
156 DoCharacter (dw, c, wid)
157         DviWidget dw;
158         int c;
159         int wid;    /* width in device units */
160 {
161         register XFontStruct    *font;
162         register XTextItem      *text;
163         int     x, y;
164         
165         x = XPos(dw);
166         y = YPos(dw);
167
168         /*
169          * quick and dirty extents calculation:
170          */
171         if (!(y + 24 >= dw->dvi.extents.y1
172               && y - 24 <= dw->dvi.extents.y2
173 #if 0
174               && x + 24 >= dw->dvi.extents.x1
175               && x - 24 <= dw->dvi.extents.x2
176 #endif
177             ))
178                 return;
179         
180         if (y != dw->dvi.cache.y
181             || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
182                 FlushCharCache (dw);
183                 x = dw->dvi.cache.x;
184         }
185         /*
186          * load a new font, if the current block is not empty,
187          * step to the next.
188          */
189         if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
190             dw->dvi.cache.font_number != dw->dvi.state->font_number)
191         {
192                 dw->dvi.cache.font_size = dw->dvi.state->font_size;
193                 dw->dvi.cache.font_number = dw->dvi.state->font_number;
194                 dw->dvi.cache.font = QueryFont (dw,
195                                                 dw->dvi.cache.font_number,
196                                                 dw->dvi.cache.font_size);
197                 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
198                         ++dw->dvi.cache.index;
199                         if (dw->dvi.cache.index >= dw->dvi.cache.max)
200                                 FlushCharCache (dw);
201                         dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
202                         dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
203                 }
204         }
205         if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
206                 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
207                         ++dw->dvi.cache.index;
208                         if (dw->dvi.cache.index >= dw->dvi.cache.max)
209                                 FlushCharCache (dw);
210                         dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
211                 }
212                 dw->dvi.cache.adjustable[dw->dvi.cache.index]
213                         = dw->dvi.word_flag;
214                 dw->dvi.word_flag = 0;
215         }
216         font = dw->dvi.cache.font;
217         text = &dw->dvi.cache.cache[dw->dvi.cache.index];
218         if (text->nchars == 0) {
219                 text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
220                 text->delta = x - dw->dvi.cache.x;
221                 if (font != dw->dvi.font) {
222                         text->font = font->fid;
223                         dw->dvi.font = font;
224                 } else
225                         text->font = None;
226                 dw->dvi.cache.x += text->delta;
227         }
228         if (charExists(font, c)) {
229                 int w;
230                 dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
231                 ++text->nchars;
232                 w = charWidth(font, c);
233                 dw->dvi.cache.x += w;
234                 if (wid != 0) {
235                         dw->dvi.text_x_width += w;
236                         dw->dvi.text_device_width += wid;
237                 }
238         }
239 }
240
241 static
242 int FindCharWidth (dw, buf, widp)
243         DviWidget dw;
244         char *buf;
245         int *widp;
246 {
247         int maxpos;
248         int i;
249
250         if (dw->dvi.device_font == 0
251             || dw->dvi.state->font_number != dw->dvi.device_font_number) {
252                 dw->dvi.device_font_number = dw->dvi.state->font_number;
253                 dw->dvi.device_font
254                         = QueryDeviceFont (dw, dw->dvi.device_font_number);
255         }
256         if (dw->dvi.device_font
257             && device_char_width (dw->dvi.device_font,
258                                   dw->dvi.state->font_size, buf, widp))
259                 return 1;
260
261         maxpos = MaxFontPosition (dw);
262         for (i = 1; i <= maxpos; i++) {
263                 DeviceFont *f = QueryDeviceFont (dw, i);
264                 if (f && device_font_special (f)
265                     && device_char_width (f, dw->dvi.state->font_size,
266                                           buf, widp)) {
267                         dw->dvi.state->font_number = i;
268                         return 1;
269                 }
270         }
271         return 0;
272 }
273
274 /* Return the width of the character in device units. */
275
276 int PutCharacter (dw, buf)
277         DviWidget dw;
278         char *buf;
279 {
280         int             prevFont;
281         int             c = -1;
282         int             wid = 0;
283         DviCharNameMap  *map;
284
285         if (!dw->dvi.display_enable)
286                 return 0;       /* The width doesn't matter in this case. */
287         prevFont = dw->dvi.state->font_number;
288         if (!FindCharWidth (dw, buf, &wid))
289                 return 0;
290         map = QueryFontMap (dw, dw->dvi.state->font_number);
291         if (map)
292                 c = DviCharIndex (map, buf);
293         if (c >= 0)
294                 DoCharacter (dw, c, wid);
295         else
296                 (void) FakeCharacter (dw, buf, wid);
297         dw->dvi.state->font_number = prevFont;
298         return wid;
299 }
300
301 /* Return 1 if we can fake it; 0 otherwise. */
302
303 static
304 int FakeCharacter (dw, buf, wid)
305         DviWidget dw;
306         char *buf;
307         int wid;
308 {
309         int oldx, oldw;
310         char ch[2];
311         char *chars = 0;
312
313         if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
314                 return 0;
315 #define pack2(c1, c2) (((c1) << 8) | (c2))
316
317         switch (pack2(buf[0], buf[1])) {
318         case pack2('f', 'i'):
319                 chars = "fi";
320                 break;
321         case pack2('f', 'l'):
322                 chars = "fl";
323                 break;
324         case pack2('f', 'f'):
325                 chars = "ff";
326                 break;
327         case pack2('F', 'i'):
328                 chars = "ffi";
329                 break;
330         case pack2('F', 'l'):
331                 chars = "ffl";
332                 break;
333         }
334         if (!chars)
335                 return 0;
336         oldx = dw->dvi.state->x;
337         oldw = dw->dvi.text_device_width;
338         ch[1] = '\0';
339         for (; *chars; chars++) {
340                 ch[0] = *chars;
341                 dw->dvi.state->x += PutCharacter (dw, ch);
342         }
343         dw->dvi.state->x = oldx;
344         dw->dvi.text_device_width = oldw + wid;
345         return 1;
346 }
347
348 PutNumberedCharacter (dw, c)
349         DviWidget dw;
350         int c;
351 {
352         char *name;
353         int wid;
354         DviCharNameMap  *map;
355
356         if (!dw->dvi.display_enable)
357                 return;
358
359         if (dw->dvi.device_font == 0
360             || dw->dvi.state->font_number != dw->dvi.device_font_number) {
361                 dw->dvi.device_font_number = dw->dvi.state->font_number;
362                 dw->dvi.device_font
363                         = QueryDeviceFont (dw, dw->dvi.device_font_number);
364         }
365         
366         if (dw->dvi.device_font == 0
367             || !device_code_width (dw->dvi.device_font,
368                                    dw->dvi.state->font_size, c, &wid))
369                 return;
370         if (dw->dvi.native) {
371                 DoCharacter (dw, c, wid);
372                 return;
373         }
374         map = QueryFontMap (dw, dw->dvi.state->font_number);
375         if (!map)
376                 return;
377         for (name = device_name_for_code (dw->dvi.device_font, c);
378              name;
379              name = device_name_for_code ((DeviceFont *)0, c)) {
380                 int code = DviCharIndex (map, name);
381                 if (code >= 0) {
382                         DoCharacter (dw, code, wid);
383                         break;
384                 }
385                 if (FakeCharacter (dw, name, wid))
386                         break;
387         }
388 }
389
390 ClearPage (dw)
391         DviWidget       dw;
392 {
393         XClearWindow (XtDisplay (dw), XtWindow (dw));
394 }
395
396 static
397 setGC (dw)
398         DviWidget       dw;
399 {
400         int desired_line_width;
401         
402         if (dw->dvi.line_thickness < 0)
403                 desired_line_width = (int)(((double)dw->dvi.device_resolution
404                                             * dw->dvi.state->font_size)
405                                            / (10.0*72.0*dw->dvi.sizescale));
406         else
407                 desired_line_width = dw->dvi.line_thickness;
408         
409         if (desired_line_width != dw->dvi.line_width) {
410                 XGCValues values;
411                 values.line_width = DeviceToX(dw, desired_line_width);
412                 if (values.line_width == 0)
413                         values.line_width = 1;
414                 XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
415                           GCLineWidth, &values);
416                 dw->dvi.line_width = desired_line_width;
417         }
418 }
419
420 static
421 setFillGC (dw)
422         DviWidget       dw;
423 {
424         int fill_type;
425         unsigned long mask = GCFillStyle | GCForeground;
426
427         fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1);
428         if (dw->dvi.fill_type != fill_type) {
429                 XGCValues values;
430                 if (fill_type <= 0) {
431                         values.foreground = dw->dvi.background;
432                         values.fill_style = FillSolid;
433                 } else if (fill_type >= 9) {
434                         values.foreground = dw->dvi.foreground;
435                         values.fill_style = FillSolid;
436                 } else {
437                         values.foreground = dw->dvi.foreground;
438                         values.fill_style = FillOpaqueStippled;
439                         values.stipple = dw->dvi.gray[fill_type - 1];
440                         mask |= GCStipple;
441                 }
442                 XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values);
443                 dw->dvi.fill_type = fill_type;
444         }
445 }
446
447 DrawLine (dw, x, y)
448         DviWidget       dw;
449         int             x, y;
450 {
451         int xp, yp;
452
453         AdjustCacheDeltas (dw);
454         setGC (dw);
455         xp = XPos (dw);
456         yp = YPos (dw);
457         XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
458                    xp, yp,
459                    xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
460 }
461
462 DrawCircle (dw, diam)
463         DviWidget       dw;
464         int             diam;
465 {
466         int d;
467
468         AdjustCacheDeltas (dw);
469         setGC (dw);
470         d = DeviceToX (dw, diam);
471         XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
472                   XPos (dw), YPos (dw) - d/2,
473                   d, d, 0, 64*360);
474 }
475
476 DrawFilledCircle (dw, diam)
477         DviWidget       dw;
478         int             diam;
479 {
480         int d;
481
482         AdjustCacheDeltas (dw);
483         setFillGC (dw);
484         d = DeviceToX (dw, diam);
485         XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
486                   XPos (dw), YPos (dw) - d/2,
487                   d, d, 0, 64*360);
488         XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
489                   XPos (dw), YPos (dw) - d/2,
490                   d, d, 0, 64*360);
491 }
492
493 DrawEllipse (dw, a, b)
494         DviWidget       dw;
495         int             a, b;
496 {
497         AdjustCacheDeltas (dw);
498         setGC (dw);
499         XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
500                   XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
501                   DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
502 }
503
504 DrawFilledEllipse (dw, a, b)
505         DviWidget       dw;
506         int             a, b;
507 {
508         AdjustCacheDeltas (dw);
509         setFillGC (dw);
510         XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
511                   XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
512                   DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
513         XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
514                   XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
515                   DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
516 }
517
518 DrawArc (dw, x0, y0, x1, y1)
519         DviWidget       dw;
520         int             x0, y0, x1, y1;
521 {
522         int angle1, angle2;
523         int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
524                         + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
525         if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
526                 return;
527         angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
528         angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
529         
530         angle2 -= angle1;
531         if (angle2 < 0)
532                 angle2 += 64*360;
533         
534         AdjustCacheDeltas (dw);
535         setGC (dw);
536
537         rad = DeviceToX (dw, rad);
538         XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
539                   XPos (dw) + DeviceToX (dw, x0) - rad,
540                   YPos (dw) + DeviceToX (dw, y0) - rad,
541                   rad*2, rad*2, angle1, angle2);
542 }
543
544 DrawPolygon (dw, v, n)
545         DviWidget       dw;
546         int             *v;
547         int             n;
548 {
549         XPoint *p;
550         int i;
551         int dx, dy;
552         
553         n /= 2;
554         
555         AdjustCacheDeltas (dw);
556         setGC (dw);
557         p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
558         p[0].x = XPos (dw);
559         p[0].y = YPos (dw);
560         dx = 0;
561         dy = 0;
562         for (i = 0; i < n; i++) {
563                 dx += v[2*i];
564                 p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
565                 dy += v[2*i + 1];
566                 p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
567         }
568         p[n+1].x = p[0].x;
569         p[n+1].y = p[0].y;
570         XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
571                    p, n + 2, CoordModeOrigin);
572         XtFree((char *)p);
573 }
574
575
576 DrawFilledPolygon (dw, v, n)
577         DviWidget       dw;
578         int             *v;
579         int             n;
580 {
581         XPoint *p;
582         int i;
583         int dx, dy;
584         
585         n /= 2;
586         if (n < 2)
587                 return;
588         
589         AdjustCacheDeltas (dw);
590         setFillGC (dw);
591         p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
592         p[0].x = p[n+1].x = XPos (dw);
593         p[0].y = p[n+1].y = YPos (dw);
594         dx = 0;
595         dy = 0;
596         for (i = 0; i < n; i++) {
597                 dx += v[2*i];
598                 p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
599                 dy += v[2*i + 1];
600                 p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
601         }
602         XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
603                       p, n + 1, Complex, CoordModeOrigin);
604         XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
605                       p, n + 2, CoordModeOrigin);
606         XtFree((char *)p);
607 }
608
609 #define POINTS_MAX 10000
610
611 static
612 appendPoint(points, pointi, x, y)
613         XPoint  *points;
614         int     *pointi;
615         int     x, y;
616 {
617         if (*pointi < POINTS_MAX) {
618                 points[*pointi].x = x;
619                 points[*pointi].y = y;
620                 *pointi += 1;
621         }
622 }
623
624 #define FLATNESS 1
625
626 static
627 flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
628         XPoint  *points;
629         int     *pointi;
630         int     x2, y2, x3, y3, x4, y4;
631 {
632         int x1, y1, dx, dy, n1, n2, n;
633
634         x1 = points[*pointi - 1].x;
635         y1 = points[*pointi - 1].y;
636         
637         dx = x4 - x1;
638         dy = y4 - y1;
639         
640         n1 = dy*(x2 - x1) - dx*(y2 - y1);
641         n2 = dy*(x3 - x1) - dx*(y3 - y1);
642         if (n1 < 0)
643                 n1 = -n1;
644         if (n2 < 0)
645                 n2 = -n2;
646         n = n1 > n2 ? n1 : n2;
647
648         if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
649                 appendPoint (points, pointi, x4, y4);
650         else {
651                 flattenCurve (points, pointi,
652                               (x1 + x2)/2, (y1 + y2)/2,
653                               (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
654                               (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
655                 flattenCurve (points, pointi,
656                               (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
657                               (x3 + x4)/2, (y3 + y4)/2,
658                               x4, y4);
659         }
660 }
661
662
663 DrawSpline (dw, v, n)
664         DviWidget       dw;
665         int             *v;
666         int             n;
667 {
668         int sx, sy, tx, ty;
669         int ox, oy, dx, dy;
670         int i;
671         int pointi;
672         XPoint points[POINTS_MAX];
673         
674         if (n == 0 || (n & 1) != 0)
675                 return;
676         AdjustCacheDeltas (dw);
677         setGC (dw);
678         ox = XPos (dw);
679         oy = YPos (dw);
680         dx = v[0];
681         dy = v[1];
682         sx = ox;
683         sy = oy;
684         tx = sx + DeviceToX (dw, dx);
685         ty = sy + DeviceToX (dw, dy);
686         
687         pointi = 0;
688         
689         appendPoint (points, &pointi, sx, sy);
690         appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
691         
692         for (i = 2; i < n; i += 2) {
693                 int ux = ox + DeviceToX (dw, dx += v[i]);
694                 int uy = oy + DeviceToX (dw, dy += v[i+1]);
695                 flattenCurve (points, &pointi,
696                                (sx + tx*5)/6, (sy + ty*5)/6,
697                                (tx*5 + ux)/6, (ty*5 + uy)/6,
698                                (tx + ux)/2, (ty + uy)/2);
699                 sx = tx;
700                 sy = ty;
701                 tx = ux;
702                 ty = uy;
703         }
704         
705         appendPoint (points, &pointi, tx, ty);
706         
707         XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
708                    points, pointi, CoordModeOrigin);
709 }
710
711
712 /*
713 Local Variables:
714 c-indent-level: 8
715 c-continued-statement-offset: 8
716 c-brace-offset: -8
717 c-argdecl-indent: 8
718 c-label-offset: -8
719 c-tab-always-indent: nil
720 End:
721 */