|
|
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.