aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Bezier.c1359
1 files changed, 0 insertions, 1359 deletions
diff --git a/Bezier.c b/Bezier.c
deleted file mode 100644
index a61ff5f..0000000
--- a/Bezier.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * Bezier.c -- Implementation of bezier item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Fri May 5 12:33:32 2000
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2000 CENA, Patrick Lecoanet --
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this code; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-#include "Draw.h"
-#include "Item.h"
-#include "Geo.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Image.h"
-#include "Color.h"
-#ifdef GPC
-#include "gpc/gpc.h"
-#endif
-
-#include <ctype.h>
-#include <malloc.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * Bit offset of flags.
- */
-#define FILLED_BIT 1<<0 /* If the item is filled with color/pattern */
-#define CCW 1<<2 /* Tell if the controls are described in
- * clockwise or ccw order. */
-#define FIRST_END_OK 1<<3
-#define LAST_END_OK 1<<4
-#define FILLED_OK 1<<5
-#define RELIEF_OK 1<<6
-
-
-/*
- **********************************************************************************
- *
- * Specific Bezier item record
- *
- **********************************************************************************
- */
-typedef struct _BezierItemStruct {
- ItemStruct header;
-
- /* Public data */
- ZnList points;
- unsigned short flags;
- ZnLineEnd first_end; /* These two are considered only if relief is flat */
- ZnLineEnd last_end;
- LineStyle line_style; /* This is considered only if relief is flat */
- int cap_style;
- ReliefStyle relief;
- ZnDim line_width; /* If 0 the path is not drawn, if <2 relief is flat */
- ZnImage fill_pattern;
- ZnGradient *fill_color;
- ZnImage line_pattern;
- ZnGradient *line_color;
- ZnImage tile;
-
- /* Private data */
- ZnList dev_points;
- ZnGradient *gradient;
- ZnTriStrip tristrip;
- ZnPoint *grad_geo;
-} BezierItemStruct, *BezierItem;
-
-
-static ZnAttrConfig bz_attrs[] = {
- { ZN_CONFIG_CAP_STYLE, "-capstyle", NULL,
- Tk_Offset(BezierItemStruct, cap_style), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(BezierItemStruct, header.flags), COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(BezierItemStruct, header.flags), COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(BezierItemStruct, header.flags), COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
- Tk_Offset(BezierItemStruct, fill_color), 0,
- ZN_COORDS_FLAG|ZN_BORDER_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(BezierItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(BezierItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-firstend", NULL,
- Tk_Offset(BezierItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-lastend", NULL,
- Tk_Offset(BezierItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
- Tk_Offset(BezierItemStruct, line_color), 0,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BITMAP, "-linepattern", NULL,
- Tk_Offset(BezierItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
- Tk_Offset(BezierItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-linewidth", NULL,
- Tk_Offset(BezierItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(BezierItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(BezierItemStruct, relief), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(BezierItemStruct, header.flags), SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(BezierItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_IMAGE, "-tile", NULL,
- Tk_Offset(BezierItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(BezierItemStruct, header.flags), VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0 }
-};
-
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(Item item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- WidgetInfo *wi = item->wi;
- BezierItem bz = (BezierItem) item;
- Tcl_Obj **elems;
- int i, num_elems;
- ZnPoint p;
-
- bz->dev_points = NULL;
- bz->tristrip.num_strips = 0;
- bz->gradient = NULL;
- bz->grad_geo = NULL;
-
- /* Init attributes */
- SET(item->flags, VISIBLE_BIT);
- SET(item->flags, SENSITIVE_BIT);
- SET(item->flags, COMPOSE_ALPHA_BIT);
- SET(item->flags, COMPOSE_ROTATION_BIT);
- SET(item->flags, COMPOSE_SCALE_BIT);
- item->priority = DEFAULT_BEZIER_PRIORITY;
-
- if (*argc < 1) {
- Tcl_AppendResult(wi->interp, " bezier coords expected", NULL);
- return ZN_ERROR;
- }
- if ((Tcl_ListObjGetElements(wi->interp, (*args)[0], &num_elems, &elems) == ZN_ERROR) ||
- ((num_elems % 2) != 0)) {
- bz_error:
- Tcl_AppendResult(wi->interp, " malformed bezier coords", NULL);
- return ZN_ERROR;
- }
-
- bz->points = ZnListNew(num_elems/2, sizeof(ZnPoint));
- for (i = 0; i < num_elems; i += 2) {
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i], &p.x) == ZN_ERROR) {
- bz_error2:
- ZnListFree(bz->points);
- bz->points = NULL;
- goto bz_error;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i+1], &p.y) == ZN_ERROR) {
- goto bz_error2;
- }
- ZnListAdd(bz->points, &p, ZnListTail);
- }
- (*args)++;
- (*argc)--;
-
- CLEAR(bz->flags, FILLED_BIT);
- bz->first_end = NULL;
- bz->last_end = NULL;
- bz->line_style = LINE_SIMPLE;
- bz->relief = RELIEF_FLAT;
- bz->line_width = 1;
- bz->tile = ZnUnspecifiedImage;
- bz->fill_pattern = ZnUnspecifiedImage;
- bz->line_pattern = ZnUnspecifiedImage;
- bz->cap_style = CapRound;
-
- bz->fill_color = ZnGetGradientByValue(wi->fore_color);
- bz->line_color = ZnGetGradientByValue(wi->fore_color);
-
- return ZN_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(Item item)
-{
- BezierItem bz = (BezierItem) item;
-
- bz->dev_points = NULL;
- bz->tristrip.num_strips = 0;
-
- if (bz->grad_geo) {
- ZnPoint *grad_geo = ZnMalloc(4*sizeof(ZnPoint));
- memcpy(grad_geo, bz->grad_geo, 4*sizeof(ZnPoint));
- bz->grad_geo = grad_geo;
- }
- if (bz->gradient) {
- bz->gradient = ZnGetGradientByValue(bz->gradient);
- }
- if (bz->points) {
- bz->points = ZnListDuplicate(bz->points);
- }
- if (bz->first_end) {
- LineEndDuplicate(bz->first_end);
- }
- if (bz->last_end) {
- LineEndDuplicate(bz->last_end);
- }
- if (bz->tile != ZnUnspecifiedImage) {
- bz->tile = ZnGetImageByValue(bz->tile);
- }
- if (bz->line_pattern != ZnUnspecifiedImage) {
- bz->line_pattern = ZnGetImageByValue(bz->line_pattern);
- }
- if (bz->fill_pattern != ZnUnspecifiedImage) {
- bz->fill_pattern = ZnGetImageByValue(bz->fill_pattern);
- }
- bz->line_color = ZnGetGradientByValue(bz->line_color);
- bz->fill_color = ZnGetGradientByValue(bz->fill_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(Item item)
-{
- BezierItem bz = (BezierItem) item;
-
- if (bz->points) {
- ZnListFree(bz->points);
- }
- if (bz->dev_points) {
- ZnListFree(bz->dev_points);
- }
- if (bz->grad_geo) {
- ZnFree(bz->grad_geo);
- }
- if (bz->tristrip.num_strips) {
- TRI_FREE(&bz->tristrip);
- }
- if (bz->first_end) {
- LineEndDelete(bz->first_end);
- }
- if (bz->last_end) {
- LineEndDelete(bz->last_end);
- }
- if (bz->gradient) {
- ZnFreeGradient(bz->gradient);
- }
- if (bz->tile != ZnUnspecifiedImage) {
- ZnFreeImage(bz->tile);
- bz->tile = ZnUnspecifiedImage;
- }
- if (bz->line_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(bz->line_pattern);
- bz->line_pattern = ZnUnspecifiedImage;
- }
- if (bz->fill_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(bz->fill_pattern);
- bz->fill_pattern = ZnUnspecifiedImage;
- }
- ZnFreeGradient(bz->fill_color);
- ZnFreeGradient(bz->line_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Setup flags to control the precedence between the
- * graphical attributes.
- *
- **********************************************************************************
- */
-static void
-SetRenderFlags(BezierItem bz)
-{
- ASSIGN(bz->flags, FILLED_OK,
- ISSET(bz->flags, FILLED_BIT) && (ZnListSize(bz->points) > 2));
-
- ASSIGN(bz->flags, RELIEF_OK,
- (bz->relief != RELIEF_FLAT) && (ZnListSize(bz->points) > 1) &&
- (bz->line_width > 1));
-
- ASSIGN(bz->flags, FIRST_END_OK,
- (bz->first_end != NULL) && (ZnListSize(bz->points) > 1) &&
- ISCLEAR(bz->flags, FILLED_BIT) && bz->line_width &&
- ISCLEAR(bz->flags, RELIEF_OK));
-
- ASSIGN(bz->flags, LAST_END_OK,
- (bz->last_end != NULL) && (ZnListSize(bz->points) > 1) &&
- ISCLEAR(bz->flags, FILLED_BIT) && bz->line_width &&
- ISCLEAR(bz->flags, RELIEF_OK));
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(Item item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- WidgetInfo *wi = item->wi;
- BezierItem bz = (BezierItem) item;
- int status = ZN_OK;
- XColor *color;
- int alpha;
-
- status = ZnConfigureAttributes(wi, item, bz_attrs, argc, argv, flags);
-
- if (bz->gradient &&
- (ISSET(*flags, ZN_BORDER_FLAG) || (bz->relief == RELIEF_FLAT))) {
- ZnFreeGradient(bz->gradient);
- bz->gradient = NULL;
- }
- if ((bz->relief != RELIEF_FLAT) && !bz->gradient) {
- color = ZnGetGradientColor(bz->line_color, 51.0, &alpha);
- bz->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- ZnNameOfColor(color), alpha);
- if (bz->gradient == NULL) {
- status = ZN_ERROR;
- }
- }
-
- return status;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(Item item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi, item, bz_attrs, argv[0]) == ZN_ERROR) {
- return ZN_ERROR;
- }
-
- return ZN_OK;
-}
-
-
-static ZnBool
-TestCCW(ZnPoint *points,
- int num_points)
-{
- ZnPoint *p, *p_p, *p_n, min;
- ZnReal xprod;
- int i, min_index;
-
- if (num_points < 3) {
- return True;
- }
-
- /*
- * First find the lowest rightmost vertex. In X11 this is the
- * topmost one.
- */
- p = points;
- min = *p;
- min_index = 0;
- for (i = 1, p++; i < num_points; i++, p++) {
- if ((p->y < min.y) ||
- ((p->y == min.y) && (p->x > min.x))) {
- min_index = i;
- min = *p;
- }
- }
- /*
- * Then find the indices of the previous and next
- * vertices.
- */
- p = &points[min_index];
- p_p = &points[(min_index+(num_points-1))%num_points]; /* min_index-1 */
- p_n = &points[(min_index+1)%num_points];
- xprod = ((p_p->x*p->y - p_p->y*p->x) +
- (p_p->y*p_n->x - p_p->x*p_n->y) +
- (p->x*p_n->y - p->y*p_n->x));
- return (xprod <= 0.0); /* Should be >= 0 but X11 has Y axis reverted. */
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(Item item,
- ZnBool force)
-{
- WidgetInfo *wi = item->wi;
- BezierItem bz = (BezierItem) item;
- ZnPoint *points;
- ZnPoint end_points[LINE_END_POINTS];
- ZnPoint *dev_points;
- int num_points;
- ZnBBox bbox;
- int lw;
-
- ResetBBox(&item->item_bounding_box);
- if (bz->points == NULL) {
- return;
- }
-
- SetRenderFlags(bz);
-
- if (bz->tristrip.num_strips) {
- TRI_FREE(&bz->tristrip);
- }
-
- points = (ZnPoint *) ZnListArray(bz->points);
- num_points = ZnListSize(bz->points);
-
- /*
- * Allocate space for devices coordinates
- */
- if (bz->dev_points == NULL) {
- bz->dev_points = ZnListNew(num_points, sizeof(ZnPoint));
- }
- ZnListAssertSize(bz->dev_points, num_points);
- dev_points = (ZnPoint *) ZnListArray(bz->dev_points);
-
- /*
- * Compute device coordinates.
- */
- ZnTransformPoints(wi->current_transfo, points, dev_points, num_points);
-
- lw = bz->line_width;
-
- if (ISSET(bz->flags, RELIEF_OK)) {
- ASSIGN(bz->flags, CCW, TestCCW(dev_points, num_points));
-
- /*
- * Compute the bounding box.
- */
- ZnGetPolygonReliefBBox(dev_points, num_points,
- ISCLEAR(bz->flags, CCW)?-lw:lw, &bbox);
- AddBBoxToBBox(&item->item_bounding_box, &bbox);
- return;
- }
-
- /*
- * Compute the bounding box.
- */
- AddPointsToBBox(&item->item_bounding_box, dev_points, num_points);
-
- /*
- * Add the line width in all directions.
- * This overestimates the space needed to draw the polyline
- * but is simple. This is even more true for smoothed polygons but is
- * even faster.
- */
- item->item_bounding_box.orig.x -= lw;
- item->item_bounding_box.orig.y -= lw;
- item->item_bounding_box.corner.x += lw;
- item->item_bounding_box.corner.y += lw;
-
- /*
- * Process arrows.
- */
- if (ISSET(bz->flags, FIRST_END_OK)) {
- GetLineEnd(&dev_points[0], &dev_points[1], lw, bz->cap_style,
- bz->first_end, end_points);
- AddPointsToBBox(&item->item_bounding_box, end_points, LINE_END_POINTS);
- }
- if (ISSET(bz->flags, LAST_END_OK)) {
- GetLineEnd(&dev_points[num_points-1], &dev_points[num_points-2],
- lw, bz->cap_style, bz->last_end, end_points);
- AddPointsToBBox(&item->item_bounding_box, end_points, LINE_END_POINTS);
- }
-
- /*
- * Expand again the bounding box by one pixel in all
- * directions to take care of rounding errors.
- */
- item->item_bounding_box.orig.x -= 1;
- item->item_bounding_box.orig.y -= 1;
- item->item_bounding_box.corner.x += 1;
- item->item_bounding_box.corner.y += 1;
-
- if (!ZnGradientFlat(bz->fill_color)) {
- ZnPoly poly;
-
- if (!bz->grad_geo) {
- bz->grad_geo = ZnMalloc(4*sizeof(ZnPoint));
- }
- if (bz->fill_color->type == ZN_AXIAL_GRADIENT) {
- POLY_CONTOUR1(&poly, points, num_points);
- ZnComputeAxialGradient(wi, &poly, bz->fill_color->g.angle,
- bz->grad_geo);
- }
- else if (bz->fill_color->type == ZN_RADIAL_GRADIENT) {
- POLY_CONTOUR1(&poly, dev_points, num_points);
- ZnComputeRadialGradient(wi, &poly, &item->item_bounding_box,
- &bz->fill_color->g.p, bz->grad_geo);
- }
- else if (bz->fill_color->type == ZN_PATH_GRADIENT) {
- ZnTransformPoint(wi->current_transfo, &bz->fill_color->g.p,
- &bz->grad_geo[0]);
- }
- }
- else {
- if (bz->grad_geo) {
- ZnFree(bz->grad_geo);
- bz->grad_geo = NULL;
- }
- }
-}
-
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(Item item,
- ZnToArea ta)
-{
- BezierItem bz = (BezierItem) item;
- WidgetInfo *wi = item->wi;
- ZnPoint *points;
- ZnPoint end_points[LINE_END_POINTS];
- int num_points, result=-1, result2;
- int lw = bz->line_width;
- ZnBBox *area = ta->area;
-
- if (bz->dev_points == NULL) {
- return -1;
- }
-
- /*printf("============== bezier %d ==============\n", item->id);*/
- GetBezierPath(bz->dev_points, wi->work_pts);
- points = (ZnPoint *) ZnListArray(wi->work_pts);
- num_points = ZnListSize(wi->work_pts);
-
- if (ISSET(bz->flags, FILLED_OK)) {
- result = PolygonInBBox(points, num_points, area, NULL);
- if (result == 0) {
- return 0;
- }
- }
-
- if (lw > 0) {
- if (ISCLEAR(bz->flags, RELIEF_OK)) {
- result2 = PolylineInBBox(points, num_points, lw,
- bz->cap_style, JoinRound, area);
- }
- else {
- result2 = ZnPolygonReliefInBBox(points, num_points,
- ISCLEAR(bz->flags, CCW)?-lw:lw, area);
- }
- if (ISCLEAR(bz->flags, FILLED_OK)) {
- if (result2 == 0) {
- return 0;
- }
- result = result2;
- }
- else if (result2 != result) {
- return 0;
- }
-
- /*
- * Check line ends.
- */
- if (ISSET(bz->flags, FIRST_END_OK)) {
- GetLineEnd(&points[0], &points[1], lw, bz->cap_style,
- bz->first_end, end_points);
- if (PolygonInBBox(end_points, LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- if (ISSET(bz->flags, LAST_END_OK)) {
- GetLineEnd(&points[num_points-1], &points[num_points-2], lw,
- bz->cap_style, bz->last_end, end_points);
- if (PolygonInBBox(end_points, LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(Item item)
-{
- WidgetInfo *wi = item->wi;
- BezierItem bz = (BezierItem) item;
- XGCValues values;
- int i, num_points;
- unsigned int gc_mask;
- ZnPoint *points;
- XPoint *xpoints = NULL;
- int lw = bz->line_width;
-
- if (bz->dev_points == NULL) {
- return;
- }
-
- GetBezierPath(bz->dev_points, wi->work_pts);
- points = ZnListArray(wi->work_pts);
- num_points = ZnListSize(wi->work_pts);
-
- /*
- * Fill if requested.
- */
- if (ISSET(bz->flags, FILLED_OK)) {
- values.foreground = ZnPixel(ZnGetGradientColor(bz->fill_color, 0.0, NULL));
- gc_mask = GCFillStyle;
- if (bz->tile != ZnUnspecifiedImage) { /* Fill tiled */
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(bz->tile, NULL);
- values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
- values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
- gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCTile;
- }
- else if (bz->fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(bz->fill_pattern, NULL);
- values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
- values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
- gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCStipple|GCForeground;
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- gc_mask |= GCForeground;
- }
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
-
- if (!xpoints) {
- ZnListAssertSize(wi->work_xpts, num_points);
- xpoints = (XPoint *) ZnListArray(wi->work_xpts);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = REAL_TO_INT(points[i].x);
- xpoints[i].y = REAL_TO_INT(points[i].y);
- }
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, num_points, Complex, CoordModeOrigin);
- }
-
- /*
- * Draw the lines between points
- */
- if (lw) {
- ZnPoint end_points[LINE_END_POINTS];
- XPoint xp[LINE_END_POINTS];
-
- /*
- * Drawing with relief disables: ends, line style and line pattern.
- */
- if (ISSET(bz->flags, RELIEF_OK)) {
- ReliefStyle relief;
- int relief_dir;
-
- relief = bz->relief;
- relief_dir = relief & RELIEF_MASK;
- if (ISCLEAR(bz->flags, CCW)) {
- lw = -lw;
- if (relief_dir == RELIEF_SUNKEN) {
- relief_dir = RELIEF_RAISED;
- }
- else {
- relief_dir = RELIEF_SUNKEN;
- }
- relief = (relief & ~RELIEF_MASK) | relief_dir;
- }
- ZnDrawPolygonRelief(wi, relief, bz->gradient, points, num_points, lw);
- }
- else {
- ZnSetLineStyle(wi, bz->line_style);
- values.foreground = ZnPixel(ZnGetGradientColor(bz->line_color, 0, NULL));
- values.line_width = (lw == 1) ? 0 : lw;
- values.join_style = JoinRound;
- values.cap_style = bz->cap_style;
- if (bz->line_pattern == ZnUnspecifiedImage) {
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
- }
- else {
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(bz->line_pattern, NULL);
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCStipple|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground,
- &values);
- }
- if (!xpoints) {
- ZnListAssertSize(wi->work_xpts, num_points);
- xpoints = (XPoint *) ZnListArray(wi->work_xpts);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = REAL_TO_INT(points[i].x);
- xpoints[i].y = REAL_TO_INT(points[i].y);
- }
- }
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, num_points, CoordModeOrigin);
-
- if (ISSET(bz->flags, FIRST_END_OK)) {
- GetLineEnd(&points[0], &points[1], lw, bz->cap_style,
- bz->first_end, end_points);
- for (i = 0; i < LINE_END_POINTS; i++) {
- xp[i].x = end_points[i].x;
- xp[i].y = end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- if (ISSET(bz->flags, LAST_END_OK)) {
- GetLineEnd(&points[num_points-1], &points[num_points-2], lw,
- bz->cap_style, bz->last_end, end_points);
- for (i = 0; i < LINE_END_POINTS; i++) {
- xp[i].x = end_points[i].x;
- xp[i].y = end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GLX
-void
-BezierRenderCB(void *closure)
-{
-#ifdef GPC
- BezierItem bz = (BezierItem) closure;
- WidgetInfo *wi = ((Item) closure)->wi;
- int i, j, num_points;
- ZnPoint *points;
-
- if (bz->tristrip.num_strips == 0) {
- ZnPoly poly;
- POLY_CONTOUR1(&poly, (ZnPoint *) ZnListArray(wi->work_pts),
- ZnListSize(wi->work_pts));
- gpc_polygon_to_tristrip((gpc_polygon *) &poly,
- (gpc_tristrip *) &bz->tristrip);
- }
-
- for (i = 0; i < bz->tristrip.num_strips; i++) {
- num_points = bz->tristrip.strips[i].num_points;
- points = bz->tristrip.strips[i].points;
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0; j < num_points; j++, points++) {
- glVertex2f(points->x, points->y);
- }
- glEnd();
- }
-#endif
-}
-#endif
-static void
-Render(Item item)
-{
-#ifdef GLX
- WidgetInfo *wi = item->wi;
- BezierItem bz = (BezierItem) item;
- ZnPoint *points;
- int num_points;
- XColor *color;
- int alpha;
-
- if (bz->dev_points == NULL) {
- return;
- }
-
- GetBezierPath(bz->dev_points, wi->work_pts);
- points = ZnListArray(wi->work_pts);
- num_points = ZnListSize(wi->work_pts);
-
- /*
- * Fill if requested.
- */
- if (ISSET(bz->flags, FILLED_OK)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (!ZnGradientFlat(bz->fill_color)) {
- ZnPoly poly;
-
- POLY_CONTOUR1(&poly, points, num_points);
- ZnRenderGradient(wi, bz->fill_color, BezierRenderCB, bz,
- bz->grad_geo, &poly);
- }
- else if (bz->tile != ZnUnspecifiedImage) { /* Fill tiled */
- ZnRenderTile(wi, bz->tile, bz->fill_color, BezierRenderCB, bz,
- (ZnPoint *) &item->item_bounding_box);
- }
- else {
- if (bz->fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
- /*
- * Setup polygon stippling.
- */
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(ZnImagePattern(bz->fill_pattern, NULL));
- }
- color = ZnGetGradientColor(bz->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- BezierRenderCB(bz);
- glDisable(GL_POLYGON_STIPPLE);
- }
- }
-
- /*
- * Draw the lines between points
- */
- if (bz->line_width) {
- /*
- * Drawing with relief disables: ends, line style and line pattern.
- */
- if (ISSET(bz->flags, RELIEF_OK)) {
- ReliefStyle relief;
- ZnDim line_width;
- int relief_dir;
-
- relief = bz->relief;
- line_width = bz->line_width;
- if (ISCLEAR(bz->flags, CCW)) {
- line_width = -line_width;
- relief_dir = relief & RELIEF_MASK;
- if (relief_dir == RELIEF_SUNKEN) {
- relief_dir = RELIEF_RAISED;
- }
- else {
- relief_dir = RELIEF_SUNKEN;
- }
- relief = (relief & ~RELIEF_MASK) | relief_dir;
- }
- ZnRenderPolygonRelief(wi, relief, bz->gradient, True,
- points, num_points, line_width);
- }
- else {
- ZnLineEnd first = ISSET(bz->flags, FIRST_END_OK) ? bz->first_end : NULL;
- ZnLineEnd last = ISSET(bz->flags, LAST_END_OK) ? bz->last_end : NULL;
-
- ZnRenderPolyline(wi, points, num_points,
- bz->line_width, bz->line_style, bz->cap_style,
- JoinRound, first, last, bz->line_color);
- }
- }
-#endif
-}
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(Item item,
- int item_part)
-{
- return (ISSET(item->flags, SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(Item item,
- ZnPick ps)
-{
- BezierItem bz = (BezierItem) item;
- WidgetInfo *wi = item->wi;
- double dist=1.0e40, new_dist;
- ZnPoint *points, *p = ps->point;
- ZnPoint end_points[LINE_END_POINTS];
- int num_points;
- int lw = bz->line_width;
-
- if (bz->dev_points == NULL) {
- return dist;
- }
-
-/*printf("Pick in curve\n");*/
- GetBezierPath(bz->dev_points, wi->work_pts);
- points = (ZnPoint *) ZnListArray(wi->work_pts);
- num_points = ZnListSize(wi->work_pts);
-
- if (ISSET(bz->flags, FILLED_OK)) {
- dist = PolygonToPointDist(points, num_points, p);
- if (dist <= 0.0) {
- return 0.0;
- }
- }
-
- if (lw > 0) {
- if (ISCLEAR(bz->flags, RELIEF_OK)) {
- new_dist = PolylineToPointDist(points, num_points, lw,
- bz->cap_style, JoinRound, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- else {
- new_dist = ZnPolygonReliefToPointDist(points, num_points,
- ISCLEAR(bz->flags, CCW)?-lw:lw, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- }
-
- /*
- * Check line ends.
- */
- if (ISSET(bz->flags, FIRST_END_OK)) {
- GetLineEnd(&points[0], &points[1], lw, bz->cap_style,
- bz->first_end, end_points);
- new_dist = PolygonToPointDist(end_points, LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- if (ISSET(bz->flags, LAST_END_OK)) {
- GetLineEnd(&points[num_points-1], &points[num_points-2], lw,
- bz->cap_style, bz->last_end, end_points);
- new_dist = PolygonToPointDist(end_points, LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
-
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static void
-PostScript(Item item,
- PostScriptInfo ps_info)
-{
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call TRI_FREE on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(Item item,
- ZnTriStrip *tristrip)
-{
-#ifdef GPC
- BezierItem bz = (BezierItem) item;
- WidgetInfo *wi = item->wi;
-#else
- ZnPoint *points;
-#endif
-
-#ifdef GPC
- tristrip->fan = False;
- tristrip->num_strips = 0;
-
- if (bz->dev_points) {
- if (bz->tristrip.num_strips == 0) {
- ZnPoly poly;
-
- GetBezierPath(bz->dev_points, wi->work_pts);
- POLY_CONTOUR1(&poly, (ZnPoint *) ZnListArray(wi->work_pts),
- ZnListSize(wi->work_pts));
- gpc_polygon_to_tristrip((gpc_polygon *) &poly,
- (gpc_tristrip *) &bz->tristrip);
- }
-
- if (bz->tristrip.num_strips == 1) {
- TRI_STRIP1(tristrip,
- bz->tristrip.strips[0].points,
- bz->tristrip.strips[0].num_points);
- }
- else if (bz->tristrip.num_strips > 1) {
- tristrip->num_strips = bz->tristrip.num_strips;
- tristrip->strips = bz->tristrip.strips;
- }
- }
-
- return False;
-#else
- ZnListAssertSize(item->wi->work_pts, 2);
- points = (ZnPoint *) ZnListArray(item->wi->work_pts);
- TRI_STRIP1(tristrip, points, 2);
- points[0] = item->item_bounding_box.orig;
- points[1] = item->item_bounding_box.corner;
-
- return True;
-#endif
-}
-
-
-/*
- **********************************************************************************
- *
- * GetContours --
- * Get the external contour(s).
- * Never ever call POLY_FREE on the poly returned by GetContours.
- *
- **********************************************************************************
- */
-static ZnBool
-GetContours(Item item,
- ZnPoly *poly)
-{
- BezierItem bz = (BezierItem) item;
- WidgetInfo *wi = item->wi;
-
- if (bz->dev_points) {
- GetBezierPath(bz->dev_points, wi->work_pts);
-
- POLY_CONTOUR1(poly, (ZnPoint *) ZnListArray(wi->work_pts),
- ZnListSize(wi->work_pts));
- }
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item vertices.
- *
- **********************************************************************************
- */
-static int
-Coords(Item item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- int *num_pts)
-{
- BezierItem bz = (BezierItem) item;
- int num_points, i;
- ZnPoint *points;
-
- if ((cmd == COORDS_REPLACE) || (cmd == COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need at least 1 point on beziers", NULL);
- return ZN_ERROR;
- }
- if (cmd == COORDS_REPLACE_ALL) {
- ZnList tmp;
- replace_all:
- tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
- if (!bz->points) {
- ZnListEmpty(bz->points);
- }
- else {
- bz->points = ZnListNew(*num_pts, sizeof(ZnPoint));
- }
- ZnListAppend(bz->points, tmp);
- ZnListFree(tmp);
- }
- else {
- if (!bz->points) {
- edit_err:
- Tcl_AppendResult(item->wi->interp,
- " coords command cannot edit empty beziers", NULL);
- return ZN_ERROR;
- }
- points = ZnListArray(bz->points);
- num_points = ZnListSize(bz->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || (index >= num_points)) {
- range_err:
- Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
- return ZN_ERROR;
- }
- points[index] = (*pts)[0];
- }
- ITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == COORDS_READ) || (cmd == COORDS_READ_ALL)) {
- if (!bz->points) {
- *num_pts = 0;
- *pts = NULL;
- return ZN_OK;
- }
- points = ZnListArray(bz->points);
- num_points = ZnListSize(bz->points);
- if (cmd == COORDS_READ_ALL) {
- *num_pts = num_points;
- *pts = points;
- }
- else {
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || (index >= num_points)) {
- goto range_err;
- }
- *num_pts = 1;
- *pts = &points[index];
- }
- }
- else if ((cmd == COORDS_ADD) || (cmd == COORDS_ADD_LAST)) {
- if (!bz->points) {
- goto replace_all;
- }
- else if (cmd == COORDS_ADD) {
- num_points = ZnListSize(bz->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || (index >= num_points)) {
- goto range_err;
- }
- for (i = 0; i < *num_pts; i++, index++) {
- ZnListAdd(bz->points, &(*pts)[i], index);
- }
- }
- else {
- ZnList tmp;
- tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
- ZnListAppend(bz->points, tmp);
- ZnListFree(tmp);
- }
- ITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == COORDS_REMOVE) {
- if (!bz->points) {
- goto edit_err;
- }
- points = ZnListArray(bz->points);
- num_points = ZnListSize(bz->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || (index >= num_points)) {
- goto range_err;
- }
- ZnListDelete(bz->points, index);
- ITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-
- return ZN_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * PickVertex --
- * Return in 'vertex' the vertex closest to p and in 'o_vertex' the
- * opposite vertex on the closest edge, if such an edge exists or -1
- * in the other case.
- *
- **********************************************************************************
- */
-static void
-PickVertex(Item item,
- ZnPoint *p,
- int *contour,
- int *vertex,
- int *o_vertex)
-{
- BezierItem bz = (BezierItem) item;
- int i, k, num_points;
- ZnPoint *points;
- ZnReal dist=1.0e40, new_dist, dist2;
-
- *contour = *vertex = *o_vertex = -1;
-
- if ((bz->line_width > 0) || ISSET(bz->flags, FILLED_OK)) {
- points = (ZnPoint *) ZnListArray(bz->dev_points);
- num_points = ZnListSize(bz->dev_points);
- for (i = 0; i < num_points; i++) {
- new_dist = hypot(points[i].x - p->x, points[i].y - p->y);
- if (new_dist < dist) {
- dist = new_dist;
- *contour = 0;
- *vertex = i;
- }
- }
- /*
- * Update the opposite vertex.
- */
- i = (*vertex+1) % num_points;
- new_dist = LineToPointDist(&points[*vertex], &points[i], p);
- k = ((unsigned)(*vertex-1)) % num_points;
- dist2 = LineToPointDist(&points[*vertex], &points[k], p);
- if (dist2 < new_dist) {
- *o_vertex = k;
- }
- else {
- *o_vertex = i;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ItemClassStruct BEZIER_ITEM_CLASS = {
- sizeof(BezierItemStruct),
- 0, /* num_parts */
- False, /* has_anchors */
- "bezier",
- bz_attrs,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL,
- NULL,
- GetClipVertices,
- GetContours,
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- PickVertex, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnBezier = (ZnItemClassId) &BEZIER_ITEM_CLASS;