aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/oldX/XDraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/oldX/XDraw.c')
-rw-r--r--nx-X11/lib/oldX/XDraw.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/nx-X11/lib/oldX/XDraw.c b/nx-X11/lib/oldX/XDraw.c
new file mode 100644
index 000000000..3eeff3e00
--- /dev/null
+++ b/nx-X11/lib/oldX/XDraw.c
@@ -0,0 +1,710 @@
+/* $Xorg: XDraw.c,v 1.4 2001/02/09 02:04:05 xorgcvs Exp $ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/oldX/XDraw.c,v 1.4 2001/07/25 15:04:57 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "X11/Xlibint.h"
+#include "X11/Xlib.h"
+#include "X10.h"
+
+#define OK_RETURN 1
+#define ERR_RETURN 0
+#include <stddef.h>
+
+/*
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+/*
+ *
+ * Vertices_converter: This internal routine takes a list of Vertices and
+ * returns another list of Vertices such that the
+ * following is true:
+ *
+ * (1) No Vertex has the VertexRelative flag on
+ * (2) No Vertex has the VertexCurved flag on
+ * (3) The first Vertex has the VertexDontDraw flag on
+ * (4) The path that the return Vertex list specifies should
+ * be drawn on the screen is very close to the path that the
+ * Vertex list passed to vertices_converter specified should be
+ * drawn. The difference is due solely to the approximation
+ * of curved segments in the original Vertex list by many
+ * small straight line segments that approximate the curve.
+ *
+ * Notes:
+ *
+ * (1) The first Vertex must have the VertexRelative flag
+ * turned off. (This is not checked, just assumed)
+ * (2) VertexDontDraw is automatically turned on for the first
+ * Vertex because drawing to the first Vertex makes no sense.
+ * (3) This routine is used only by XDraw & XDrawFilled.
+ * (4) A 0 is returned iff no error occurs.
+ * (5) The passed Vertex list not changed in any way.
+ *
+ * Implementation:
+ *
+ * A routine from the qvss device dependent code library from the
+ * X version 10 sources written by DEC was used, abet slightly
+ * modified as it provided 99% of the desired functionality.
+ *
+ */
+
+/*****************************************************************************/
+/* */
+/* WRITTEN BY DARYL F. HAZEL 8509.06 */
+/* */
+/* Modification history: */
+/* */
+/* Carver 8510.23 Fixed first time allocation of the coord buffer */
+/* to allocate max(200, pathcount) amount insted of just */
+/* 200. Potential Xserver crash problem. */
+/* */
+/* Carver 8510.21 Replaced old module by module worked on by Ram Rao and */
+/* Bob Scheifler to get better performace. */
+/* */
+/* Carver 8510.03 Changed the curve line converter to return the coord */
+/* path if a successor point does not exist for curve gen. */
+/* */
+/* Carver 8510.03 Fixed memory loss problem. A coord path is only */
+/* allocated if the current path will not fit in it and */
+/* before the new coord path is allocated the old one is */
+/* freed. */
+/* */
+/* Carver 8509.24 Fixed pointer/integer mismatch {*ppathaddr_new = ...} */
+/* */
+/* Corkum 8509.18 Modify code to intergrate into the draw curve command */
+/* */
+/* Modified by Mark Lillibridge 5/20/87 to make into */
+/* X11 Xlib XDraw() support. */
+/****************************************************************************/
+
+/*
+ * Definitions:
+ *
+ */
+
+typedef short WORD;
+typedef short *WORD_POINTER;
+
+/*
+ * Lookup tables, buffers used in the conversion:
+ *
+ */
+
+
+/*
+ * modified path list storage information:
+ */
+static Vertex *pathaddr_new = NULL; /*pointer to current modified path list*/
+static int pathlist_bytes = 0; /* size of modified path list in bytes */
+static int pathlist_segs = 0;/* size of modified path list in segments */
+static Vertex *pathaddr_coords = NULL; /*ptr to path list with coordinates */
+static int path_coord_list_bytes = 0; /* size of path list (w/coords) buff */
+static int path_coord_list_segs = 0; /* size of path list (w/coords) buff */
+
+/*
+ * THE TABLE OF PSEUDO FLOATING-POINT NUMBERS WHICH MAKE UP THE
+ * MULTIPLICATIVE COEFFICIENTS FOR THE CUBIC SPLINE ALGORITHM.
+ */
+static unsigned short bntable[] = {
+ 0xfc18, 0x7f97, 0x0476, 0xffde,
+ 0xf8be, 0x7e5d, 0x0972, 0xff76,
+ 0xf5f4, 0x7c56, 0x0eec, 0xfecc,
+ 0xf3ba, 0x7988, 0x14da, 0xfde6,
+ 0xf20b, 0x75fe, 0x1b2f, 0xfcca,
+ 0xf0e2, 0x71c1, 0x21dd, 0xfb81,
+ 0xf038, 0x6ce1, 0x28d3, 0xfa16,
+ 0xf001, 0x676d, 0x3000, 0xf894,
+ 0xf034, 0x6176, 0x3750, 0xf709,
+ 0xf0c3, 0x5b0f, 0x3eae, 0xf583,
+ 0xf1a1, 0x544b, 0x4605, 0xf410,
+ 0xf2c0, 0x4d41, 0x4d41, 0xf2c0,
+ 0xf410, 0x4605, 0x544b, 0xf1a1,
+ 0xf583, 0x3eae, 0x5b0f, 0xf0c3,
+ 0xf709, 0x3750, 0x6176, 0xf034,
+ 0xf894, 0x3000, 0x676d, 0xf001,
+ 0xfa16, 0x28d3, 0x6ce1, 0xf038,
+ 0xfb81, 0x21dd, 0x71c1, 0xf0e2,
+ 0xfcca, 0x1b2f, 0x75fe, 0xf20b,
+ 0xfde6, 0x14da, 0x7988, 0xf3ba,
+ 0xfecc, 0x0eec, 0x7c56, 0xf5f4,
+ 0xff76, 0x0972, 0x7e5d, 0xf8be,
+ 0xffde, 0x0476, 0x7f97, 0xfc18
+ };
+
+/*
+ * this is the table which determines how many straight-line segments to draw
+ * for a given curved segment.
+ */
+static short segtable[] = { 10, 3, 56, /* pl <= 10, 3 segments */
+ 32, 4, 40, /* pl <= 32, 4 segments */
+ 80, 6, 24, /* pl <= 80, 6 segments */
+ 96, 8, 16, /* pl <= 96, 8 segments */
+ 192, 12, 8, /* pl <= 192, 12 segments */
+ 32767, 24, 00 /* pl <= 32767, 24 segments */
+ };
+
+/*
+ *
+ * The Real routine:
+ *
+ */
+
+static int vertices_converter(pathaddr, pathcount, ppathaddr_new, newpathcnt)
+ Vertex *pathaddr; /* address of original path list */
+ int pathcount; /* number of points in original path list */
+ Vertex **ppathaddr_new; /* ptr to addr of new path list */
+ int *newpathcnt; /* ptr to new number of pts in path list */
+{
+ int p0x, p0y; /* coordinates of curve's predecessor point */
+ int p1x, p1y; /* coordinates of curve's starting point */
+ int p2x, p2y; /* coordinates of curve's ending point */
+ int p3x, p3y; /* coordinates of curve's successor point */
+ int flag; /* flag word of current end-point in p.list */
+ int successor_x = 0; /* X coordinate of curve's successor point */
+ int successor_y = 0; /* Y coordinate of curve's successor point */
+ int little_endian; /* stupid bntable is little-endian */
+ WORD increment; /* bntable-ptr-increment value */
+ WORD diffx, diffy; /* absolute values of x, y end-point diffs */
+ WORD lmajoraxis; /* "length" of seg projected onto major axis */
+ union /* accumulator variables for computing end-points... */
+ { /* ...using the bntable. */
+ struct
+ {
+ WORD low;
+ WORD high;
+ } sword;
+ int lword;
+ } xxe, yye;
+ register Vertex *pnewpath;/* pointer for traversing modified path list */
+ int newpathcount; /* number of end-points in modified path list*/
+ register Vertex *pflag; /* pointer used for looking for fig's last pt*/
+ int i; /* general-purpose loop variable */
+ int ecf_flag_set; /* flag indicating existence of set ECF flag */
+ int count;
+ int curve_flag; /* 0 = no curves in path; 1 = curves in path */
+
+ /*
+ * The following is necessary because of the pseudo-floating point
+ * calculations done down below.
+ */
+ i = 1;
+ if (*(char *) &i)
+ little_endian = 1;
+ else
+ little_endian = 0;
+
+ {
+ register Vertex *poldpath;/* pointer for traversing original path list */
+ register Vertex *p_coord_path; /* ptr to path list with coordinates */
+
+ /* Init the return path count to 0 in case of error */
+ *newpathcnt = 0;
+ newpathcount = 0;
+
+ /* Use path buffers from last time */
+ pnewpath = pathaddr_new;
+ p_coord_path = pathaddr_coords;
+
+ /*
+ * if size of coordinate path list buffer is not at least large enough to
+ * accommodate the specified path list, allocate enough memory to do so
+ */
+ if (path_coord_list_segs == 0) /* first time through*/
+ {
+ path_coord_list_segs = max (200, pathcount);
+ path_coord_list_bytes = path_coord_list_segs * sizeof(Vertex);
+ if ((pathaddr_coords = (Vertex *)Xmalloc(path_coord_list_bytes)) != 0)
+ p_coord_path = pathaddr_coords;
+ else
+ return(ERR_RETURN);
+ }
+ else /* all but first time through */
+ {
+ /* If coord buffer is large enough for this path then reuse it, other
+ wise free the old one and get a new one (Carver) 8510.03 */
+ if (path_coord_list_segs < pathcount)
+ {
+ Xfree( pathaddr_coords);
+ path_coord_list_segs = pathcount;
+ path_coord_list_bytes = path_coord_list_segs * sizeof(Vertex);
+ if ((pathaddr_coords =(Vertex *)Xmalloc(path_coord_list_bytes)) !=0)
+ p_coord_path = pathaddr_coords;
+ else
+ return(ERR_RETURN);
+ };
+ }
+
+ /*
+ * Copy given Vertex list (pathaddr) to coordinate buffer converting
+ * relative coordinates to absolute coordinates.
+ *
+ * Sets curve_flag iff at least one Vertex has the VertexCurved flag set.
+ *
+ */
+
+ poldpath = pathaddr;
+ curve_flag = 0;
+
+ *p_coord_path = *poldpath++; /* First Vertex is a special case */
+ p_coord_path->flags = (p_coord_path->flags | VertexDontDraw)
+ & ~VertexRelative;
+ if ((p_coord_path++)->flags & VertexCurved)
+ curve_flag = 1;
+ for (i = pathcount - 1; i > 0; i--)
+ {
+ if (poldpath->flags & VertexRelative)
+ { /* compute coordinates using last pt */
+ p_coord_path->x = poldpath->x + p_coord_path[-1].x;
+ p_coord_path->y = poldpath->y + p_coord_path[-1].y;
+ p_coord_path->flags = poldpath->flags & ~VertexRelative;
+ }
+ else *p_coord_path = *poldpath;
+ p_coord_path++;
+ if ((poldpath++)->flags & VertexCurved)
+ curve_flag = 1;
+ }
+ } /* End of scope for poldaddr, p_coord_path */
+
+ /*
+ * if it has been determined that there are no curved segment end points in
+ * the specified path list, return the path list containing the coordinates
+ * to the calling routine.
+ */
+ if (!curve_flag)
+ {
+ *newpathcnt = pathcount;
+ *ppathaddr_new = pathaddr_coords;
+ return(OK_RETURN);
+ }
+
+ /*
+ * if size of modified path list buffer is not at least large enough to
+ * accommodate the specified path list allocate enough memory to do so
+ */
+ pathaddr = pathaddr_coords;
+ if (pathlist_segs < pathcount)
+ {
+ if (pathlist_segs == 0) /* Fix storage leak -- MDL 5/20/87 */
+ Xfree( pathaddr_new );
+ pathlist_segs = pathcount;
+ pathlist_bytes = pathcount * sizeof(Vertex);
+ if ((pathaddr_new = (Vertex *)Xmalloc(pathlist_bytes)) != 0)
+ pnewpath = pathaddr_new;
+ else
+ return(ERR_RETURN);
+ }
+
+ /*
+ * initialize the beginning and ending coordinates of the first segment
+ */
+ p1x = 0;
+ p1y = 0;
+ p2x = 0;
+ p2y = 0;
+
+ {
+ register WORD *pbntable; /* table of multiplicative coeffics.*/
+ register WORD *psegtable; /* table used to detrmn num.sub-segs*/
+ register WORD m; /* num segments into which curve is divided */
+
+ /*
+ * MAIN LOOP OF THE PATH_LIST_CONVERTER ROUTINE
+ */
+ for ( count=pathcount ; count > 0; count--)
+ {
+ p0x = p1x; /* save previous values of path-list coordinate pairs*/
+ p0y = p1y;
+ p1x = p2x;
+ p1y = p2y;
+
+ /*
+ * read next end-point's coordinates from the path list
+ */
+ p2x = pathaddr->x;
+ p2y = pathaddr->y;
+ flag = (pathaddr++)->flags;
+
+ /*
+ * CURVED-segment considerations
+ */
+ if (flag & VertexCurved)
+ {
+ /*
+ * determine which point to use as the successor point: the next
+ * point in the list (if there is one), or a previously-saved point
+ * (when drawing closed figures)
+ */
+ if (flag & VertexEndClosed) /* last segment of closed fig*/
+ {
+ p3x = successor_x;
+ p3y = successor_y;
+ }
+ else /* stand-alone curved segment*/
+ {
+ if (count <= 1) /* no points to use as successor pt */
+ {
+
+ /* in this case draw the coord path */
+ *newpathcnt = pathcount;
+ *ppathaddr_new = pathaddr_coords;
+ return(OK_RETURN);
+ }
+ else
+ {
+ /*
+ * read next end-point's coordinates from the path list...
+ */
+ p3x = pathaddr->x;
+ p3y = pathaddr->y;
+
+ if (flag & VertexStartClosed)
+ { /* first segment of closed figure */
+ /*
+ * save P3 as successor pt for closed-fig-ending curve
+ */
+ successor_x = p3x;
+ successor_y = p3y;
+
+ /*
+ * Traverse the original path list looking for ECF flag
+ * After finding it, back pointer up to previous point
+ * and save the information for use as curve's pred. pt
+ */
+ ecf_flag_set = 0;
+ pflag = pathaddr;
+ for (i = count; i > 0; i--)
+ {
+ if (pflag->flags & VertexEndClosed)
+ {
+ pflag--;
+ p1x = pflag->x;
+ p1y = pflag->y;
+ ecf_flag_set = 1;
+ break;
+ }
+ pflag++;
+ }
+ if (!ecf_flag_set)
+ return(ERR_RETURN);
+ } /* end code pertaining to starting figure*/
+ } /* end code pertaining to successor points */
+ } /* end code pertaining to stand-alone curved segs*/
+
+ if ((flag & VertexDontDraw) == 0)
+ {
+ /*
+ * determine the "length" of the segment along the major axis
+ */
+ if ((diffx = p2x - p1x) < 0)
+ diffx = ~diffx + 1;
+ if ((diffy = p2y - p1y) < 0)
+ diffy = ~diffy + 1;
+ lmajoraxis = (diffx >= diffy) ? diffx : diffy;
+ if (lmajoraxis == 0) /* for vector to have length of... */
+ lmajoraxis = 1; /* ...at least one */
+
+ /*
+ * compute M, the number of sub-segments into which a curved
+ * segment is divided
+ */
+ psegtable = segtable;
+ while (lmajoraxis > *psegtable++)/* search for appropriate..*/
+ psegtable += 2; /* ...table entry */
+ m = *psegtable++; /* read number of segments */
+ increment = *psegtable >> 1;
+
+ /*
+ * determine if there is enough room remaining in the modified
+ * path-list buffer to hold ALL of the curve's sub-segment in-
+ * formation; if not, double the buffer size (if possible).
+ */
+ while ((newpathcount + m) > pathlist_segs)
+ {
+ pathlist_segs *= 2;
+ pathlist_bytes *= 2;
+ if ((pathaddr_new = (Vertex *)Xrealloc(pathaddr_new,
+ pathlist_bytes)) != 0)
+ pnewpath = pathaddr_new + newpathcount;
+ else
+ return(ERR_RETURN);
+ }
+
+ /*
+ * generate end-points of sub-segs into which curve is divided
+ */
+ pbntable = (WORD *) bntable; /* initialize the pointer to the Bn table*/
+ for ( ; m > 1; m--)
+ {
+ pbntable += increment;
+ xxe.lword = *pbntable * p0x;
+ yye.lword = *pbntable++ * p0y;
+ xxe.lword += *pbntable * p1x;
+ yye.lword += *pbntable++ * p1y;
+ xxe.lword += *pbntable * p2x;
+ yye.lword += *pbntable++ * p2y;
+ xxe.lword += *pbntable * p3x;
+ yye.lword += *pbntable++ * p3y;
+ xxe.lword = xxe.lword << 1; /* double values... */
+ yye.lword = yye.lword << 1; /* ...bn accts for it*/
+ xxe.lword += 0x8000; /* round off the accum value */
+ yye.lword += 0x8000;
+ if (little_endian) {
+ pnewpath->x = xxe.sword.high;/* the X coordinate */
+ pnewpath->y = yye.sword.high;/* the Y coordinate */
+ } else {
+ pnewpath->x = xxe.sword.low;/* the X coordinate */
+ pnewpath->y = yye.sword.low;/* the Y coordinate */
+ }
+ (pnewpath++)->flags = 0; /* the flag word */
+ newpathcount++;/* increment segment end-point countr*/
+ } /* end sub-segment end-point compute loop*/
+ } /* end DRAW-segment considerations code */
+ } /* end CURVED-segment considerations code */
+
+ /*
+ * put end-point from original path list into modified list
+ */
+ pnewpath->x = p2x;
+ pnewpath->y = p2y;
+ (pnewpath++)->flags = flag & ~VertexCurved;
+ newpathcount++;
+
+ /*
+ * determine whether or not the modified path list is full, and if so,
+ * double its size
+ */
+ if (newpathcount == pathlist_segs)
+ {
+ pathlist_bytes *= 2;
+ pathlist_segs *= 2;
+ if ((pathaddr_new = (Vertex *)Xrealloc(pathaddr_new,
+ pathlist_bytes)) != 0)
+ pnewpath = pathaddr_new + newpathcount;
+ else
+ return(ERR_RETURN);
+ }
+ } /* END of PATH_LIST_CONVERTER's main loop */
+
+ /*
+ * return the address of the modified path list and the number of segment
+ * end-points it contains
+ */
+ *newpathcnt = newpathcount;
+ *ppathaddr_new = pathaddr_new;
+ }
+
+ return(OK_RETURN);
+}
+
+/* Written by Mark Lillibridge */
+
+static XPoint *XDraw_points = NULL; /* Buffer to hold list of points for */
+static int point_count = 0; /* use in calling XDrawLines */
+
+Status XDraw (dpy, d, gc, vlist, vcount)
+ register Display *dpy;
+ Drawable d;
+ GC gc;
+ Vertex *vlist;
+ int vcount;
+{
+ Vertex *newvlist;
+ int newvcount;
+ XPoint *p;
+ int pcount;
+
+ /* If less than 2 vertices, we don't have to do anything (no lines) */
+ if (vcount<2)
+ return(OK_RETURN);
+
+ /* Convert curved lines to straight lines & change relative references to */
+ /* absolute references. */
+ if (!vertices_converter( vlist, vcount, &newvlist, &newvcount))
+ return(ERR_RETURN);
+
+ /* Insure we have enough buffer space */
+ if (point_count < newvcount) {
+ if (point_count != 0)
+ Xfree( XDraw_points );
+ if (!(XDraw_points = (XPoint *) Xmalloc( newvcount * sizeof(XPoint) )))
+ return(ERR_RETURN);
+ point_count = newvcount;
+ }
+
+ /*
+ * Draw the lines defined by newvlist using seperate XDrawLines calls
+ * to insure that all the lines that should be joined are and that closed
+ * figures are joined correctly.
+ */
+ while (newvcount>0) {
+ p = XDraw_points; /* Put points in buffer */
+ pcount = 0;
+ p->x = newvlist->x; /* Copy first point */
+ (p++)->y = (newvlist++)->y;
+ newvcount--; pcount++;
+
+ /*
+ * Copy more points until out of points or need to stop XDrawLine
+ * because either we don't want to join to the next point
+ * (VertexDontDraw) or we want to stop after the next point so that
+ * a closed figure will be joined correctly. (We have to stop before
+ * a VertexStartClosed because the vertex marked VertexStartClosed
+ * must be the first vertex in its XDrawLines call to get joining
+ * to work correctly.
+ */
+ while (newvcount > 0 && !(newvlist->flags & (VertexDontDraw |
+ VertexStartClosed |
+ VertexEndClosed))) {
+ p->x = newvlist->x;
+ (p++)->y = (newvlist++)->y;
+ newvcount--; pcount++;
+ }
+
+ /*
+ * If stopped only because of need to start a new XDrawLines, copy
+ * next point but don't advance pointer so two XdrawLines act like one.
+ */
+ if ( newvcount > 0 && !(newvlist->flags & VertexDontDraw) ) {
+ p->x = newvlist->x;
+ (p++)->y = newvlist->y;
+ pcount++;
+ }
+
+ /* Do the XDrawLines if there are any lines to draw */
+ if (pcount>1)
+ XDrawLines(dpy, d, gc, XDraw_points, pcount, CoordModeOrigin);
+ }
+
+ return(OK_RETURN);
+}
+
+Status XDrawFilled (dpy, d, gc, vlist, vcount)
+ register Display *dpy;
+ Drawable d;
+ GC gc;
+ Vertex *vlist;
+ int vcount;
+{
+ Vertex *newvlist;
+ int newvcount;
+ XPoint *p;
+ int pcount;
+
+ /* If less than 2 vertices, we don't have to do anything (no lines) */
+ if (vcount<2)
+ return(OK_RETURN);
+
+ /* Convert curved lines to straight lines & change relative references to */
+ /* absolute references. */
+ if (!vertices_converter( vlist, vcount, &newvlist, &newvcount))
+ return(ERR_RETURN);
+
+ /* Insure we have enough buffer space */
+ if (point_count < newvcount) {
+ if (point_count != 0)
+ Xfree( XDraw_points );
+ if (!(XDraw_points = (XPoint *) Xmalloc( newvcount * sizeof(XPoint) )))
+ return(ERR_RETURN);
+ point_count = newvcount;
+ }
+
+ /*
+ * Draw the lines defined by newvlist using seperate XDrawLines calls
+ * to insure that all the lines that should be joined are and that closed
+ * figures are joined correctly.
+ */
+ while (newvcount>0) {
+ p = XDraw_points; /* Put points in buffer */
+ pcount = 0;
+ p->x = newvlist->x; /* Copy first point */
+ (p++)->y = (newvlist++)->y;
+ newvcount--; pcount++;
+
+ /*
+ * Copy more points until out of points or need to stop XDrawLine
+ * because either we don't want to join to the next point
+ * (VertexDontDraw) or we want to stop after the next point so that
+ * a closed figure will be joined correctly. (We have to stop before
+ * a VertexStartClosed because the vertex marked VertexStartClosed
+ * must be the first vertex in its XDrawLines call to get joining
+ * to work correctly.
+ */
+ while (newvcount > 0 && !(newvlist->flags & (VertexStartClosed |
+ VertexEndClosed))) {
+ p->x = newvlist->x;
+ (p++)->y = (newvlist++)->y;
+ newvcount--; pcount++;
+ }
+
+ /*
+ * If stopped only because of need to start a new XDrawLines, copy
+ * next point but don't advance pointer so two XdrawLines act like one.
+ */
+ if ( newvcount > 0 ) {
+ p->x = newvlist->x;
+ (p++)->y = newvlist->y;
+ pcount++;
+ }
+
+ /* Do the XDrawLines if there are any lines to draw */
+ if (pcount>1) {
+ XFillPolygon(dpy, d, gc, XDraw_points, pcount, Complex,
+ CoordModeOrigin);
+ }
+ }
+
+ return(OK_RETURN);
+}