/* xws_polygon.c 03 May 1999 */ # include # include #ifdef VMS #include #else /* UNIX */ #include #endif #include "defs.h" #include "xws_defs.h" /* BOUNDARY_WIDTH is the width of the polygon boundary, for hollow. * If you want a boundary width of 1 pixel, use 0, because it's faster. */ #define BOUNDARY_WIDTH 2 #define MAX_HATCH_INDEX 6 #define MAX_PATTERN_INDEX 10 extern void free(); static int Pgon_Fill_Init=FALSE; static Pixmap HatchFill[MAX_HATCH_INDEX]; static Pixmap PatternFill[MAX_PATTERN_INDEX]; /* PROCEDURE DECLARATIONS */ static xws_fill_polygon ( int point_count, int x[], int y[] ); static void xws_init_fill ( ); /* Set polygon fill color */ xws_fl_colour(r, g, b, index) float r, g, b; int index; { XSetForeground(Dpy, PolygonGC, (*xws_get_pixel)(r, g, b, index)); return(GPLOT_SUCCESS); } /* Set polygon interior style */ xws_fl_style(interior_style) enum is_enum interior_style; { unsigned long valuemask = 0; XGCValues values; switch(interior_style) { case hollow: /* I think hollow could be a total no-op if we set these in * xws_setup, and determine that they are never changed by * driver code. But since GC values are cached, this * insurance of always setting the line width and type does * not result in a server transaction. The CGM standard * states that linewidth and linetype of the boundary are * implementation dependent, in section 4.7.8 */ valuemask = GCLineWidth | GCLineStyle; values.line_width = BOUNDARY_WIDTH; values.line_style = LineSolid; break; case solid_i: valuemask = GCFillStyle; values.fill_style = FillSolid; break; case pattern: /* falls through */ case hatch: valuemask = GCFillStyle; values.fill_style = FillOpaqueStippled; break; case empty: /* no attributes to set */ return(GPLOT_SUCCESS); default: return(GPLOT_INVALID_PARAMETER); } XChangeGC(Dpy, PolygonGC, valuemask, &values); return(GPLOT_SUCCESS); } /* Polygon processor routine */ xws_pgon(point_count, x, y) int point_count; int x[], y[]; { unsigned long valuemask=0; XGCValues values; int status = GPLOT_SUCCESS; /* check for illegal polygon specification */ if (point_count <= 1) return(GPLOT_INVALID_PARAMETER); /* The Polygon Graphics Context foreground pixel has been set * to the current fill colour attribute value by xws_fl_colour(). * The appropriate attributes have been set for fill. */ switch (CGMClass5->int_style) { default: status = GPLOT_INVALID_PARAMETER; /* fall through - the default fill interior style is hollow */ case (hollow): /* The boundary is drawn in the fill color */ xws_lines(point_count, x, y, PolygonGC, TRUE); break; case (hatch): /* fall through */ case (pattern): if (!Pgon_Fill_Init) xws_init_fill(); valuemask = GCStipple; values.stipple = (CGMClass5->int_style == pattern) ? PatternFill[(CGMClass5->pat_index) - 1] : HatchFill[(CGMClass5->hatch_index) - 1]; XChangeGC(Dpy, PolygonGC, valuemask, &values); /* fall through */ case (solid_i): status = xws_fill_polygon(point_count, x, y); break; case (empty): /* An empty polygon has no fill */ break; } /* Draw the edge after filling, insuring that it is visible. * "The visibility and style of the edge of the area depend on the * edge attributes alone." CGM Standard, Functional Spec, 4.6.4 */ if (CGMClass5->edge_vis == on) xws_edge(point_count, x, y); return(status); } /* MAX_POINTS, as defined in "xws_defs.h", is the maximum number of points * in a polygon specification if my static data structure is to be used. * Polygon points must be passed to the X drawing routine in a single call. * Therefore if the number of points defining a polygon is greater than * MAX_POINTS, an array of appropriate size will be dynamically allocated. * MAX_POINTS must be an integer greater than 2. */ static xws_fill_polygon ( int point_count, int x[], int y[] ) { register int n; /* count of processed unsent polyline coordinates */ XPoint *points; XPoint *many_points=NULL; /* Allocate a large array for polygons defined by many points */ if (point_count > MAX_POINTS) { if ((many_points = (XPoint *) calloc((unsigned) point_count, sizeof(XPoint))) == NULL) { (void) fprintf(stderr, "%s: xws_pgon: not enough \ memory for a polygon of %d points.\n", ProgramName, point_count); return(GPLOT_DRIVER_INCAPABLE); } points = many_points; /* use the dynamic data structure */ } else points = Points; /* use the static data structure */ /* Pack points into the suitable data structure and fill the polygon */ for (n=0; point_count - n > 0; n++) { points[n].x = (short) x[n]; points[n].y = (short) (MaxY - y[n]); } XFillPolygon(Dpy, Win, PolygonGC, points, n, Complex, CoordModeOrigin); /* CGM polygons may be complex, that is, self-intersecting */ if (points == many_points) free((char *) many_points); return(GPLOT_SUCCESS); } static void xws_init_fill ( ) { #include "xws_fill.h" /* look at these with the bitmap program */ /* Pixmap IDs are not returned in the proper order on the Xqdss * server. A bug, n'est pas? -synchronize doesn't always help. */ HatchFill[0] = XCreateBitmapFromData(Dpy, Win, h_bits, h_width, h_height); HatchFill[1] = XCreateBitmapFromData(Dpy, Win, v_bits, v_width, v_height); HatchFill[2] = XCreateBitmapFromData(Dpy, Win, p_bits, p_width, p_height); HatchFill[3] = XCreateBitmapFromData(Dpy, Win, n_bits, n_width, n_height); HatchFill[4] = XCreateBitmapFromData(Dpy, Win, hv_bits, hv_width, hv_height); HatchFill[5] = XCreateBitmapFromData(Dpy, Win, pn_bits, pn_width, pn_height); PatternFill[0] = XCreateBitmapFromData(Dpy, Win, stipple_bits, stipple_width, stipple_height); PatternFill[1] = XCreateBitmapFromData(Dpy, Win, boxes_bits, boxes_width, boxes_height); PatternFill[2] = XCreateBitmapFromData(Dpy, Win, cross_weave_bits, cross_weave_width, cross_weave_height); PatternFill[3] = XCreateBitmapFromData(Dpy, Win, icon_bits, icon_width, icon_height); PatternFill[4] = XCreateBitmapFromData(Dpy, Win, opendot_bits, opendot_width, opendot_height); PatternFill[5] = XCreateBitmapFromData(Dpy, Win, scales_bits, scales_width, scales_height); PatternFill[6] = XCreateBitmapFromData(Dpy, Win, star_bits, star_width, star_height); PatternFill[7] = XCreateBitmapFromData(Dpy, Win, target_bits, target_width, target_height); PatternFill[8] = XCreateBitmapFromData(Dpy, Win, wide_weave_bits, wide_weave_width, wide_weave_height); PatternFill[9] = XCreateBitmapFromData(Dpy, Win, dot_bits, dot_width, dot_height); Pgon_Fill_Init++; } /* Set edge line type */ xws_e_type(type) enum line_enum type; /* the requested edge line type */ { return(xws_set_type(type, EdgeGC)); } /* Set edge line width */ /*ARGSUSED*/ xws_e_width(absolute_width, scaled_width) int absolute_width; /* requested edge line width in pixels */ float scaled_width; /* purposely ignored and redundant */ { XGCValues values; /* lines of width 1 pixel may be drawn faster if width is set to 0 */ values.line_width = (absolute_width <= 1 ? 0 : absolute_width); XChangeGC(Dpy, EdgeGC, GCLineWidth, &values); return((absolute_width < 1) ? GPLOT_INVALID_PARAMETER : GPLOT_SUCCESS); } /* Set edge color */ xws_e_colour(r, g, b, index) float r, g, b; /* specification in direct color metacode */ int index; /* specification in indexed color metacode */ { XSetForeground(Dpy, EdgeGC, (*xws_get_pixel)(r, g, b, index)); return(GPLOT_SUCCESS); } /* Draw a polygon edge using the current edge attributes. * xws_edge() may also be called for degenerate cell arrays. */ void xws_edge(point_count, x, y) int point_count; int x[], y[]; { /* Edge type, width, and color attributes have already been set. * Draw the edge as a closed polyline. This results in an * incorrect representation of a self-intersecting polygon: the * edge line will be visible in the interior of the polygon. */ (void) xws_lines(point_count, x, y, EdgeGC, TRUE); }