aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2000-01-13 10:02:58 +0000
committerlecoanet2000-01-13 10:02:58 +0000
commitc565c357ebbcaa5608761b28eb63a15c850f22b4 (patch)
treea601473ca2a68ecca0369d3aa22c6c6b80a20865 /generic
parente5d87a3fc0ae33010acd42b2831b0aa46eb0c704 (diff)
downloadtkzinc-c565c357ebbcaa5608761b28eb63a15c850f22b4.zip
tkzinc-c565c357ebbcaa5608761b28eb63a15c850f22b4.tar.gz
tkzinc-c565c357ebbcaa5608761b28eb63a15c850f22b4.tar.bz2
tkzinc-c565c357ebbcaa5608761b28eb63a15c850f22b4.tar.xz
Renommage de l'item de multipoint en curve.
Suppression des lignes doubles. Utilisation du module interne de couleur. implantation des fl�ches, du relief des joints, des caps. Ecriture de la m�thode ToArea.
Diffstat (limited to 'generic')
-rw-r--r--generic/Curve.c1411
1 files changed, 1411 insertions, 0 deletions
diff --git a/generic/Curve.c b/generic/Curve.c
new file mode 100644
index 0000000..f1a836b
--- /dev/null
+++ b/generic/Curve.c
@@ -0,0 +1,1411 @@
+/*
+ * Curve.c -- Implementation of curve item.
+ *
+ * Authors : Patrick Lecoanet.
+ * Creation date : Fri Mar 25 15:32:17 1994
+ *
+ * $Id$
+ */
+
+/*
+ * Copyright (c) 1993 - 1999 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"
+
+#include <ctype.h>
+#include <alloca.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 MARKED_BIT 1<<1 /* If the vertices are marked by a symbol */
+#define SMOOTHED_BIT 1<<2 /* If we `smooth' the path with Bezier curves */
+#define BEZIER_BIT 1<<3 /* If we interpret the vertices as Bezier controls. */
+
+#define CCW 1<<5 /* Tell if the vertices are described in
+ * clockwise or ccw order. */
+#define FIRST_END_OK 1<<6
+#define LAST_END_OK 1<<7
+#define FILLED_OK 1<<8
+#define SMOOTHED_OK 1<<9
+#define RELIEF_OK 1<<10
+#define BEZIER_OK 1<<11
+#define MARKER_OK 1<<12
+
+
+/*
+ **********************************************************************************
+ *
+ * Specific Curve item record
+ *
+ **********************************************************************************
+ */
+
+typedef struct _CurveItemStruct {
+ ItemStruct header;
+
+ /* Public data */
+ RadarList points;
+ unsigned int flags;
+ Pixmap marker;
+ LineEnd first_end; /* These two are considered only if relief is flat */
+ LineEnd last_end;
+ LineStyle line_style; /* This is considered only if relief is flat */
+ int cap_style;
+ int join_style;
+ ReliefStyle relief;
+ int line_width; /* If 0 the path is not drawn, if <2 relief is flat */
+ Pixmap fill_pattern;
+ RadarColor fill_color;
+ Pixmap line_pattern;
+ RadarColor line_color;
+ RadarColor marker_color;
+ char *tile_name;
+
+ /* Private data */
+ RadarImage tile;
+ RadarList dev_points;
+ RadarList first_end_points;
+ RadarList last_end_points;
+ RadarColorGradient gradient;
+} CurveItemStruct, *CurveItem;
+
+/*
+ * Need RADAR_COORDS_FLAG in -smoothed and -bezier because
+ * -relief may need a reversing of vertices and this is done
+ * lazily.
+ */
+static RadarAttrConfig cv_attrs[] = {
+ { RADAR_CONFIG_BOOL, "-bezier", NULL,
+ Tk_Offset(CurveItemStruct, flags), BEZIER_BIT,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_CAP_STYLE, "-capstyle", NULL,
+ Tk_Offset(CurveItemStruct, cap_style), 0,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-composerotation", NULL,
+ Tk_Offset(CurveItemStruct, header.flags), COMPOSE_ROTATION_BIT,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-composescale", NULL,
+ Tk_Offset(CurveItemStruct, header.flags), COMPOSE_SCALE_BIT,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_COLOR, "-fillcolor", NULL,
+ Tk_Offset(CurveItemStruct, fill_color), 0,
+ RADAR_DRAW_FLAG|RADAR_BORDER_FLAG, False },
+ { RADAR_CONFIG_PATTERN, "-fillpattern", NULL,
+ Tk_Offset(CurveItemStruct, fill_pattern), 0, RADAR_DRAW_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-filled", NULL,
+ Tk_Offset(CurveItemStruct, flags), FILLED_BIT, RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_LINE_END, "-firstend", NULL,
+ Tk_Offset(CurveItemStruct, first_end), 0, RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_JOIN_STYLE, "-joinstyle", NULL,
+ Tk_Offset(CurveItemStruct, join_style), 0,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_LINE_END, "-lastend", NULL,
+ Tk_Offset(CurveItemStruct, last_end), 0, RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_COLOR, "-linecolor", NULL,
+ Tk_Offset(CurveItemStruct, line_color), 0,
+ RADAR_DRAW_FLAG, False },
+ { RADAR_CONFIG_PATTERN, "-linepattern", NULL,
+ Tk_Offset(CurveItemStruct, line_pattern), 0, RADAR_DRAW_FLAG, False },
+ { RADAR_CONFIG_LINE_STYLE, "-linestyle", NULL,
+ Tk_Offset(CurveItemStruct, line_style), 0, RADAR_DRAW_FLAG, False },
+ { RADAR_CONFIG_DIM, "-linewidth", NULL,
+ Tk_Offset(CurveItemStruct, line_width), 0, RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_PRI, "-priority", NULL,
+ Tk_Offset(CurveItemStruct, header.priority), 0,
+ RADAR_DRAW_FLAG|RADAR_REPICK_FLAG, False },
+ { RADAR_CONFIG_PATTERN, "-marker", NULL,
+ Tk_Offset(CurveItemStruct, marker), 0, RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_COLOR, "-markercolor", NULL,
+ Tk_Offset(CurveItemStruct, marker_color), 0, RADAR_DRAW_FLAG, False },
+ { RADAR_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(CurveItemStruct, relief), 0,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-sensitive", NULL,
+ Tk_Offset(CurveItemStruct, header.flags), SENSITIVE_BIT,
+ RADAR_REPICK_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-smoothed", NULL,
+ Tk_Offset(CurveItemStruct, flags), SMOOTHED_BIT,
+ RADAR_COORDS_FLAG, False },
+ { RADAR_CONFIG_TAGS, "-tags", NULL,
+ Tk_Offset(CurveItemStruct, header.tags), 0, 0, False },
+ { RADAR_CONFIG_IMAGE, "-tile", NULL,
+ Tk_Offset(CurveItemStruct, tile_name), 0,
+ RADAR_DRAW_FLAG|RADAR_TILE_FLAG, False },
+ { RADAR_CONFIG_BOOL, "-visible", NULL,
+ Tk_Offset(CurveItemStruct, header.flags), VISIBLE_BIT,
+ RADAR_DRAW_FLAG|RADAR_REPICK_FLAG|RADAR_VIS_FLAG, False },
+
+ { RADAR_CONFIG_END, NULL, NULL, 0, 0, 0 }
+};
+
+
+/*
+ **********************************************************************************
+ *
+ * CvTileChange --
+ *
+ **********************************************************************************
+ */
+static void
+CvTileChange(ClientData client_data,
+ int x,
+ int y,
+ int width,
+ int height,
+ int image_width,
+ int image_height)
+{
+ CurveItem cv = (CurveItem) client_data;
+
+ InvalidateImage(cv->tile);
+ ITEM.Invalidate((Item) cv, RADAR_COORDS_FLAG);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Init --
+ *
+ **********************************************************************************
+ */
+static int
+Init(Item item,
+ int *argc,
+ Arg **args)
+{
+ WidgetInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+ Arg *elems;
+ int i, result, num_elems;
+ RadarPoint p;
+#ifdef PTK
+ LangFreeProc *freeProc = NULL;
+#endif
+
+ cv->dev_points = NULL;
+ cv->first_end_points = NULL;
+ cv->last_end_points = NULL;
+ cv->gradient = NULL;
+
+ /* Init attributes */
+ SET(item->flags, VISIBLE_BIT);
+ SET(item->flags, SENSITIVE_BIT);
+ SET(item->flags, COMPOSE_ROTATION_BIT);
+ SET(item->flags, COMPOSE_SCALE_BIT);
+ item->priority = DEFAULT_MULTI_POINT_PRIORITY;
+
+ if (*argc < 1) {
+ Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
+ return RADAR_ERROR;
+ }
+ result = Lang_SplitList(wi->interp, (*args)[0], &num_elems, &elems, &freeProc);
+ if ((result == RADAR_ERROR) || ((num_elems%2) != 0)) {
+ cv_error:
+#ifdef PTK
+ if (elems != NULL && freeProc) {
+ (*freeProc)(num_elems, elems);
+ }
+#endif
+ Tcl_AppendResult(wi->interp, " malformed curve coords", NULL);
+ return RADAR_ERROR;
+ }
+
+ cv->points = RadarListNew(num_elems/2, sizeof(RadarPoint));
+ for (i = 0; i < num_elems; i += 2) {
+ if (Tcl_GetDouble(wi->interp, elems[i], &p.x) == RADAR_ERROR) {
+ cv_error2:
+#ifndef PTK
+ Tcl_Free((char *) elems);
+#endif
+ RadarListFree(cv->points);
+ cv->points = NULL;
+ goto cv_error;
+ }
+ if (Tcl_GetDouble(wi->interp, elems[i+1], &p.y) == RADAR_ERROR) {
+ goto cv_error2;
+ }
+ RadarListAdd(cv->points, &p, RadarListTail);
+ }
+ (*args)++;
+ (*argc)--;
+#ifndef PTK
+ Tcl_Free((char *) elems);
+#else
+ if (freeProc) {
+ (*freeProc)(num_elems, elems);
+ }
+#endif
+
+ CLEAR(cv->flags, FILLED_BIT);
+ CLEAR(cv->flags, SMOOTHED_BIT);
+ CLEAR(cv->flags, BEZIER_BIT);
+ cv->first_end = NULL;
+ cv->last_end = NULL;
+ cv->line_style = LINE_SIMPLE;
+ cv->relief = RELIEF_FLAT;
+ cv->line_width = 1;
+ cv->tile_name = "";
+ cv->tile = RadarUnspecifiedImage;
+ cv->fill_pattern = RadarUnspecifiedPattern;
+ cv->line_pattern = RadarUnspecifiedPattern;
+ cv->cap_style = CapRound;
+ cv->join_style = JoinRound;
+
+ /*
+ * In Tk marker visibility is controlled by the bitmap
+ * being unspecified.
+ */
+ SET(cv->flags, MARKED_BIT);
+ cv->marker = RadarUnspecifiedPattern;
+ cv->fill_color = RadarGetColorByValue(wi->win, wi->fore_color);
+ cv->line_color = RadarGetColorByValue(wi->win, wi->fore_color);
+ cv->marker_color = RadarGetColorByValue(wi->win, wi->fore_color);
+
+ return RADAR_OK;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Clone --
+ *
+ **********************************************************************************
+ */
+static void
+Clone(Item item)
+{
+ CurveItem cv = (CurveItem) item;
+ WidgetInfo *wi = item->wi;
+ char *text;
+
+ cv->first_end_points = NULL;
+ cv->last_end_points = NULL;
+ cv->dev_points = NULL;
+
+ if (cv->gradient) {
+ cv->gradient = RadarGetColorGradientByValue(cv->gradient);
+ }
+ if (cv->points) {
+ cv->points = RadarListDuplicate(cv->points);
+ }
+ if (cv->line_pattern != RadarUnspecifiedPattern) {
+ cv->line_pattern = Tk_GetBitmap(wi->interp, wi->win,
+ Tk_NameOfBitmap(wi->dpy, cv->line_pattern));
+ }
+ if (cv->first_end) {
+ LineEndDuplicate(cv->first_end);
+ }
+ if (cv->last_end) {
+ LineEndDuplicate(cv->last_end);
+ }
+ if (strlen(cv->tile_name) != 0) {
+ text = RadarMalloc((strlen(cv->tile_name) + 1) * sizeof(char));
+ strcpy(text, cv->tile_name);
+ cv->tile_name = text;
+ cv->tile = Tk_GetImage(wi->interp, wi->win, cv->tile_name,
+ CvTileChange, (ClientData) cv);
+ }
+ if (cv->fill_pattern != RadarUnspecifiedPattern) {
+ cv->fill_pattern = Tk_GetBitmap(wi->interp, wi->win,
+ Tk_NameOfBitmap(wi->dpy, cv->fill_pattern));
+ }
+ if (cv->marker != RadarUnspecifiedPattern) {
+ cv->marker = Tk_GetBitmap(wi->interp, wi->win,
+ Tk_NameOfBitmap(wi->dpy, cv->marker));
+ }
+ cv->line_color = RadarGetColorByValue(wi->win, cv->line_color);
+ cv->fill_color = RadarGetColorByValue(wi->win, cv->fill_color);
+ cv->marker_color = RadarGetColorByValue(wi->win, cv->marker_color);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Destroy --
+ *
+ **********************************************************************************
+ */
+static void
+Destroy(Item item)
+{
+ WidgetInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+
+ if (cv->points) {
+ RadarListFree(cv->points);
+ }
+ if (cv->dev_points) {
+ RadarListFree(cv->dev_points);
+ }
+ if (cv->first_end) {
+ LineEndDelete(cv->first_end);
+ }
+ if (cv->last_end) {
+ LineEndDelete(cv->last_end);
+ }
+ if (cv->first_end_points) {
+ RadarListFree(cv->first_end_points);
+ }
+ if (cv->last_end_points) {
+ RadarListFree(cv->last_end_points);
+ }
+ if (cv->gradient) {
+ RadarFreeColorGradient(cv->gradient);
+ }
+ if (strlen(cv->tile_name) != 0) {
+ RadarFree(cv->tile_name);
+ }
+ if (cv->tile != RadarUnspecifiedImage) {
+ Tk_FreeImage(cv->tile);
+ cv->tile = RadarUnspecifiedImage;
+ }
+ if (cv->line_pattern != RadarUnspecifiedPattern) {
+ Tk_FreeBitmap(wi->dpy, cv->line_pattern);
+ }
+ if (cv->fill_pattern != RadarUnspecifiedPattern) {
+ Tk_FreeBitmap(wi->dpy, cv->fill_pattern);
+ }
+ if (cv->marker != RadarUnspecifiedPattern) {
+ Tk_FreeBitmap(wi->dpy, cv->marker);
+ }
+ RadarFreeColor(cv->fill_color);
+ RadarFreeColor(cv->line_color);
+ RadarFreeColor(cv->marker_color);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Setup flags to control the precedence between the
+ * graphical attributes.
+ *
+ **********************************************************************************
+ */
+static void
+SetRenderFlags(CurveItem cv)
+{
+ ASSIGN(cv->flags, FILLED_OK,
+ ISSET(cv->flags, FILLED_BIT) && (RadarListSize(cv->points) > 2));
+
+ ASSIGN(cv->flags, BEZIER_OK,
+ ISSET(cv->flags, BEZIER_BIT) && (RadarListSize(cv->points) > 2) &&
+ (ISSET(cv->flags, FILLED_BIT) || cv->line_width));
+
+ ASSIGN(cv->flags, SMOOTHED_OK,
+ ISSET(cv->flags, SMOOTHED_BIT) && (RadarListSize(cv->points) > 2) &&
+ ISCLEAR(cv->flags, BEZIER_OK) &&
+ (ISSET(cv->flags, FILLED_BIT) || cv->line_width));
+
+ ASSIGN(cv->flags, RELIEF_OK,
+ (cv->relief != RELIEF_FLAT) && (RadarListSize(cv->points) > 1) &&
+ (cv->line_width > 1) && ISCLEAR(cv->flags, SMOOTHED_OK) &&
+ ISCLEAR(cv->flags, BEZIER_OK));
+
+ ASSIGN(cv->flags, MARKER_OK,
+ (cv->marker != RadarUnspecifiedPattern) && ISCLEAR(cv->flags, BEZIER_OK) &&
+ ISCLEAR(cv->flags, SMOOTHED_OK) && ISCLEAR(cv->flags, RELIEF_OK));
+
+ ASSIGN(cv->flags, FIRST_END_OK,
+ (cv->first_end != NULL) && (RadarListSize(cv->points) > 1) &&
+ ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
+ ISCLEAR(cv->flags, RELIEF_OK));
+
+ ASSIGN(cv->flags, LAST_END_OK,
+ (cv->last_end != NULL) && (RadarListSize(cv->points) > 1) &&
+ ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
+ ISCLEAR(cv->flags, RELIEF_OK));
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Configure --
+ *
+ **********************************************************************************
+ */
+static int
+Configure(Item item,
+ int argc,
+ RadarAttrList argv,
+ int *flags)
+{
+ WidgetInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+
+ if (ITEM_P.ConfigureAttributes((char *) item, -1, argc, argv, flags) == RADAR_ERROR) {
+ return RADAR_ERROR;
+ }
+
+ if (cv->gradient &&
+ (ISSET(*flags, RADAR_BORDER_FLAG) || (cv->relief == RELIEF_FLAT))) {
+ RadarFreeColorGradient(cv->gradient);
+ cv->gradient = NULL;
+ }
+ if ((cv->relief != RELIEF_FLAT) && !cv->gradient) {
+ cv->gradient = RadarGetReliefGradient(wi->interp, wi->win,
+ RadarNameOfColor(cv->fill_color));
+ }
+ if (ISSET(*flags, RADAR_TILE_FLAG)) {
+ Tk_Image tile;
+
+ if (strcmp(cv->tile_name, "") != 0) {
+ tile = Tk_GetImage(wi->interp, wi->win, cv->tile_name,
+ CvTileChange, (ClientData) cv);
+ if (tile == NULL) {
+ /*
+ * The name will not be in sync with the image in
+ * this case.
+ */
+ return RADAR_ERROR;
+ }
+ }
+ else {
+ tile = RadarUnspecifiedImage;
+ }
+ if (cv->tile != RadarUnspecifiedImage) {
+ Tk_FreeImage(cv->tile);
+ }
+ cv->tile = tile;
+ }
+
+ SetRenderFlags(cv);
+
+ return RADAR_OK;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Query --
+ *
+ **********************************************************************************
+ */
+static int
+Query(Item item,
+ int argc,
+ RadarAttrList argv)
+{
+ if (ITEM_P.QueryAttribute((char *) item, -1, argv[0]) == RADAR_ERROR) {
+ return RADAR_ERROR;
+ }
+
+ return RADAR_OK;
+}
+
+
+static RadarBool
+TestCCW(RadarPoint *points,
+ int num_points)
+{
+ RadarPoint *p, *p_p, *p_n, min;
+ RadarReal 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,
+ RadarBool force)
+{
+ WidgetInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+ int i, j;
+ RadarPoint *points;
+ RadarPoint end_points[LINE_END_POINTS];
+ RadarPoint *dev_points, *p;
+ int num_points;
+ RadarBBox bbox;
+ int lw;
+
+ ResetBBox(&item->item_bounding_box);
+ if (cv->points == NULL) {
+ return;
+ }
+
+ points = (RadarPoint *) RadarListArray(cv->points);
+ num_points = RadarListSize(cv->points);
+
+ /*
+ * Allocate space for devices coordinates
+ */
+ if (cv->dev_points == NULL) {
+ cv->dev_points = RadarListNew(num_points, sizeof(RadarPoint));
+ }
+ RadarListAssertSize(cv->dev_points, num_points);
+ dev_points = (RadarPoint *) RadarListArray(cv->dev_points);
+
+ /*
+ * Process all points, skipping adjacent points that transform
+ * to the same device location.
+ */
+ for (i = 0, j = 0; i < num_points; i++) {
+ /* Compute device coordinates */
+ RadarTransformPoint(wi->current_transfo, &points[i], &dev_points[j]);
+ if ((j == 0) || (dev_points[j].x != dev_points[j-1].x) ||
+ (dev_points[j].y != dev_points[j-1].y)) {
+ j++;
+ }
+ }
+
+ /*
+ * Adjust the device coords list to the actual size.
+ */
+ RadarListTruncate(cv->dev_points, j);
+ /*printf("==========num_points %d=============\n", RadarListSize(cv->dev_points));*/
+
+ lw = cv->line_width;
+
+ ASSIGN(cv->flags, CCW, TestCCW(dev_points, num_points));
+ if (ISCLEAR(cv->flags, CCW)) {
+ if (ISSET(cv->flags, RELIEF_OK)) {
+ RadarPoint tmp;
+ int mid = num_points/2;
+ /*
+ * Revert the points to draw the relief inside.
+ */
+ for (i = 0; i < mid; i++) {
+ tmp = dev_points[i];
+ dev_points[i] = dev_points[num_points-i-1];
+ dev_points[num_points-i-1] = tmp;
+ }
+ }
+ }
+
+ /*
+ * Add to bounding box.
+ */
+ if (ISSET(cv->flags, RELIEF_OK)) {
+ GetPolygonReliefBBox(cv->dev_points, lw, &bbox);
+ AddBBoxToBBox(&item->item_bounding_box, &bbox);
+ return;
+ }
+
+ for (i = 0; i < j; i++) {
+ AddPointToBBox(&item->item_bounding_box, dev_points[i].x, dev_points[i].y);
+ }
+
+ /*
+ * 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;
+
+ /*
+ * Take care of miters.
+ */
+ if (cv->join_style == JoinMiter) {
+ RadarPoint miter_i, miter_o;
+ for (i = j, p = dev_points; i >= 3; i--, p++) {
+ GetMiterPoints(p, p+1, p+2, lw, &miter_i, &miter_o);
+ AddPointToBBox(&item->item_bounding_box, miter_i.x, miter_i.y);
+ AddPointToBBox(&item->item_bounding_box, miter_o.x, miter_o.y);
+ }
+ }
+
+ /*
+ * Add the markers.
+ */
+ if (ISSET(cv->flags, MARKER_OK)) {
+ int w, h;
+ RadarBBox bbox;
+
+ Tk_SizeOfBitmap(wi->dpy, cv->marker, &w, &h);
+ w = w/2 + 2;
+ h = w/2 + 2;
+ for (i = 0; i < j; i++) {
+ bbox.orig.x = dev_points[i].x - w;
+ bbox.orig.y = dev_points[i].y - h;
+ bbox.corner.x = dev_points[i].x + w;
+ bbox.corner.y = dev_points[i].y + h;
+ AddBBoxToBBox(&item->item_bounding_box, &bbox);
+ }
+ }
+
+ /*
+ * Process arrows.
+ */
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ GetLineEnd(&dev_points[0], &dev_points[1], lw, cv->cap_style,
+ cv->first_end, end_points);
+ AddPointsToBBox(&item->item_bounding_box, end_points, LINE_END_POINTS);
+ }
+ if (ISSET(cv->flags, LAST_END_OK)) {
+ GetLineEnd(&dev_points[j-1], &dev_points[j-2], lw, cv->cap_style,
+ cv->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;
+}
+
+
+
+/*
+ **********************************************************************************
+ *
+ * ToArea --
+ * Tell if the object is entirely outside (-1),
+ * entirely inside (1) or in between (0).
+ *
+ **********************************************************************************
+ */
+static int
+ToArea(Item item,
+ RadarBBox *area,
+ Tk_Uid tag_uid,
+ int enclosed,
+ RadarBool report)
+{
+ CurveItem cv = (CurveItem) item;
+ WidgetInfo *wi = item->wi;
+ RadarBBox bbox;
+ RadarPoint *points;
+ RadarPoint end_points[LINE_END_POINTS];
+ int num_points, result;
+ RadarList actual_points;
+
+ if (cv->dev_points == NULL) {
+ return -1;
+ }
+ printf("============== poly %d ==============\n", item->id);
+ if (ISSET(cv->flags, SMOOTHED_OK)) {
+ SmoothPathWithBezier(cv->dev_points, wi->work_pts);
+ actual_points = wi->work_pts;
+ }
+ else if (ISSET(cv->flags, BEZIER_OK)) {
+ GetBezierPath(cv->dev_points, wi->work_pts);
+ actual_points = wi->work_pts;
+ }
+ else {
+ actual_points = cv->dev_points;
+ }
+
+ points = (RadarPoint *) RadarListArray(actual_points);
+ num_points = RadarListSize(actual_points);
+
+ if (ISSET(cv->flags, FILLED_OK)) {
+ result = PolygonInBBox(points, num_points, area);
+ printf("filled = %d\n", result);
+ if (result == 0) {
+ return 0;
+ }
+ }
+ else {
+ result = -1;
+ }
+ printf("result1 = %d\n", result);
+ if (cv->line_width > 0) {
+ if (ISCLEAR(cv->flags, RELIEF_OK)) {
+ if (PolylineInBBox(points, num_points, cv->line_width,
+ cv->cap_style, cv->join_style, area) != result) {
+ printf("overlap plain line\n");
+ return 0;
+ }
+ }
+ else {
+ if (PolygonReliefInBBox(actual_points, cv->line_width, area) != result) {
+ printf("overlap relief\n");
+ return 0;
+ }
+ }
+ }
+ printf("result2 = %d\n", result);
+
+ /*
+ * Check line ends.
+ */
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ GetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
+ cv->first_end, end_points);
+ if (PolygonInBBox(end_points, LINE_END_POINTS, area) != result) {
+ return 0;
+ }
+ }
+ if (ISSET(cv->flags, LAST_END_OK)) {
+ GetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
+ cv->cap_style, cv->last_end, end_points);
+ if (PolygonInBBox(end_points, LINE_END_POINTS, area) != result) {
+ return 0;
+ }
+ }
+
+ /*
+ * Last, check markers
+ */
+ if (ISSET(cv->flags, MARKER_OK)) {
+ int num_points, width, height;
+ RadarPoint *points;
+
+ points = (RadarPoint *) RadarListArray(actual_points);
+ num_points = RadarListSize(actual_points);
+
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ num_points--;
+ points++;
+ }
+ if (ISSET(cv->flags, LAST_END_OK) ||
+ ((points[0].x == points[num_points-1].x) &&
+ (points[0].y == points[num_points-1].y))) {
+ num_points--;
+ }
+
+ Tk_SizeOfBitmap(wi->dpy, cv->marker, &width, &height);
+ for (; num_points > 0; num_points--, points++) {
+ bbox.orig.x = points->x - (width+1)/2;
+ bbox.orig.y = points->y - (height+1)/2;
+ bbox.corner.x = bbox.orig.x + width;
+ bbox.corner.y = bbox.orig.y + height;
+ if (BBoxInBBox(&bbox, area) != result) {
+ return 0;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Draw --
+ *
+ **********************************************************************************
+ */
+static void
+Draw(Item item)
+{
+ WidgetInfo *wi = item->wi;
+ CurveItem cv = (CurveItem) item;
+ XGCValues values;
+ int i, num_points;
+ unsigned int gc_mask;
+ RadarPoint *points;
+ XPoint *xpoints = NULL;
+
+ if (cv->dev_points == NULL) {
+ return;
+ }
+
+ if (ISSET(cv->flags, SMOOTHED_OK)) {
+ SmoothPathWithBezier(cv->dev_points, wi->work_pts);
+ points = (RadarPoint *) RadarListArray(wi->work_pts);
+ num_points = RadarListSize(wi->work_pts);
+ }
+ else if (ISSET(cv->flags, BEZIER_OK)) {
+ GetBezierPath(cv->dev_points, wi->work_pts);
+ points = (RadarPoint *) RadarListArray(wi->work_pts);
+ num_points = RadarListSize(wi->work_pts);
+ }
+ else {
+ points = (RadarPoint *) RadarListArray(cv->dev_points);
+ num_points = RadarListSize(cv->dev_points);
+ }
+
+ /*
+ * Fill if requested.
+ */
+ if (ISSET(cv->flags, FILLED_OK)) {
+ values.foreground = RadarPixel(cv->fill_color);
+ gc_mask = GCFillStyle;
+ if (cv->tile != RadarUnspecifiedImage) { /* Fill tiled */
+ Pixmap pmap = GetImagePixmap(wi->win, cv->tile);
+ values.fill_style = FillTiled;
+ values.tile = pmap;
+ 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 (cv->fill_pattern != RadarUnspecifiedPattern) { /* Fill stippled */
+ values.fill_style = FillStippled;
+ values.stipple = cv->fill_pattern;
+ 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) {
+ xpoints = (XPoint *) alloca(num_points*sizeof(XPoint));
+ 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 (cv->line_width) {
+ RadarPoint end_points[LINE_END_POINTS];
+ XPoint xp[LINE_END_POINTS];
+
+ /*
+ * Drawing with relief disables: ends, line style and line pattern.
+ */
+ if (ISSET(cv->flags, RELIEF_OK)) {
+ DrawPolygonRelief(wi, cv->relief, cv->gradient,
+ points, num_points, cv->line_width);
+ }
+ else {
+ SetLineStyle(wi->dpy, wi->gc, cv->line_style);
+ values.foreground = RadarPixel(cv->line_color);
+ values.line_width = (cv->line_width == 1) ? 0 : cv->line_width;
+ values.join_style = cv->join_style;
+ values.cap_style = cv->cap_style;
+ if (cv->line_pattern == RadarUnspecifiedPattern) {
+ values.fill_style = FillSolid;
+ XChangeGC(wi->dpy, wi->gc,
+ GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
+ }
+ else {
+ values.fill_style = FillStippled;
+ values.stipple = cv->line_pattern;
+ XChangeGC(wi->dpy, wi->gc,
+ GCFillStyle|GCStipple|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground,
+ &values);
+ }
+ if (!xpoints) {
+ xpoints = alloca(num_points*sizeof(XPoint));
+ 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(cv->flags, FIRST_END_OK)) {
+ GetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
+ cv->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(cv->flags, LAST_END_OK)) {
+ GetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
+ cv->cap_style, cv->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);
+ }
+ }
+ }
+
+ /*
+ * Draw the marks at each point. Smoothed line or relief disable this.
+ * If ends are specified or if last point join first point suppress
+ * markers as needed.
+ */
+ if (ISSET(cv->flags, MARKER_OK)) {
+ int width, h_width, height, h_height;
+ RadarPoint ptmp, *p;
+ int i;
+
+ i = num_points;
+ p = points;
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ i--;
+ p++;
+ }
+ if (ISSET(cv->flags, LAST_END_OK) ||
+ ((p[0].x == p[num_points-1].x) &&
+ (p[0].y == p[num_points-1].y))) {
+ i--;
+ }
+
+ values.foreground = RadarPixel(cv->marker_color);
+ Tk_SizeOfBitmap(wi->dpy, cv->marker, &width, &height);
+ h_width = (width+1)/2;
+ h_height = (height+1)/2;
+ values.fill_style = FillStippled;
+ values.stipple = cv->marker;
+ for (; i > 0; i--, p++) {
+ ptmp.x = p->x - h_width;
+ ptmp.y = p->y - h_height;
+ values.ts_x_origin = ptmp.x;
+ values.ts_y_origin = ptmp.y;
+ XChangeGC(wi->dpy, wi->gc,
+ GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
+ &values);
+ XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, ptmp.x, ptmp.y,
+ width, height);
+ }
+ }
+
+ /*
+ * If nothing useful is requested then why have you
+ * created this item ? Try to do something useful, we
+ * guess that drawing points is useful.
+ */
+ if (ISCLEAR(cv->flags, FILLED_OK) && !cv->line_width &&
+ (cv->marker == RadarUnspecifiedPattern)) {
+ values.foreground = RadarPixel(cv->marker_color);
+ values.fill_style = FillSolid;
+ XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle, &values);
+
+ if (!xpoints) {
+ xpoints = alloca(num_points*sizeof(XPoint));
+ for (i = 0; i < num_points; i++) {
+ xpoints[i].x = points[i].x;
+ xpoints[i].y = points[i].y;
+ }
+ }
+ XDrawPoints(wi->dpy, wi->draw_buffer, wi->gc, xpoints, num_points, CoordModeOrigin);
+ }
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * IsSensitive --
+ *
+ **********************************************************************************
+ */
+static RadarBool
+IsSensitive(Item item,
+ int item_part)
+{
+ return (ISSET(item->flags, SENSITIVE_BIT) &&
+ item->parent->class->IsSensitive(item->parent, RADAR_NO_PART));
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Pick --
+ *
+ **********************************************************************************
+ */
+static double
+Pick(Item item,
+ RadarPoint *p,
+ Item start_item,
+ int aperture,
+ Item *a_item,
+ int *part)
+{
+ CurveItem cv = (CurveItem) item;
+ WidgetInfo *wi = item->wi;
+ RadarBBox bbox;
+ double dist=1.0e40, new_dist;
+ RadarPoint *points;
+ RadarPoint end_points[LINE_END_POINTS];
+ int num_points;
+ RadarList actual_points;
+
+ if (cv->dev_points == NULL) {
+ return dist;
+ }
+
+/*printf("Pick in curve\n");*/
+ if (ISSET(cv->flags, SMOOTHED_OK)) {
+ SmoothPathWithBezier(cv->dev_points, wi->work_pts);
+ actual_points = wi->work_pts;
+ }
+ else if (ISSET(cv->flags, BEZIER_OK)) {
+ GetBezierPath(cv->dev_points, wi->work_pts);
+ actual_points = wi->work_pts;
+ }
+ else {
+ actual_points = cv->dev_points;
+ }
+
+ points = (RadarPoint *) RadarListArray(actual_points);
+ num_points = RadarListSize(actual_points);
+
+ if (ISSET(cv->flags, FILLED_OK)) {
+ dist = PolygonToPointDist(points, num_points, p);
+ if (dist <= 0.0) {
+ return 0.0;
+ }
+ }
+
+ if (cv->line_width > 0) {
+ if (ISCLEAR(cv->flags, RELIEF_OK)) {
+ new_dist = PolylineToPointDist(points, num_points, cv->line_width,
+ cv->cap_style, cv->join_style, p);
+ if (new_dist < dist) {
+ dist = new_dist;
+ }
+
+ if (dist <= 0.0) {
+ return 0.0;
+ }
+ }
+ else {
+ new_dist = PolygonReliefToPointDist(actual_points, cv->line_width, p);
+ if (new_dist < dist) {
+ dist = new_dist;
+ }
+ if (dist <= 0.0) {
+ return 0.0;
+ }
+ }
+ }
+
+ /*
+ * Check line ends.
+ */
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ GetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
+ cv->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(cv->flags, LAST_END_OK)) {
+ GetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
+ cv->cap_style, cv->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;
+ }
+ }
+
+ /*
+ * Last, check markers
+ */
+ if (ISSET(cv->flags, MARKER_OK)) {
+ int num_points, width, height;
+ RadarPoint *points;
+
+ points = (RadarPoint *) RadarListArray(actual_points);
+ num_points = RadarListSize(actual_points);
+
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ num_points--;
+ points++;
+ }
+ if (ISSET(cv->flags, LAST_END_OK) ||
+ ((points[0].x == points[num_points-1].x) &&
+ (points[0].y == points[num_points-1].y))) {
+ num_points--;
+ }
+
+ Tk_SizeOfBitmap(wi->dpy, cv->marker, &width, &height);
+ for (; num_points > 0; num_points--, points++) {
+ bbox.orig.x = points->x - (width+1)/2;
+ bbox.orig.y = points->y - (height+1)/2;
+ bbox.corner.x = bbox.orig.x + width;
+ bbox.corner.y = bbox.orig.y + height;
+ new_dist = RectangleToPointDist(&bbox, 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.
+ *
+ **********************************************************************************
+ */
+static RadarBool
+GetClipVertices(Item item,
+ RadarPoint **points,
+ int *num_points)
+{
+ CurveItem cv = (CurveItem) item;
+
+ *points = NULL;
+ *num_points = 0;
+
+ if (cv->dev_points) {
+ *points = (RadarPoint *) RadarListArray(cv->dev_points);
+ *num_points = RadarListSize(cv->dev_points);
+ }
+
+ return False;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Coords --
+ * Return or edit the item vertices.
+ *
+ **********************************************************************************
+ */
+static int
+Coords(Item item,
+ int index,
+ int cmd,
+ RadarPoint **pts,
+ int *num_pts)
+{
+ CurveItem cv = (CurveItem) item;
+ int num_points, i;
+ RadarPoint *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 curves", NULL);
+ return RADAR_ERROR;
+ }
+ if (cmd == COORDS_REPLACE_ALL) {
+ RadarList tmp;
+ replace_all:
+ tmp = RadarListFromArray(*pts, *num_pts, sizeof(RadarPoint));
+ if (!cv->points) {
+ RadarListEmpty(cv->points);
+ }
+ else {
+ cv->points = RadarListNew(*num_pts, sizeof(RadarPoint));
+ }
+ RadarListAppend(cv->points, tmp);
+ RadarListFree(tmp);
+ }
+ else {
+ if (!cv->points) {
+ edit_err:
+ Tcl_AppendResult(item->wi->interp,
+ " coords command cannot edit empty curves", NULL);
+ return RADAR_ERROR;
+ }
+ points = RadarListArray(cv->points);
+ num_points = RadarListSize(cv->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 RADAR_ERROR;
+ }
+ points[index] = (*pts)[0];
+ }
+ ITEM.Invalidate(item, RADAR_COORDS_FLAG);
+ }
+ else if ((cmd == COORDS_READ) || (cmd == COORDS_READ_ALL)) {
+ if (!cv->points) {
+ *num_pts = 0;
+ *pts = NULL;
+ return RADAR_OK;
+ }
+ points = RadarListArray(cv->points);
+ num_points = RadarListSize(cv->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 (!cv->points) {
+ goto replace_all;
+ }
+ else if (cmd == COORDS_ADD) {
+ num_points = RadarListSize(cv->points);
+ if (index < 0) {
+ index += num_points;
+ }
+ if ((index < 0) || (index >= num_points)) {
+ goto range_err;
+ }
+ for (i = 0; i < *num_pts; i++, index++) {
+ RadarListAdd(cv->points, &(*pts)[i], index);
+ }
+ }
+ else {
+ RadarList tmp;
+ tmp = RadarListFromArray(*pts, *num_pts, sizeof(RadarPoint));
+ RadarListAppend(cv->points, tmp);
+ RadarListFree(tmp);
+ }
+ ITEM.Invalidate(item, RADAR_COORDS_FLAG);
+ }
+ else if (cmd == COORDS_REMOVE) {
+ if (!cv->points) {
+ goto edit_err;
+ }
+ points = RadarListArray(cv->points);
+ num_points = RadarListSize(cv->points);
+ if (index < 0) {
+ index += num_points;
+ }
+ if ((index < 0) || (index >= num_points)) {
+ goto range_err;
+ }
+ RadarListDelete(cv->points, index);
+ ITEM.Invalidate(item, RADAR_COORDS_FLAG);
+ }
+
+ return RADAR_OK;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Exported functions struct --
+ *
+ **********************************************************************************
+ */
+static ItemClassStruct CURVE_ITEM_CLASS = {
+ sizeof(CurveItemStruct),
+ False,
+ False,
+ False,
+ "curve",
+ cv_attrs,
+ Init,
+ Clone,
+ Destroy,
+ Configure,
+ Query,
+ NULL,
+ NULL,
+ GetClipVertices,
+ Coords,
+ ComputeCoordinates,
+ ToArea,
+ Draw,
+ IsSensitive,
+ Pick,
+ PostScript
+};
+
+RadarItemClassId RadarCurve = (RadarItemClassId) &CURVE_ITEM_CLASS;