|
|
1.1 root 1: /* $Header: XDraw.c,v 1.2 87/08/28 13:34:18 toddb Exp $ */
2: #include "copyright.h"
3:
4: /* Copyright Massachusetts Institute of Technology 1987 */
5:
6: #include "Xlibint.h"
7: #include "Xlib.h"
8: #include "X10.h"
9:
10: #define OK_RETURN 1
11: #define ERR_RETURN 0
12: #define NULL 0
13:
14: /*
15: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
16: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
17:
18: All Rights Reserved
19:
20: Permission to use, copy, modify, and distribute this software and its
21: documentation for any purpose and without fee is hereby granted,
22: provided that the above copyright notice appear in all copies and that
23: both that copyright notice and this permission notice appear in
24: supporting documentation, and that the names of Digital or MIT not be
25: used in advertising or publicity pertaining to distribution of the
26: software without specific, written prior permission.
27:
28: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
29: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
30: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
31: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
32: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
33: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
34: SOFTWARE.
35:
36: */
37:
38: /*
39: *
40: * Vertices_converter: This internal routine takes a list of Vertices and
41: * returns another list of Vertices such that the
42: * following is true:
43: *
44: * (1) No Vertex has the VertexRelative flag on
45: * (2) No Vertex has the VertexCurved flag on
46: * (3) The first Vertex has the VertexDontDraw flag on
47: * (4) The path that the return Vertex list specifies should
48: * be drawn on the screen is very close to the path that the
49: * Vertex list passed to vertices_converter specified should be
50: * drawn. The difference is due solely to the approximation
51: * of curved segments in the original Vertex list by many
52: * small straight line segments that approximate the curve.
53: *
54: * Notes:
55: *
56: * (1) The first Vertex must have the VertexRelative flag
57: * turned off. (This is not checked, just assumed)
58: * (2) VertexDontDraw is automatically turned on for the first
59: * Vertex because drawing to the first Vertex makes no sense.
60: * (3) This routine is used only by XDraw & XDrawFilled.
61: * (4) A 0 is returned iff no error occurs.
62: * (5) The passed Vertex list not changed in any way.
63: *
64: * Implementation:
65: *
66: * A routine from the qvss device dependent code library from the
67: * X version 10 sources written by DEC was used, abet slightly
68: * modified as it provided 99% of the desired functionality.
69: *
70: */
71:
72: /*****************************************************************************/
73: /* */
74: /* WRITTEN BY DARYL F. HAZEL 8509.06 */
75: /* */
76: /* Modification history: */
77: /* */
78: /* Carver 8510.23 Fixed first time allocation of the coord buffer */
79: /* to allocate max(200, pathcount) amount insted of just */
80: /* 200. Potential Xserver crash problem. */
81: /* */
82: /* Carver 8510.21 Replaced old module by module worked on by Ram Rao and */
83: /* Bob Scheifler to get better performace. */
84: /* */
85: /* Carver 8510.03 Changed the curve line converter to return the coord */
86: /* path if a successor point does not exist for curve gen. */
87: /* */
88: /* Carver 8510.03 Fixed memory loss problem. A coord path is only */
89: /* allocated if the current path will not fit in it and */
90: /* before the new coord path is allocated the old one is */
91: /* freed. */
92: /* */
93: /* Carver 8509.24 Fixed pointer/integer mismatch {*ppathaddr_new = ...} */
94: /* */
95: /* Corkum 8509.18 Modify code to intergrate into the draw curve command */
96: /* */
97: /* Modified by Mark Lillibridge 5/20/87 to make into */
98: /* X11 Xlib XDraw() support. */
99: /****************************************************************************/
100:
101: /*
102: * Definitions:
103: *
104: */
105:
106: typedef short WORD;
107: typedef short *WORD_POINTER;
108:
109: /*
110: * Lookup tables, buffers used in the conversion:
111: *
112: */
113:
114:
115: /*
116: * modified path list storage information:
117: */
118: static Vertex *pathaddr_new = NULL; /*pointer to current modified path list*/
119: static int pathlist_bytes = 0; /* size of modified path list in bytes */
120: static int pathlist_segs = 0;/* size of modified path list in segments */
121: static Vertex *pathaddr_coords = NULL; /*ptr to path list with coordinates */
122: static int path_coord_list_bytes = 0; /* size of path list (w/coords) buff */
123: static int path_coord_list_segs = 0; /* size of path list (w/coords) buff */
124:
125: /*
126: * THE TABLE OF PSEUDO FLOATING-POINT NUMBERS WHICH MAKE UP THE
127: * MULTIPLICATIVE COEFFICIENTS FOR THE CUBIC SPLINE ALGORITHM.
128: */
129: static short bntable[] = { 0xfc18, 0x7f97, 0x0476, 0xffde,
130: 0xf8be, 0x7e5d, 0x0972, 0xff76,
131: 0xf5f4, 0x7c56, 0x0eec, 0xfecc,
132: 0xf3ba, 0x7988, 0x14da, 0xfde6,
133: 0xf20b, 0x75fe, 0x1b2f, 0xfcca,
134: 0xf0e2, 0x71c1, 0x21dd, 0xfb81,
135: 0xf038, 0x6ce1, 0x28d3, 0xfa16,
136: 0xf001, 0x676d, 0x3000, 0xf894,
137: 0xf034, 0x6176, 0x3750, 0xf709,
138: 0xf0c3, 0x5b0f, 0x3eae, 0xf583,
139: 0xf1a1, 0x544b, 0x4605, 0xf410,
140: 0xf2c0, 0x4d41, 0x4d41, 0xf2c0,
141: 0xf410, 0x4605, 0x544b, 0xf1a1,
142: 0xf583, 0x3eae, 0x5b0f, 0xf0c3,
143: 0xf709, 0x3750, 0x6176, 0xf034,
144: 0xf894, 0x3000, 0x676d, 0xf001,
145: 0xfa16, 0x28d3, 0x6ce1, 0xf038,
146: 0xfb81, 0x21dd, 0x71c1, 0xf0e2,
147: 0xfcca, 0x1b2f, 0x75fe, 0xf20b,
148: 0xfde6, 0x14da, 0x7988, 0xf3ba,
149: 0xfecc, 0x0eec, 0x7c56, 0xf5f4,
150: 0xff76, 0x0972, 0x7e5d, 0xf8be,
151: 0xffde, 0x0476, 0x7f97, 0xfc18
152: };
153:
154: /*
155: * this is the table which determines how many straight-line segments to draw
156: * for a given curved segment.
157: */
158: static short segtable[] = { 10, 3, 56, /* pl <= 10, 3 segments */
159: 32, 4, 40, /* pl <= 32, 4 segments */
160: 80, 6, 24, /* pl <= 80, 6 segments */
161: 96, 8, 16, /* pl <= 96, 8 segments */
162: 192, 12, 8, /* pl <= 192, 12 segments */
163: 32767, 24, 00 /* pl <= 32767, 24 segments */
164: };
165:
166: /*
167: *
168: * The Real routine:
169: *
170: */
171:
172: static vertices_converter(pathaddr, pathcount, ppathaddr_new, newpathcnt)
173: Vertex *pathaddr; /* address of original path list */
174: int pathcount; /* number of points in original path list */
175: Vertex **ppathaddr_new; /* ptr to addr of new path list */
176: int *newpathcnt; /* ptr to new number of pts in path list */
177: {
178: int p0x, p0y; /* coordinates of curve's predecessor point */
179: int p1x, p1y; /* coordinates of curve's starting point */
180: int p2x, p2y; /* coordinates of curve's ending point */
181: int p3x, p3y; /* coordinates of curve's successor point */
182: int flag; /* flag word of current end-point in p.list */
183: int successor_x = 0; /* X coordinate of curve's successor point */
184: int successor_y = 0; /* Y coordinate of curve's successor point */
185: WORD increment; /* bntable-ptr-increment value */
186: WORD diffx, diffy; /* absolute values of x, y end-point diffs */
187: WORD lmajoraxis; /* "length" of seg projected onto major axis */
188: union /* accumulator variables for computing end-points... */
189: { /* ...using the bntable. */
190: struct
191: {
192: WORD low;
193: WORD high;
194: } sword;
195: int lword;
196: } xxe, yye;
197: register Vertex *pnewpath;/* pointer for traversing modified path list */
198: int newpathcount; /* number of end-points in modified path list*/
199: register Vertex *pflag; /* pointer used for looking for fig's last pt*/
200: int i; /* general-purpose loop variable */
201: int ecf_flag_set; /* flag indicating existence of set ECF flag */
202: int count;
203: int curve_flag; /* 0 = no curves in path; 1 = curves in path */
204:
205: {
206: register Vertex *poldpath;/* pointer for traversing original path list */
207: register Vertex *p_coord_path; /* ptr to path list with coordinates */
208:
209: /* Init the return path count to 0 in case of error */
210: *newpathcnt = 0;
211: newpathcount = 0;
212:
213: /* Use path buffers from last time */
214: pnewpath = pathaddr_new;
215: p_coord_path = pathaddr_coords;
216:
217: /*
218: * if size of coordinate path list buffer is not at least large enough to
219: * accommodate the specified path list, allocate enough memory to do so
220: */
221: if (path_coord_list_segs == 0) /* first time through*/
222: {
223: path_coord_list_segs = max (200, pathcount);
224: path_coord_list_bytes = path_coord_list_segs * sizeof(Vertex);
225: if ((pathaddr_coords = (Vertex *)Xmalloc(path_coord_list_bytes)) != 0)
226: p_coord_path = pathaddr_coords;
227: else
228: return(ERR_RETURN);
229: }
230: else /* all but first time through */
231: {
232: /* If coord buffer is large enough for this path then reuse it, other
233: wise free the old one and get a new one (Carver) 8510.03 */
234: if (path_coord_list_segs < pathcount)
235: {
236: Xfree( pathaddr_coords);
237: path_coord_list_segs = pathcount;
238: path_coord_list_bytes = path_coord_list_segs * sizeof(Vertex);
239: if ((pathaddr_coords =(Vertex *)Xmalloc(path_coord_list_bytes)) !=0)
240: p_coord_path = pathaddr_coords;
241: else
242: return(ERR_RETURN);
243: };
244: }
245:
246: /*
247: * Copy given Vertex list (pathaddr) to coordinate buffer converting
248: * relative coordinates to absolute coordinates.
249: *
250: * Sets curve_flag iff at least one Vertex has the VertexCurved flag set.
251: *
252: */
253:
254: poldpath = pathaddr;
255: curve_flag = 0;
256:
257: *p_coord_path = *poldpath++; /* First Vertex is a special case */
258: p_coord_path->flags = (p_coord_path->flags | VertexDontDraw)
259: & ~VertexRelative;
260: if ((p_coord_path++)->flags & VertexCurved)
261: curve_flag = 1;
262: for (i = pathcount - 1; i > 0; i--)
263: {
264: if (poldpath->flags & VertexRelative)
265: { /* compute coordinates using last pt */
266: p_coord_path->x = poldpath->x + p_coord_path[-1].x;
267: p_coord_path->y = poldpath->y + p_coord_path[-1].y;
268: p_coord_path->flags = poldpath->flags & ~VertexRelative;
269: }
270: else *p_coord_path++ = *poldpath;
271: if ((poldpath++)->flags & VertexCurved)
272: curve_flag = 1;
273: }
274: } /* End of scope for poldaddr, p_coord_path */
275:
276: /*
277: * if it has been determined that there are no curved segment end points in
278: * the specified path list, return the path list containing the coordinates
279: * to the calling routine.
280: */
281: if (!curve_flag)
282: {
283: *newpathcnt = pathcount;
284: *ppathaddr_new = pathaddr_coords;
285: return(OK_RETURN);
286: }
287:
288: /*
289: * if size of modified path list buffer is not at least large enough to
290: * accommodate the specified path list allocate enough memory to do so
291: */
292: pathaddr = pathaddr_coords;
293: if (pathlist_segs < pathcount)
294: {
295: if (pathlist_segs == 0) /* Fix storage leak -- MDL 5/20/87 */
296: Xfree( pathaddr_new );
297: pathlist_segs = pathcount;
298: pathlist_bytes = pathcount * sizeof(Vertex);
299: if ((pathaddr_new = (Vertex *)Xmalloc(pathlist_bytes)) != 0)
300: pnewpath = pathaddr_new;
301: else
302: return(ERR_RETURN);
303: }
304:
305: /*
306: * initialize the beginning and ending coordinates of the first segment
307: */
308: p1x = 0;
309: p1y = 0;
310: p2x = 0;
311: p2y = 0;
312:
313: {
314: register WORD *pbntable; /* table of multiplicative coeffics.*/
315: register WORD *psegtable; /* table used to detrmn num.sub-segs*/
316: register WORD m; /* num segments into which curve is divided */
317:
318: /*
319: * MAIN LOOP OF THE PATH_LIST_CONVERTER ROUTINE
320: */
321: for ( count=pathcount ; count > 0; count--)
322: {
323: p0x = p1x; /* save previous values of path-list coordinate pairs*/
324: p0y = p1y;
325: p1x = p2x;
326: p1y = p2y;
327:
328: /*
329: * read next end-point's coordinates from the path list
330: */
331: p2x = pathaddr->x;
332: p2y = pathaddr->y;
333: flag = (pathaddr++)->flags;
334:
335: /*
336: * CURVED-segment considerations
337: */
338: if (flag & VertexCurved)
339: {
340: /*
341: * determine which point to use as the successor point: the next
342: * point in the list (if there is one), or a previously-saved point
343: * (when drawing closed figures)
344: */
345: if (flag & VertexEndClosed) /* last segment of closed fig*/
346: {
347: p3x = successor_x;
348: p3y = successor_y;
349: }
350: else /* stand-alone curved segment*/
351: {
352: if (count <= 1) /* no points to use as successor pt */
353: {
354:
355: /* in this case draw the coord path */
356: *newpathcnt = pathcount;
357: *ppathaddr_new = pathaddr_coords;
358: return(OK_RETURN);
359: }
360: else
361: {
362: /*
363: * read next end-point's coordinates from the path list...
364: */
365: p3x = pathaddr->x;
366: p3y = pathaddr->y;
367:
368: if (flag & VertexStartClosed)
369: { /* first segment of closed figure */
370: /*
371: * save P3 as successor pt for closed-fig-ending curve
372: */
373: successor_x = p3x;
374: successor_y = p3y;
375:
376: /*
377: * Traverse the original path list looking for ECF flag
378: * After finding it, back pointer up to previous point
379: * and save the information for use as curve's pred. pt
380: */
381: ecf_flag_set = 0;
382: pflag = pathaddr;
383: for (i = count; i > 0; i--)
384: {
385: if (pflag->flags & VertexEndClosed)
386: {
387: pflag--;
388: p1x = pflag->x;
389: p1y = pflag->y;
390: ecf_flag_set = 1;
391: break;
392: }
393: pflag++;
394: }
395: if (!ecf_flag_set)
396: return(ERR_RETURN);
397: } /* end code pertaining to starting figure*/
398: } /* end code pertaining to successor points */
399: } /* end code pertaining to stand-alone curved segs*/
400:
401: if ((flag & VertexDontDraw) == 0)
402: {
403: /*
404: * determine the "length" of the segment along the major axis
405: */
406: if ((diffx = p2x - p1x) < 0)
407: diffx = ~diffx + 1;
408: if ((diffy = p2y - p1y) < 0)
409: diffy = ~diffy + 1;
410: lmajoraxis = (diffx >= diffy) ? diffx : diffy;
411: if (lmajoraxis == 0) /* for vector to have length of... */
412: lmajoraxis = 1; /* ...at least one */
413:
414: /*
415: * compute M, the number of sub-segments into which a curved
416: * segment is divided
417: */
418: psegtable = segtable;
419: while (lmajoraxis > *psegtable++)/* search for appropriate..*/
420: psegtable += 2; /* ...table entry */
421: m = *psegtable++; /* read number of segments */
422: increment = *psegtable >> 1;
423:
424: /*
425: * determine if there is enough room remaining in the modified
426: * path-list buffer to hold ALL of the curve's sub-segment in-
427: * formation; if not, double the buffer size (if possible).
428: */
429: while ((newpathcount + m) > pathlist_segs)
430: {
431: pathlist_segs *= 2;
432: pathlist_bytes *= 2;
433: if ((pathaddr_new = (Vertex *)Xrealloc(pathaddr_new,
434: pathlist_bytes)) != 0)
435: pnewpath = pathaddr_new + newpathcount;
436: else
437: return(ERR_RETURN);
438: }
439:
440: /*
441: * generate end-points of sub-segs into which curve is divided
442: */
443: pbntable = bntable; /* initialize the pointer to the Bn table*/
444: for ( ; m > 1; m--)
445: {
446: pbntable += increment;
447: xxe.lword = *pbntable * p0x;
448: yye.lword = *pbntable++ * p0y;
449: xxe.lword += *pbntable * p1x;
450: yye.lword += *pbntable++ * p1y;
451: xxe.lword += *pbntable * p2x;
452: yye.lword += *pbntable++ * p2y;
453: xxe.lword += *pbntable * p3x;
454: yye.lword += *pbntable++ * p3y;
455: xxe.lword = xxe.lword << 1; /* double values... */
456: yye.lword = yye.lword << 1; /* ...bn accts for it*/
457: xxe.lword += 0x8000; /* round off the accum value */
458: yye.lword += 0x8000;
459: pnewpath->x = xxe.sword.high;/* the X coordinate */
460: pnewpath->y = yye.sword.high;/* the Y coordinate */
461: (pnewpath++)->flags = 0; /* the flag word */
462: newpathcount++;/* increment segment end-point countr*/
463: } /* end sub-segment end-point compute loop*/
464: } /* end DRAW-segment considerations code */
465: } /* end CURVED-segment considerations code */
466:
467: /*
468: * put end-point from original path list into modified list
469: */
470: pnewpath->x = p2x;
471: pnewpath->y = p2y;
472: (pnewpath++)->flags = flag & ~VertexCurved;
473: newpathcount++;
474:
475: /*
476: * determine whether or not the modified path list is full, and if so,
477: * double its size
478: */
479: if (newpathcount == pathlist_segs)
480: {
481: pathlist_bytes *= 2;
482: pathlist_segs *= 2;
483: if ((pathaddr_new = (Vertex *)Xrealloc(pathaddr_new,
484: pathlist_bytes)) != 0)
485: pnewpath = pathaddr_new + newpathcount;
486: else
487: return(ERR_RETURN);
488: }
489: } /* END of PATH_LIST_CONVERTER's main loop */
490:
491: /*
492: * return the address of the modified path list and the number of segment
493: * end-points it contains
494: */
495: *newpathcnt = newpathcount;
496: *ppathaddr_new = pathaddr_new;
497: }
498:
499: return(OK_RETURN);
500: }
501:
502: /* Written by Mark Lillibridge */
503:
504: static XPoint *XDraw_points = NULL; /* Buffer to hold list of points for */
505: static int point_count = 0; /* use in calling XDrawLines */
506:
507: Status XDraw (dpy, d, gc, vlist, vcount)
508: register Display *dpy;
509: Drawable d;
510: GC gc;
511: Vertex *vlist;
512: int vcount;
513: {
514: Vertex *newvlist;
515: int newvcount;
516: XPoint *p;
517: int pcount;
518:
519: /* If less than 2 vertices, we don't have to do anything (no lines) */
520: if (vcount<2)
521: return(OK_RETURN);
522:
523: /* Convert curved lines to straight lines & change relative references to */
524: /* absolute references. */
525: if (!vertices_converter( vlist, vcount, &newvlist, &newvcount))
526: return(ERR_RETURN);
527:
528: /* Insure we have enough buffer space */
529: if (point_count < newvcount) {
530: if (point_count != 0)
531: Xfree( XDraw_points );
532: if (!(XDraw_points = (XPoint *) Xmalloc( newvcount * sizeof(XPoint) )))
533: return(ERR_RETURN);
534: point_count = newvcount;
535: }
536:
537: /*
538: * Draw the lines defined by newvlist using seperate XDrawLines calls
539: * to insure that all the lines that should be joined are and that closed
540: * figures are joined correctly.
541: */
542: while (newvcount>0) {
543: p = XDraw_points; /* Put points in buffer */
544: pcount = 0;
545: p->x = newvlist->x; /* Copy first point */
546: (p++)->y = (newvlist++)->y;
547: newvcount--; pcount++;
548:
549: /*
550: * Copy more points until out of points or need to stop XDrawLine
551: * because either we don't want to join to the next point
552: * (VertexDontDraw) or we want to stop after the next point so that
553: * a closed figure will be joined correctly. (We have to stop before
554: * a VertexStartClosed because the vertex marked VertexStartClosed
555: * must be the first vertex in its XDrawLines call to get joining
556: * to work correctly.
557: */
558: while (newvcount > 0 && !(newvlist->flags & (VertexDontDraw |
559: VertexStartClosed |
560: VertexEndClosed))) {
561: p->x = newvlist->x;
562: (p++)->y = (newvlist++)->y;
563: newvcount--; pcount++;
564: }
565:
566: /*
567: * If stopped only because of need to start a new XDrawLines, copy
568: * next point but don't advance pointer so two XdrawLines act like one.
569: */
570: if ( newvcount > 0 && !(newvlist->flags & VertexDontDraw) ) {
571: p->x = newvlist->x;
572: (p++)->y = newvlist->y;
573: pcount++;
574: }
575:
576: /* Do the XDrawLines if there are any lines to draw */
577: if (pcount>1)
578: XDrawLines(dpy, d, gc, XDraw_points, pcount, CoordModeOrigin);
579: }
580:
581: return(OK_RETURN);
582: }
583:
584: Status XDrawFilled (dpy, d, gc, vlist, vcount)
585: register Display *dpy;
586: Drawable d;
587: GC gc;
588: Vertex *vlist;
589: int vcount;
590: {
591: Vertex *newvlist;
592: int newvcount;
593: XPoint *p;
594: int pcount;
595: int closed;
596:
597: /* If less than 2 vertices, we don't have to do anything (no lines) */
598: if (vcount<2)
599: return(OK_RETURN);
600:
601: /* Convert curved lines to straight lines & change relative references to */
602: /* absolute references. */
603: if (!vertices_converter( vlist, vcount, &newvlist, &newvcount))
604: return(ERR_RETURN);
605:
606: /* Insure we have enough buffer space */
607: if (point_count < newvcount) {
608: if (point_count != 0)
609: Xfree( XDraw_points );
610: if (!(XDraw_points = (XPoint *) Xmalloc( newvcount * sizeof(XPoint) )))
611: return(ERR_RETURN);
612: point_count = newvcount;
613: }
614:
615: /*
616: * Draw the lines defined by newvlist using seperate XDrawLines calls
617: * to insure that all the lines that should be joined are and that closed
618: * figures are joined correctly.
619: */
620: while (newvcount>0) {
621: p = XDraw_points; /* Put points in buffer */
622: pcount = 0;
623: closed = newvlist->flags & VertexStartClosed;
624: p->x = newvlist->x; /* Copy first point */
625: (p++)->y = (newvlist++)->y;
626: newvcount--; pcount++;
627:
628: /*
629: * Copy more points until out of points or need to stop XDrawLine
630: * because either we don't want to join to the next point
631: * (VertexDontDraw) or we want to stop after the next point so that
632: * a closed figure will be joined correctly. (We have to stop before
633: * a VertexStartClosed because the vertex marked VertexStartClosed
634: * must be the first vertex in its XDrawLines call to get joining
635: * to work correctly.
636: */
637: while (newvcount > 0 && !(newvlist->flags & (VertexDontDraw |
638: VertexStartClosed |
639: VertexEndClosed))) {
640: p->x = newvlist->x;
641: (p++)->y = (newvlist++)->y;
642: newvcount--; pcount++;
643: }
644:
645: /*
646: * If stopped only because of need to start a new XDrawLines, copy
647: * next point but don't advance pointer so two XdrawLines act like one.
648: */
649: if ( newvcount > 0 && !(newvlist->flags & VertexDontDraw) ) {
650: p->x = newvlist->x;
651: (p++)->y = newvlist->y;
652: pcount++;
653: }
654:
655: /* Do the XDrawLines if there are any lines to draw */
656: if (pcount>1) {
657: if (closed)
658: XFillPolygon(dpy, d, gc, XDraw_points, pcount, Complex,
659: CoordModeOrigin);
660: else
661: XDrawLines(dpy, d, gc, XDraw_points, pcount, CoordModeOrigin);
662: }
663: }
664:
665: return(OK_RETURN);
666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.