aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/tkZinc.c342
1 files changed, 305 insertions, 37 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 0dc1f21..8466880 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -50,6 +50,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ "
#include "Track.h"
#include "Transfo.h"
#include "Image.h"
+#include "gpc/gpc.h"
#include <ctype.h>
#include <stdlib.h>
@@ -1318,6 +1319,130 @@ ParseCoordList(WidgetInfo *wi,
/*
*----------------------------------------------------------------------
*
+ * Contour --
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+Contour(WidgetInfo *wi,
+ int argc,
+ Arg *args)
+{
+ ZnPoint *points;
+ ZnPoint p[4], xp[4];
+ Item item, shape;
+ int cmd, num_points, num, i;
+ ZnBool simple;
+ ZnPoly poly;
+ char c;
+ ZnTransfo t, inv;
+ ZnContour *contours;
+
+ num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, NULL);
+ if (num == 0) {
+ return ZN_ERROR;
+ }
+ if (!item->class->Contour) {
+ Tcl_AppendResult(wi->interp, "class: \"", item->class->name,
+ "\" doesn't handle the contour method", NULL);
+ return ZN_ERROR;
+ }
+
+ c = LangString(args[3])[0];
+ if ((c == 'd') && (strcmp(LangString(args[3]), "diff") == 0)) {
+ cmd = GPC_DIFF;
+ }
+ else if ((c == 'i') && (strcmp(LangString(args[3]), "inter") == 0)) {
+ cmd = GPC_INT;
+ }
+ else if ((c == 'u') && (strcmp(LangString(args[3]), "union") == 0)) {
+ cmd = GPC_UNION;
+ }
+ else if ((c == 'x') && (strcmp(LangString(args[3]), "xor") == 0)) {
+ cmd = GPC_XOR;
+ }
+ else {
+ Tcl_AppendResult(wi->interp, "unknown contour operation: \"",
+ LangString(args[3]),
+ "\" should be diff/inter/union/xor", NULL);
+ return ZN_ERROR;
+ }
+
+ num = ZnItemsWithTagOrId(wi, LangString(args[4]), &shape, NULL);
+ if (num == 0) {
+ Tcl_ResetResult(wi->interp);
+ if (ParseCoordList(wi, args[4], &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ POLY_CONTOUR1(&poly, points, num_points);
+ }
+ else {
+ /*
+ * If something has changed in the geometry we need to
+ * update or the shape will be erroneous.
+ */
+ ITEM_P.Update(wi);
+ if (!shape->class->GetClipVertices) {
+ Tcl_AppendResult(wi->interp, "class: \"", shape->class->name,
+ "\" can't give a polygonal shape", NULL);
+ return ZN_ERROR;
+ }
+ simple = shape->class->GetClipVertices(shape, &poly);
+ if (poly.num_contours == 0) {
+ return ZN_OK;
+ }
+ /*
+ * Compute the tranform to map the device points
+ * into the coordinate space of item.
+ */
+ ITEM.GetItemTransform(item, &t);
+ ZnTransfoInvert(&t, &inv);
+ /*
+ * Make a new transformed poly.
+ */
+ if (simple) {
+ p[0] = poly.contours[0].points[0];
+ p[2] = poly.contours[0].points[1];
+ p[1].x = p[2].x;
+ p[1].y = p[0].y;
+ p[3].x = p[0].x;
+ p[3].y = p[2].y;
+ ZnTransformPoints(&inv, p, xp, 4);
+ poly.contours[0].points = xp;
+ poly.contours[0].num_points = 4;
+ }
+ else {
+ if (poly.num_contours != 1) {
+ contours = poly.contours;
+ poly.contours = (ZnContour *) ZnMalloc(poly.num_contours*sizeof(ZnContour));
+ }
+ else {
+ contours = poly.contours;
+ poly.contours = &poly.contour1;
+ }
+ for (i = 0; i < poly.num_contours; i++) {
+ points = contours[i].points;
+ num_points = contours[i].num_points;
+ poly.contours[i].num_points = num_points;
+ poly.contours[i].points = (ZnPoint *) ZnMalloc(num_points*sizeof(ZnPoint));
+ ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
+ }
+ }
+ }
+
+ item->class->Contour(item, cmd, &poly);
+
+ if (!simple) {
+ POLY_FREE(&poly);
+ }
+
+ return ZN_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* Coords --
*
*----------------------------------------------------------------------
@@ -1331,7 +1456,7 @@ Coords(WidgetInfo *wi,
Item item;
int num_points, num = 0, i;
int cmd = COORDS_READ;
- long index;
+ long index, contour = 0;
char *end, c;
char msg[INTEGER_SPACE];
@@ -1341,11 +1466,11 @@ Coords(WidgetInfo *wi,
}
num_points = 0;
if (argc == 3) {
- /* Get all coords. */
- cmd = COORDS_READ_ALL;
- if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) {
+ /* Get all coords of default contour (0). */
+ if (item->class->Coords(item, 0, 0, COORDS_READ_ALL, &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
+ coords_read:
for (i = 0; i < num_points; i++, points++) {
sprintf(msg, "%g", points->x);
Tcl_AppendElement(wi->interp, msg);
@@ -1355,30 +1480,43 @@ Coords(WidgetInfo *wi,
return ZN_OK;
}
+ /*
+ * See if it is an ADD or REMOVE op.
+ */
i = 3;
c = LangString(args[i])[0];
if ((c == 'a') && (strcmp(LangString(args[i]), "add") == 0)) {
- if ((argc != 5) && (argc != 6)) {
+ if ((argc < 5) || (argc > 7)) {
Tcl_AppendResult(wi->interp, "wrong # args: should be \"", LangString(args[0]),
- "\" coords tagOrId add ?index? coordList", NULL);
+ "\" coords tagOrId add ?contour? ?index? coordList", NULL);
return ZN_ERROR;
}
cmd = COORDS_ADD;
i++;
}
else if ((c == 'r') && (strcmp(LangString(args[i]), "remove") == 0)) {
- if (argc != 5) {
+ if ((argc != 5) && (argc != 6)) {
Tcl_AppendResult(wi->interp, "wrong # args: should be \"", LangString(args[0]),
- "\" coords tagOrId remove index", NULL);
+ "\" coords tagOrId remove ?contour? index", NULL);
return ZN_ERROR;
}
cmd = COORDS_REMOVE;
i++;
}
-
- index = strtol(LangString(args[i]), &end, 10);
+
+ /*
+ * Try to see if the next param is a vertex index,
+ * a contour index or a coord list.
+ */
+ contour = index = strtol(LangString(args[i]), &end, 10);
if (*end != '\0') {
- if (((argc == 5) && (cmd != COORDS_ADD)) || (argc == 6)) {
+ if (((argc == 5) && (cmd != COORDS_ADD) && (cmd != COORDS_REMOVE)) ||
+ (argc == 6) || (argc == 7)) {
+ Tcl_AppendResult(wi->interp, " incorrect contour index \"",
+ args[i], "\"", NULL);
+ return ZN_ERROR;
+ }
+ else if ((argc == 5) && (cmd != COORDS_ADD)) {
Tcl_AppendResult(wi->interp, " incorrect coord index \"",
args[i], "\"", NULL);
return ZN_ERROR;
@@ -1387,47 +1525,97 @@ Coords(WidgetInfo *wi,
return ZN_ERROR;
}
if (cmd == COORDS_ADD) {
- /* Append coords. */
- cmd = COORDS_ADD_LAST;
- if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) {
+ /* Append coords at end of default contour (0). */
+ if (item->class->Coords(item, 0, 0, COORDS_ADD_LAST,
+ &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
}
else {
- /* Set all coords. */
- cmd = COORDS_REPLACE_ALL;
- if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) {
+ /* Set all coords of default contour (0). */
+ if (item->class->Coords(item, 0, 0, COORDS_REPLACE_ALL,
+ &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
}
return ZN_OK;
}
-
- if (argc == (i+2)) {
- /* Set a single coord or add coords at index. */
- if (ParseCoordList(wi, args[i+1], &points, &num_points) == ZN_ERROR) {
+ if (argc == 4) {
+ /* Get all coords of contour. */
+ if (item->class->Coords(item, contour, 0, COORDS_READ_ALL,
+ &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
- if (argc == 5) {
- num_points = 1;
- cmd = COORDS_REPLACE;
+ goto coords_read;
+ }
+ else if ((argc == 5) && (cmd == COORDS_REMOVE)) {
+ /* Remove coord at index in default contour (0). */
+ if (item->class->Coords(item, 0, index, COORDS_REMOVE,
+ &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
}
- if (item->class->Coords(item, index, cmd, &points, &num_points) == ZN_ERROR) {
+ return ZN_OK;
+ }
+
+ /*
+ * Try to see if the next param is a vertex index or a coord list.
+ */
+ i++;
+ index = strtol(LangString(args[i]), &end, 10);
+ if (*end != '\0') {
+ if ((argc == 7) || ((argc == 6) && (cmd != COORDS_ADD))) {
+ Tcl_AppendResult(wi->interp, " incorrect coord index \"",
+ args[i], "\"", NULL);
+ return ZN_ERROR;
+ }
+ else if (ParseCoordList(wi, args[i], &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
+ if (cmd == COORDS_ADD) {
+ /* Append coords at end of contour. */
+ if (item->class->Coords(item, contour, 0, COORDS_ADD_LAST,
+ &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ }
+ else {
+ /* Set all coords of contour. */
+ if (item->class->Coords(item, contour, 0, COORDS_REPLACE_ALL,
+ &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ }
+ return ZN_OK;
}
- else {
- /* Read a single coord or remove a coord. */
- if (item->class->Coords(item, index, cmd, &points, &num_points) == ZN_ERROR) {
+ if (argc == 5) {
+ /* Get coord of contour at index. */
+ if (item->class->Coords(item, contour, index, COORDS_READ,
+ &points, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
- if (num_points) {
- sprintf(msg, "%g", points->x);
- Tcl_AppendElement(wi->interp, msg);
- sprintf(msg, "%g", points->y);
- Tcl_AppendElement(wi->interp, msg);
+ goto coords_read;
+ }
+ else if ((argc == 6) && (cmd == COORDS_REMOVE)) {
+ /* Remove coord of contour at index. */
+ if (item->class->Coords(item, contour, index, COORDS_REMOVE,
+ &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
}
+ return ZN_OK;
+ }
+
+ /* Set a single coord or add coords at index in contour. */
+ if (ParseCoordList(wi, args[i+1], &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ if (argc == 6) {
+ num_points = 1;
+ cmd = COORDS_REPLACE;
+ }
+ if (item->class->Coords(item, contour, index, cmd, &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
}
+
return ZN_OK;
}
@@ -1832,6 +2020,21 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * contour
+ */
+ else if ((c == 'c') && (strncmp(LangString(args[1]), "contour", length) == 0)) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]),
+ "\" contour tagOrId diff/inter/union/xor coordListOrTagOrId",
+ NULL);
+ goto error;
+ }
+ if (Contour(wi, argc, args) == ZN_ERROR) {
+ goto error;
+ }
+ }
+
+ /*
* coords
*/
else if ((c == 'c') && (strncmp(LangString(args[1]), "coords", length) == 0)) {
@@ -1903,6 +2106,40 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * fit
+ */
+ else if ((c == 'f') && (strncmp(LangString(args[1]), "fit", length) == 0)) {
+ ZnPoint *points;
+ int num_points;
+ ZnReal error;
+ ZnList to_points;
+
+ if (argc != 4) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" fit coordList error", NULL);
+ goto error;
+ }
+ if (ParseCoordList(wi, args[2], &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ if (Tcl_GetDouble(interp, args[3], &error) == ZN_ERROR) {
+ goto error;
+ }
+ to_points = ZnListNew(32, sizeof(ZnPoint));
+ FitBezier(points, num_points, error, to_points);
+ points = (ZnPoint *) ZnListArray(to_points);
+ num_points = ZnListSize(to_points);
+ for (i = 0; i < num_points; i++, points++) {
+ sprintf(msg, "%g", points->x);
+ Tcl_AppendElement(wi->interp, msg);
+ sprintf(msg, "%g", points->y);
+ Tcl_AppendElement(wi->interp, msg);
+ }
+ ZnListFree(to_points);
+ }
+
+ /*
* gettags
*/
else if ((c == 'g') && (strncmp(LangString(args[1]), "gettags", length) == 0)) {
@@ -2370,6 +2607,36 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
}
/*
+ * smooth
+ */
+ else if ((c == 's') && (strncmp(LangString(args[1]), "smooth", length) == 0)) {
+ ZnPoint *points;
+ int num_points;
+ ZnList to_points;
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", LangString(args[0]),
+ "\" smooth coordList", NULL);
+ goto error;
+ }
+ if (ParseCoordList(wi, args[2], &points, &num_points) == ZN_ERROR) {
+ return ZN_ERROR;
+ }
+ to_points = ZnListNew(32, sizeof(ZnPoint));
+ SmoothPathWithBezier(points, num_points, to_points);
+ points = (ZnPoint *) ZnListArray(to_points);
+ num_points = ZnListSize(to_points);
+ for (i = 0; i < num_points; i++, points++) {
+ sprintf(msg, "%g", points->x);
+ Tcl_AppendElement(wi->interp, msg);
+ sprintf(msg, "%g", points->y);
+ Tcl_AppendElement(wi->interp, msg);
+ }
+ ZnListFree(to_points);
+ }
+
+ /*
* tapply
*/
else if ((c == 't') && (strncmp(LangString(args[1]), "tapply", length) == 0)) {
@@ -2637,11 +2904,12 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */
Tcl_AppendResult(interp, "invalid command \"", LangString(args[1]),
"\": must be "
"add, addtag, anchorxy, bbox, becomes, bind, cget, "
- "chggroup, clone, configure, coords, currentpart, "
- "dtag, find, gettags, group, hasanchors, "
+ "chggroup, clone, configure, contour, coords, currentpart, "
+ "dtag, find, fit, gettags, group, hasanchors, "
"hasfields, hasparts, hastag, itemcget, "
- "itemconfigure, lower, monitor, raise, remove, rotate, "
- "scale, tapply, tdelete, transform, translate, "
+ "itemconfigure, lower, monitor, raise, "
+ "remove, rotate, scale, smooth, tapply, tdelete, "
+ "transform, translate, "
"treset, trestore, tsave, type, ", NULL);
goto error;
}