home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / oldX / XDraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  23.3 KB  |  692 lines

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