aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorcvs2svn2005-06-10 10:29:11 +0000
committercvs2svn2005-06-10 10:29:11 +0000
commit960cdf29197bc3f5922110cf26627aa9709ac79b (patch)
tree7d6e4a472376b203d21826c2230b4a8c6a9024bd /generic
parent3fc9c4bc1d6f70db41ad418992bf3d461059d3c0 (diff)
downloadtkzinc-960cdf29197bc3f5922110cf26627aa9709ac79b.zip
tkzinc-960cdf29197bc3f5922110cf26627aa9709ac79b.tar.gz
tkzinc-960cdf29197bc3f5922110cf26627aa9709ac79b.tar.bz2
tkzinc-960cdf29197bc3f5922110cf26627aa9709ac79b.tar.xz
This commit was manufactured by cvs2svn to create branch 'bogue40'.
Diffstat (limited to 'generic')
-rw-r--r--generic/Arc.c1330
-rw-r--r--generic/Attrs.c1109
-rw-r--r--generic/Attrs.h241
-rw-r--r--generic/CharsetISO8859-15.h18
-rw-r--r--generic/CharsetUTF8.h25
-rw-r--r--generic/Color.c1220
-rw-r--r--generic/Color.h85
-rw-r--r--generic/Curve.c2260
-rw-r--r--generic/Draw.c2245
-rw-r--r--generic/Draw.h119
-rw-r--r--generic/Field.c2584
-rw-r--r--generic/Field.h85
-rw-r--r--generic/Geo.c3276
-rw-r--r--generic/Geo.h384
-rw-r--r--generic/Group.c1781
-rw-r--r--generic/Group.h35
-rw-r--r--generic/Icon.c949
-rw-r--r--generic/Image.c1695
-rw-r--r--generic/Image.h72
-rw-r--r--generic/Item.c2664
-rw-r--r--generic/Item.h377
-rw-r--r--generic/List.c557
-rw-r--r--generic/List.h68
-rw-r--r--generic/Map.c1611
-rw-r--r--generic/MapInfo.c2171
-rw-r--r--generic/MapInfo.h95
-rw-r--r--generic/OverlapMan.c1125
-rw-r--r--generic/OverlapMan.h109
-rw-r--r--generic/PostScript.c1873
-rw-r--r--generic/PostScript.h57
-rw-r--r--generic/Rectangle.c1026
-rw-r--r--generic/Reticle.c621
-rw-r--r--generic/Tabular.c706
-rw-r--r--generic/Text.c2061
-rw-r--r--generic/Track.c2372
-rw-r--r--generic/Track.h48
-rw-r--r--generic/Transfo.c754
-rw-r--r--generic/Transfo.h105
-rw-r--r--generic/Triangles.c918
-rw-r--r--generic/Types.h197
-rw-r--r--generic/WidgetInfo.h254
-rw-r--r--generic/Window.c809
-rw-r--r--generic/perfos.c345
-rw-r--r--generic/perfos.h63
-rw-r--r--generic/tkZinc.c9059
-rw-r--r--generic/tkZinc.h110
46 files changed, 0 insertions, 49668 deletions
diff --git a/generic/Arc.c b/generic/Arc.c
deleted file mode 100644
index 9d86514..0000000
--- a/generic/Arc.c
+++ /dev/null
@@ -1,1330 +0,0 @@
-/*
- * Arc.c -- Implementation of Arc item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Wed Mar 30 16:24:09 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "Types.h"
-#include "Image.h"
-#include "WidgetInfo.h"
-#include "tkZinc.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 arc is filled with color/pattern */
-#define CLOSED_BIT 1<<1 /* If the arc outline is closed */
-#define PIE_SLICE_BIT 1<<2 /* If the arc is closed as a pie slice or a chord */
-
-#define FIRST_END_OK 1<<3
-#define LAST_END_OK 1<<4
-#define USING_POLY_BIT 1<<5
-
-
-static double Pick(ZnItem item, ZnPick ps);
-
-
-/*
- **********************************************************************************
- *
- * Specific Arc item record.
- *
- **********************************************************************************
- */
-typedef struct _ArcItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint coords[2];
- int start_angle;
- int angle_extent;
- ZnImage line_pattern;
- ZnGradient *fill_color;
- ZnGradient *line_color;
- ZnDim line_width;
- ZnLineStyle line_style;
- ZnLineEnd first_end;
- ZnLineEnd last_end;
- ZnImage tile;
- unsigned short flags;
-
- /* Private data */
- ZnPoint orig;
- ZnPoint corner;
- ZnList render_shape;
- ZnPoint *grad_geo;
-} ArcItemStruct, *ArcItem;
-
-
-static ZnAttrConfig arc_attrs[] = {
- { ZN_CONFIG_BOOL, "-closed", NULL,
- Tk_Offset(ArcItemStruct, flags), CLOSED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ANGLE, "-extent", NULL,
- Tk_Offset(ArcItemStruct, angle_extent), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
- Tk_Offset(ArcItemStruct, fill_color), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(ArcItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(ArcItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_END, "-firstend", NULL,
- Tk_Offset(ArcItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-lastend", NULL,
- Tk_Offset(ArcItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
- Tk_Offset(ArcItemStruct, line_color), 0,
- ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
- { ZN_CONFIG_BITMAP, "-linepattern", NULL,
- Tk_Offset(ArcItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
- Tk_Offset(ArcItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-linewidth", NULL,
- Tk_Offset(ArcItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-pieslice", NULL,
- Tk_Offset(ArcItemStruct, flags), PIE_SLICE_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(ArcItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(ArcItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_ANGLE, "-startangle", NULL,
- Tk_Offset(ArcItemStruct, start_angle), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(ArcItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_IMAGE, "-tile", NULL,
- Tk_Offset(ArcItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(ArcItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- ArcItem arc = (ArcItem) item;
- unsigned int num_points;
- ZnPoint *points;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 1;
-
- arc->start_angle = 0;
- arc->angle_extent = 360;
- CLEAR(arc->flags, FILLED_BIT);
- CLEAR(arc->flags, CLOSED_BIT);
- CLEAR(arc->flags, PIE_SLICE_BIT);
- CLEAR(arc->flags, USING_POLY_BIT);
- arc->line_pattern = ZnUnspecifiedImage;
- arc->tile = ZnUnspecifiedImage;
- arc->line_style = ZN_LINE_SIMPLE;
- arc->line_width = 1;
- arc->first_end = arc->last_end = NULL;
- arc->render_shape = NULL;
- arc->grad_geo = NULL;
-
- if (*argc < 1) {
- Tcl_AppendResult(wi->interp, " arc coords expected", NULL);
- return TCL_ERROR;
- }
- if (ZnParseCoordList(wi, (*args)[0], &points,
- NULL, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (num_points != 2) {
- Tcl_AppendResult(wi->interp, " malformed arc coords", NULL);
- return TCL_ERROR;
- };
- arc->coords[0] = points[0];
- arc->coords[1] = points[1];
- (*args)++;
- (*argc)--;
-
- arc->fill_color = ZnGetGradientByValue(wi->fore_color);
- arc->line_color = ZnGetGradientByValue(wi->fore_color);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- ArcItem arc = (ArcItem) item;
-
- if (arc->tile != ZnUnspecifiedImage) {
- arc->tile = ZnGetImageByValue(arc->tile, ZnUpdateItemImage, item);
- }
- if (arc->first_end) {
- ZnLineEndDuplicate(arc->first_end);
- }
- if (arc->last_end) {
- ZnLineEndDuplicate(arc->last_end);
- }
- if (arc->line_pattern != ZnUnspecifiedImage) {
- arc->line_pattern = ZnGetImageByValue(arc->line_pattern, NULL, NULL);
- }
- arc->line_color = ZnGetGradientByValue(arc->line_color);
- arc->fill_color = ZnGetGradientByValue(arc->fill_color);
- arc->grad_geo = NULL;
- if (arc->render_shape) {
- arc->render_shape = ZnListDuplicate(arc->render_shape);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- ArcItem arc = (ArcItem) item;
-
- if (arc->render_shape) {
- ZnListFree(arc->render_shape);
- }
- if (arc->first_end) {
- ZnLineEndDelete(arc->first_end);
- }
- if (arc->last_end) {
- ZnLineEndDelete(arc->last_end);
- }
- if (arc->tile != ZnUnspecifiedImage) {
- ZnFreeImage(arc->tile, ZnUpdateItemImage, item);
- arc->tile = ZnUnspecifiedImage;
- }
- if (arc->line_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(arc->line_pattern, NULL, NULL);
- arc->line_pattern = ZnUnspecifiedImage;
- }
- if (arc->grad_geo) {
- ZnFree(arc->grad_geo);
- }
- ZnFreeGradient(arc->fill_color);
- ZnFreeGradient(arc->line_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Setup flags to control the precedence between the
- * graphical attributes.
- *
- **********************************************************************************
- */
-static void
-SetRenderFlags(ArcItem arc)
-{
- ASSIGN(arc->flags, FIRST_END_OK,
- (arc->first_end != NULL) && ISCLEAR(arc->flags, CLOSED_BIT) &&
- ISCLEAR(arc->flags, FILLED_BIT) && arc->line_width
- /*&& ISCLEAR(arc->flags, RELIEF_OK)*/);
-
- ASSIGN(arc->flags, LAST_END_OK,
- (arc->last_end != NULL) && ISCLEAR(arc->flags, CLOSED_BIT) &&
- ISCLEAR(arc->flags, FILLED_BIT) && arc->line_width
- /*&& ISCLEAR(arc->flags, RELIEF_OK)*/);
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ArcItem arc = (ArcItem) item;
- int status = TCL_OK;
-
- status = ZnConfigureAttributes(item->wi, item, item, arc_attrs, argc, argv, flags);
- if (arc->start_angle < 0) {
- arc->start_angle = 360 + arc->start_angle;
- }
-
- SetRenderFlags(arc);
-
- return status;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, arc_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-UpdateRenderShape(ArcItem arc)
-{
- ZnPoint *p_list, p, p2, o, o2;
- ZnReal width, height, d;
- int num_p, i, quality;
- ZnTransfo *t = ((ZnItem) arc)->wi->current_transfo;
-
- if (!arc->render_shape) {
- arc->render_shape = ZnListNew(8, sizeof(ZnPoint));
- }
- o.x = (arc->coords[1].x + arc->coords[0].x)/2.0;
- o.y = (arc->coords[1].y + arc->coords[0].y)/2.0;
- width = (arc->coords[1].x - arc->coords[0].x)/2.0;
- height = (arc->coords[1].y - arc->coords[0].y)/2.0;
- d = MAX(width, height);
- quality = ZN_CIRCLE_COARSE;
- p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
- quality,
- ZnDegRad(arc->start_angle),
- ZnDegRad(arc->angle_extent),
- &num_p,
- arc->render_shape);
-
- /*
- * Adapt the number of arc points to the radius of the arc.
- */
- p.x = o.x + p_list->x*d;
- p.y = o.y + p_list->y*d;
- ZnTransformPoint(t, &o, &o2);
- ZnTransformPoint(t, &p, &p2);
- d = hypot(o2.x-p2.x, o2.y-p2.y);
- if (d > 100.0) {
- quality = ZN_CIRCLE_FINER;
- }
- else if (d > 30.0) {
- quality = ZN_CIRCLE_FINE;
- }
- else if (d > 9.0) {
- quality = ZN_CIRCLE_MEDIUM;
- }
-
- if (quality != ZN_CIRCLE_COARSE) {
- p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
- quality,
- ZnDegRad(arc->start_angle),
- ZnDegRad(arc->angle_extent),
- &num_p,
- arc->render_shape);
- }
-
- for (i = 0; i < num_p; i++, p_list++) {
- p.x = o.x + p_list->x*width;
- p.y = o.y + p_list->y*height;
- ZnTransformPoint(t, &p, p_list);
- }
-}
-
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- ArcItem arc = (ArcItem) item;
- ZnReal angle, tmp;
- unsigned int num_p;
- ZnPoint *p_list;
- ZnPoint end_points[ZN_LINE_END_POINTS];
-
- ZnResetBBox(&item->item_bounding_box);
- /*
- * If it is neither filled nor outlined, then nothing to show.
- */
- if (!arc->line_width && ISCLEAR(arc->flags, FILLED_BIT)) {
- return;
- }
-
- /*
- * Special case for ellipse rotation and gradient.
- */
- if (!wi->render) {
- ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &angle, NULL);
- }
- if (wi->render || (angle >= PRECISION_LIMIT) || (ABS(arc->angle_extent) != 360) ||
- ISSET(arc->flags, FIRST_END_OK) || ISSET(arc->flags, LAST_END_OK)) {
- SET(arc->flags, USING_POLY_BIT);
- UpdateRenderShape(arc);
- p_list = ZnListArray(arc->render_shape);
- num_p = ZnListSize(arc->render_shape);
- ZnAddPointsToBBox(&item->item_bounding_box, p_list, num_p);
-
- tmp = (arc->line_width + 1.0) / 2.0 + 1.0;
- item->item_bounding_box.orig.x -= tmp;
- item->item_bounding_box.orig.y -= tmp;
- item->item_bounding_box.corner.x += tmp;
- item->item_bounding_box.corner.y += tmp;
-
- /*
- * Add the arrows if any.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- ZnGetLineEnd(p_list, p_list+1, arc->line_width, CapRound,
- arc->first_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- ZnGetLineEnd(&p_list[num_p-1], &p_list[num_p-2], arc->line_width, CapRound,
- arc->last_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
-
-#ifdef GL
- if (!ZnGradientFlat(arc->fill_color)) {
- ZnPoly shape;
- ZnPoint p[4];
-
- if (!arc->grad_geo) {
- arc->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
- }
- if (arc->fill_color->type == ZN_AXIAL_GRADIENT) {
- p[0] = arc->coords[0];
- p[2] = arc->coords[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;
- ZnPolyContour1(&shape, p, 4, False);
- }
- else {
- ZnPolyContour1(&shape, arc->coords, 2, False);
- }
- ZnComputeGradient(arc->fill_color, wi, &shape, arc->grad_geo);
- }
- else {
- if (arc->grad_geo) {
- ZnFree(arc->grad_geo);
- arc->grad_geo = NULL;
- }
- }
-#endif
- return;
- }
-
- /*
- ******* ******** **********
- * This part is for X drawn arcs: full extent, not rotated.
- ******* ******** **********
- */
- CLEAR(arc->flags, USING_POLY_BIT);
- ZnTransformPoint(wi->current_transfo, &arc->coords[0], &arc->orig);
- ZnTransformPoint(wi->current_transfo, &arc->coords[1], &arc->corner);
-
- ZnAddPointToBBox(&item->item_bounding_box, arc->orig.x, arc->orig.y);
- ZnAddPointToBBox(&item->item_bounding_box, arc->corner.x, arc->corner.y);
-
- tmp = (arc->line_width + 1.0) / 2.0 + 1.0;
- item->item_bounding_box.orig.x -= tmp;
- item->item_bounding_box.orig.y -= tmp;
- item->item_bounding_box.corner.x += tmp;
- item->item_bounding_box.corner.y += tmp;
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- ArcItem arc = (ArcItem) item;
- ZnPoint *points;
- ZnPoint pts[20]; /* Should be at least ZN_LINE_END_POINTS large */
- ZnPoint center;
- ZnBBox *area = ta->area;
- unsigned int num_points;
- int result=-1, result2;
- ZnReal lw = arc->line_width;
- ZnReal width, height;
-
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- if (ISSET(arc->flags, FILLED_BIT) || (arc->line_width)) {
- points = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
-
- if (ISSET(arc->flags, FILLED_BIT)) {
- result = ZnPolygonInBBox(points, num_points, area, NULL);
- if (result == 0) {
- return 0;
- }
- }
- if (arc->line_width > 0) {
- result2 = ZnPolylineInBBox(points, num_points, arc->line_width,
- CapRound, JoinRound, area);
- if (ISCLEAR(arc->flags, FILLED_BIT)) {
- if (result2 == 0) {
- return 0;
- }
- result = result2;
- }
- else if (result2 != result) {
- return 0;
- }
- if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) {
- pts[0] = points[num_points-1];
- pts[1] = points[0];
- if (ZnPolylineInBBox(pts, 2, arc->line_width,
- CapRound, JoinRound, area) != result) {
- return 0;
- }
- }
- /*
- * Check line ends.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
- arc->first_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
- CapRound, arc->last_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- }
- return result;
- }
- else {
- return -1;
- }
- }
-
- /*
- ******* ******** **********
- * The rest of this code deal with non rotated, full extent *
- * arcs. It has been stolen from tkRectOval.c *
- ******* ******** **********
- */
- /*
- * Transform both the arc and the rectangle so that the arc's oval
- * is centered on the origin.
- */
- center.x = (arc->orig.x + arc->corner.x)/2.0;
- center.y = (arc->orig.y + arc->corner.y)/2.0;
- width = (arc->corner.x - arc->orig.x) + lw;
- height = (arc->corner.y - arc->orig.y) + lw;
-
- result = ZnOvalInBBox(&center, width, height, area);
-
- /*
- * If the area appears to overlap the oval and the oval
- * isn't filled, do one more check to see if perhaps all four
- * of the area's corners are totally inside the oval's
- * unfilled center, in which case we should return "outside".
- */
- if ((result == 0) && lw && ISCLEAR(arc->flags, FILLED_BIT)) {
- ZnReal x_delta1, x_delta2, y_delta1, y_delta2;
-
- width /= 2.0;
- height /= 2.0;
- x_delta1 = (area->orig.x - center.x) / width;
- x_delta1 *= x_delta1;
- y_delta1 = (area->orig.y - center.y) / height;
- y_delta1 *= y_delta1;
- x_delta2 = (area->corner.x - center.x) / width;
- x_delta2 *= x_delta2;
- y_delta2 = (area->corner.y - center.y) / height;
- y_delta2 *= y_delta2;
- if (((x_delta1 + y_delta1) < 1.0) && ((x_delta1 + y_delta2) < 1.0) &&
- ((x_delta2 + y_delta1) < 1.0) && ((x_delta2 + y_delta2) < 1.0)) {
- return -1;
- }
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ArcItem arc = (ArcItem) item;
- XGCValues values;
- int x=0, y=0, width=0, height=0;
- ZnPoint *p=NULL;
- XPoint *xp=NULL;
- unsigned int num_points=0, i;
-
- if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
- return;
- }
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- p = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
- ZnListAssertSize(ZnWorkXPoints, num_points);
- xp = ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_points; i++, p++) {
- xp[i].x = (short) p->x;
- xp[i].y = (short) p->y;
- }
- p = ZnListArray(arc->render_shape);
- }
- else {
- if (arc->corner.x > arc->orig.x) {
- x = ((int) arc->orig.x);
- width = ((int) (arc->corner.x - arc->orig.x));
- }
- else {
- x = ((int) arc->corner.x);
- width = ((int) (arc->orig.x - arc->corner.x));
- }
- if (arc->corner.y > arc->orig.y) {
- y = ((int) arc->orig.y);
- height = ((int) (arc->corner.y - arc->orig.y));
- }
- else {
- y = ((int) arc->corner.y);
- height = ((int) (arc->orig.y - arc->corner.y));
- }
- }
-
- /* Fill if requested */
- if (ISSET(arc->flags, FILLED_BIT)) {
- values.foreground = ZnGetGradientPixel(arc->fill_color, 0.0);
- values.arc_mode = ISSET(arc->flags, PIE_SLICE_BIT) ? ArcPieSlice : ArcChord;
- if (arc->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(arc->tile)) { /* Fill tiled */
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(arc->tile, wi->win);
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile|GCArcMode,
- &values);
- }
- else { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(arc->tile, wi->win);
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground|GCArcMode,
- &values);
- }
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCArcMode, &values);
- }
-
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xp, (int) num_points, Nonconvex, CoordModeOrigin);
- }
- else {
- XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, (unsigned int) width, (unsigned int) height,
- -arc->start_angle*64, -arc->angle_extent*64);
- }
- }
-
- /*
- * Draw the arc.
- */
- if (arc->line_width) {
- ZnPoint end_points[ZN_LINE_END_POINTS];
- XPoint xap[ZN_LINE_END_POINTS];
-
- ZnSetLineStyle(wi, arc->line_style);
- values.foreground = ZnGetGradientPixel(arc->line_color, 0.0);
- values.line_width = (arc->line_width == 1) ? 0 : (int) arc->line_width;
- values.cap_style = CapRound;
- values.join_style = JoinRound;
- if (arc->line_pattern == ZnUnspecifiedImage) {
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCLineWidth|GCCapStyle|GCJoinStyle|GCForeground, &values);
- }
- else {
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(arc->line_pattern, wi->win);
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCStipple|GCLineWidth|GCCapStyle|GCJoinStyle|GCForeground,
- &values);
- }
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- if (ISCLEAR(arc->flags, CLOSED_BIT) && arc->angle_extent != 360) {
- num_points--;
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- num_points--;
- }
- }
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc,
- xp, (int) num_points, CoordModeOrigin);
- if (ISSET(arc->flags, FIRST_END_OK)) {
- p = (ZnPoint *) ZnListArray(arc->render_shape);
- ZnGetLineEnd(p, p+1, arc->line_width, CapRound,
- arc->first_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xap[i].x = (short) end_points[i].x;
- xap[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- p = (ZnPoint *) ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
- ZnGetLineEnd(&p[num_points-1], &p[num_points-2], arc->line_width,
- CapRound, arc->last_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xap[i].x = (short) end_points[i].x;
- xap[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- }
- else {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, (unsigned int) width, (unsigned int) height,
- -arc->start_angle*64, -arc->angle_extent*64);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-ArcRenderCB(void *closure)
-{
- ZnItem item = (ZnItem) closure;
- ArcItem arc = (ArcItem) item;
- int num_points=0, i;
- ZnPoint *p=NULL;
- ZnPoint center;
-
- center.x = (item->item_bounding_box.corner.x + item->item_bounding_box.orig.x) / 2.0;
- center.y = (item->item_bounding_box.corner.y + item->item_bounding_box.orig.y) / 2.0;
- p = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
- glBegin(GL_TRIANGLE_FAN);
- glVertex2d(center.x, center.y);
- for (i = 0; i < num_points; i++) {
- glVertex2d(p[i].x, p[i].y);
- }
- glEnd();
-}
-#endif
-
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ArcItem arc = (ArcItem) item;
- unsigned int num_points=0;
- ZnPoint *p=NULL;
-
- if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
- return;
- }
-
-#ifdef GL_LIST
- if (!item->gl_list) {
- item->gl_list = glGenLists(1);
- glNewList(item->gl_list, GL_COMPILE);
-#endif
- /* Fill if requested */
- if (ISSET(arc->flags, FILLED_BIT)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- if (!ZnGradientFlat(arc->fill_color)) {
- ZnPoly poly;
-
- ZnPolyContour1(&poly, ZnListArray(arc->render_shape),
- ZnListSize(arc->render_shape), False);
- ZnRenderGradient(wi, arc->fill_color, ArcRenderCB, arc,
- arc->grad_geo, &poly);
- }
- else if (arc->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
- ZnRenderTile(wi, arc->tile, arc->fill_color, ArcRenderCB, arc,
- (ZnPoint *) &item->item_bounding_box);
- }
- else {
- unsigned short alpha;
- XColor *color = ZnGetGradientColor(arc->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- ArcRenderCB(arc);
- }
- }
-
- /*
- * Draw the arc.
- */
- if (arc->line_width) {
- ZnLineEnd first = ISSET(arc->flags, FIRST_END_OK) ? arc->first_end : NULL;
- ZnLineEnd last = ISSET(arc->flags, LAST_END_OK) ? arc->last_end : NULL;
- ZnBool closed = ISSET(arc->flags, CLOSED_BIT);
-
- p = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
- if (!closed) {
- if (arc->angle_extent != 360) {
- num_points--;
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- num_points--;
- }
- }
- }
- ZnRenderPolyline(wi, p, num_points, arc->line_width,
- arc->line_style, CapRound, JoinRound, first, last,
- arc->line_color);
- }
-#ifdef GL_LIST
- glEndList();
- }
-
- glCallList(item->gl_list);
-#endif
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static ZnReal
-Pick(ZnItem item,
- ZnPick ps)
-{
- ArcItem arc = (ArcItem) item;
- double dist = 1e40, new_dist;
- ZnPoint center;
- ZnPoint *points, *p = ps->point;
- ZnPoint end_points[ZN_LINE_END_POINTS];
- unsigned int num_points;
- ZnDim lw = arc->line_width;
-
- if (ISCLEAR(arc->flags, FILLED_BIT) && ! arc->line_width) {
- return dist;
- }
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- points = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
-
- if (ISSET(arc->flags, FILLED_BIT)) {
- dist = ZnPolygonToPointDist(points, num_points, p);
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- if (arc->line_width > 0) {
- if (ISCLEAR(arc->flags, CLOSED_BIT) && arc->angle_extent != 360) {
- num_points--;
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- num_points--;
- }
- }
- new_dist = ZnPolylineToPointDist(points, num_points, arc->line_width,
- CapRound, JoinRound, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
-
- /*
- * Check line ends.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
- arc->first_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
- CapRound, arc->last_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- }
- return dist;
- }
-
- /*
- ******* ******** **********
- * The rest of this code deal with non rotated full extent arcs. *
- ******* ******** **********
- */
- center.x = (arc->orig.x + arc->corner.x) / 2.0;
- center.y = (arc->orig.y + arc->corner.y) / 2.0;
- dist = ZnOvalToPointDist(&center, arc->corner.x - arc->orig.x,
- arc->corner.y - arc->orig.y, lw, p);
- if (dist < 0.0) {
- if (ISSET(arc->flags, FILLED_BIT)) {
- dist = 0.0;
- }
- else {
- dist = -dist;
- }
- }
- return dist;
-}
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static void
-UpdateRenderShapeX(ArcItem arc)
-{
- ZnReal ox, oy, width_2, height_2;
- int i, num_p;
- ZnPoint *p_list;
-
- if (!arc->render_shape) {
- arc->render_shape = ZnListNew(8, sizeof(ZnPoint));
- }
- p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
- ZN_CIRCLE_FINE,
- ZnDegRad(arc->start_angle),
- ZnDegRad(arc->angle_extent),
- &num_p, arc->render_shape);
- ox = (arc->corner.x + arc->orig.x) / 2.0;
- oy = (arc->corner.y + arc->orig.y) / 2.0;
- width_2 = (arc->corner.x - arc->orig.x) / 2.0;
- height_2 = (arc->corner.y - arc->orig.y) / 2.0;
- for (i = 0; i < num_p; i++, p_list++) {
- p_list->x = ox + p_list->x*width_2;
- p_list->y = oy + p_list->y*height_2;
- }
-}
-
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- ArcItem arc = (ArcItem) item;
- ZnPoint center;
-
- if (ISCLEAR(arc->flags, USING_POLY_BIT) || !arc->render_shape) {
- UpdateRenderShapeX(arc);
- SET(arc->flags, USING_POLY_BIT);
- }
-
-
- center.x = (item->item_bounding_box.corner.x + item->item_bounding_box.orig.x) / 2.0;
- center.y = (item->item_bounding_box.corner.y + item->item_bounding_box.orig.y) / 2.0;
- ZnListEmpty(ZnWorkPoints);
- ZnListAdd(ZnWorkPoints, &center, ZnListTail);
- ZnListAppend(ZnWorkPoints, arc->render_shape);
- ZnTriStrip1(tristrip, ZnListArray(ZnWorkPoints),
- ZnListSize(ZnWorkPoints), True);
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetContours --
- * Get the external contour(s).
- * Never ever call ZnPolyFree on the tristrip returned by GetContours.
- *
- **********************************************************************************
- */
-static ZnBool
-GetContours(ZnItem item,
- ZnPoly *poly)
-{
- ArcItem arc = (ArcItem) item;
-
- if (ISCLEAR(arc->flags, USING_POLY_BIT) || !arc->render_shape) {
- UpdateRenderShapeX(arc);
- }
-
- ZnPolyContour1(poly, ZnListArray(arc->render_shape),
- ZnListSize(arc->render_shape), True);
- poly->contour1.controls = NULL;
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item vertices.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- ArcItem arc = (ArcItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " arcs can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if (cmd == ZN_COORDS_REPLACE_ALL) {
- if (*num_pts != 2) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 2 points on arcs", NULL);
- return TCL_ERROR;
- }
- arc->coords[0] = (*pts)[0];
- arc->coords[1] = (*pts)[1];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == ZN_COORDS_REPLACE) {
- if (*num_pts < 1) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need at least 1 point", NULL);
- return TCL_ERROR;
- }
- if (index < 0) {
- index += 2;
- }
- if ((index < 0) || (index > 1)) {
- range_err:
- Tcl_AppendResult(item->wi->interp,
- " incorrect coord index, should be between -2 and 1", NULL);
- return TCL_ERROR;
- }
- arc->coords[index] = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == ZN_COORDS_READ_ALL) {
- *num_pts = 2;
- *pts = arc->coords;
- }
- else if (cmd == ZN_COORDS_READ) {
- if (index < 0) {
- index += 2;
- }
- if ((index < 0) || (index > 1)) {
- goto range_err;
- }
- *num_pts = 1;
- *pts = &arc->coords[index];
- }
-
- return TCL_OK;
-}
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnBBox *bbox = &item->item_bounding_box;
-
- ZnOrigin2Anchor(&bbox->orig,
- bbox->corner.x - bbox->orig.x,
- bbox->corner.y - bbox->orig.y,
- anchor, p);
-}
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ArcItem arc = (ArcItem) item;
- ZnWInfo *wi = item->wi;
- ZnPoint *p;
- int i, num_points;
- char path[500];
-
- if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
- return TCL_OK;
- }
-
- /*
- * Create the arc path.
- */
- if (ISSET(arc->flags, USING_POLY_BIT)) {
- p = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
- sprintf(path, "%.15g %.15g moveto ", p[0].x, p[0].y);
- Tcl_AppendResult(wi->interp, path, NULL);
- for (i = 0; i < num_points; i++) {
- sprintf(path, "%.15g %.15g lineto ", p[i].x, p[i].y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- Tcl_AppendResult(wi->interp, "closepath\n", NULL);
- }
- else {
- sprintf(path,
- "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
- (arc->corner.x + arc->orig.x) / 2.0, (arc->corner.y + arc->orig.y) / 2.0,
- (arc->corner.x - arc->orig.x) / 2.0, (arc->corner.y - arc->orig.y) / 2.0);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
-
- /*
- * Emit code to draw the filled area.
- */
- if (ISSET(arc->flags, FILLED_BIT)) {
- if (arc->line_width) {
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- }
- if (!ZnGradientFlat(arc->fill_color)) {
- if (ZnPostscriptGradient(wi->interp, wi->ps_info, arc->fill_color,
- arc->grad_geo, NULL) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- else if (arc->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(arc->tile)) { /* Fill tiled */
- /* TODO No support yet */
- }
- else { /* Fill stippled */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "clip ", NULL);
- if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
- ZnImagePixmap(arc->tile, wi->win)) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- }
- else { /* Fill solid */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "fill\n", NULL);
- }
- if (arc->line_width) {
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
-
- /*
- * Then emit code code to stroke the outline.
- */
- if (arc->line_width) {
- Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
- if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
- arc->line_width, arc->line_style,
- arc->line_color, arc->line_pattern) != TCL_OK) {
- return TCL_ERROR;
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct ARC_ITEM_CLASS = {
- "arc",
- sizeof(ArcItemStruct),
- arc_attrs,
- 0, /* num_parts */
- 0, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- GetContours,
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnArc = (ZnItemClassId) &ARC_ITEM_CLASS;
diff --git a/generic/Attrs.c b/generic/Attrs.c
deleted file mode 100644
index 5b6a74f..0000000
--- a/generic/Attrs.c
+++ /dev/null
@@ -1,1109 +0,0 @@
-/*
- * Attrs.c -- Various attributes manipulation routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Fri Dec 31 10:03:34 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Attrs.h"
-#include "Item.h"
-#include "List.h"
-#include "Geo.h"
-#include "WidgetInfo.h"
-
-#include <GL/glu.h>
-#include <memory.h>
-#include <stdlib.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- ****************************************************************
- *
- * Code for reliefs.
- *
- ****************************************************************
- */
-#define RELIEF_FLAT_SPEC "flat"
-#define RELIEF_RAISED_SPEC "raised"
-#define RELIEF_SUNKEN_SPEC "sunken"
-#define RELIEF_GROOVE_SPEC "groove"
-#define RELIEF_RIDGE_SPEC "ridge"
-#define RELIEF_ROUND_RAISED_SPEC "roundraised"
-#define RELIEF_ROUND_SUNKEN_SPEC "roundsunken"
-#define RELIEF_ROUND_GROOVE_SPEC "roundgroove"
-#define RELIEF_ROUND_RIDGE_SPEC "roundridge"
-#define RELIEF_SUNKEN_RULE_SPEC "sunkenrule"
-#define RELIEF_RAISED_RULE_SPEC "raisedrule"
-
-int
-ZnGetRelief(ZnWInfo *wi,
- char *name,
- ZnReliefStyle *relief)
-{
- size_t length;
-
- length = strlen(name);
- if (strncmp(name, RELIEF_FLAT_SPEC, length) == 0) {
- *relief = ZN_RELIEF_FLAT;
- }
- else if (strncmp(name, RELIEF_SUNKEN_SPEC, length) == 0) {
- *relief = ZN_RELIEF_SUNKEN;
- }
- else if ((strncmp(name, RELIEF_RAISED_SPEC, length) == 0) && (length >= 2)) {
- *relief = ZN_RELIEF_RAISED;
- }
- else if ((strncmp(name, RELIEF_RIDGE_SPEC, length) == 0) && (length >= 2)) {
- *relief = ZN_RELIEF_RIDGE;
- }
- else if (strncmp(name, RELIEF_GROOVE_SPEC, length) == 0) {
- *relief = ZN_RELIEF_GROOVE;
- }
- else if ((strncmp(name, RELIEF_ROUND_SUNKEN_SPEC, length) == 0) && (length >= 6)) {
- *relief = ZN_RELIEF_ROUND_SUNKEN;
- }
- else if ((strncmp(name, RELIEF_ROUND_RAISED_SPEC, length) == 0) && (length >= 7)) {
- *relief = ZN_RELIEF_ROUND_RAISED;
- }
- else if ((strncmp(name, RELIEF_ROUND_RIDGE_SPEC, length) == 0) && (length >= 7)) {
- *relief = ZN_RELIEF_ROUND_RIDGE;
- }
- else if ((strncmp(name, RELIEF_ROUND_GROOVE_SPEC, length) == 0) && (length >= 6)) {
- *relief = ZN_RELIEF_ROUND_GROOVE;
- }
- else if ((strncmp(name, RELIEF_SUNKEN_RULE_SPEC, length) == 0) && (length >= 7)) {
- *relief = ZN_RELIEF_SUNKEN_RULE;
- }
- else if ((strncmp(name, RELIEF_RAISED_RULE_SPEC, length) == 0) && (length >= 7)) {
- *relief = ZN_RELIEF_RAISED_RULE;
- }
- else {
- Tcl_AppendResult(wi->interp, "bad relief \"", name, "\": must be ",
- RELIEF_FLAT_SPEC, ", ",
- RELIEF_RAISED_SPEC, ", ",
- RELIEF_SUNKEN_SPEC, ", ",
- RELIEF_GROOVE_SPEC, ", ",
- RELIEF_RIDGE_SPEC, ", ",
- RELIEF_ROUND_RAISED_SPEC, ", ",
- RELIEF_ROUND_SUNKEN_SPEC, ", ",
- RELIEF_ROUND_GROOVE_SPEC, ", ",
- RELIEF_ROUND_RIDGE_SPEC, ", ",
- RELIEF_SUNKEN_RULE_SPEC, ", ",
- RELIEF_RAISED_RULE_SPEC,
- NULL);
- return TCL_ERROR;
- }
- if (!wi->render) {
- *relief = *relief & ~(ZN_RELIEF_ROUND|ZN_RELIEF_RULE);
- }
-
- return TCL_OK;
-}
-
-char *
-ZnNameOfRelief(ZnReliefStyle relief)
-{
- switch (relief) {
- case ZN_RELIEF_FLAT:
- return RELIEF_FLAT_SPEC;
- case ZN_RELIEF_SUNKEN:
- return RELIEF_SUNKEN_SPEC;
- case ZN_RELIEF_RAISED:
- return RELIEF_RAISED_SPEC;
- case ZN_RELIEF_GROOVE:
- return RELIEF_GROOVE_SPEC;
- case ZN_RELIEF_RIDGE:
- return RELIEF_RIDGE_SPEC;
- case ZN_RELIEF_ROUND_SUNKEN:
- return RELIEF_ROUND_SUNKEN_SPEC;
- case ZN_RELIEF_ROUND_RAISED:
- return RELIEF_ROUND_RAISED_SPEC;
- case ZN_RELIEF_ROUND_GROOVE:
- return RELIEF_ROUND_GROOVE_SPEC;
- case ZN_RELIEF_ROUND_RIDGE:
- return RELIEF_ROUND_RIDGE_SPEC;
- case ZN_RELIEF_SUNKEN_RULE:
- return RELIEF_SUNKEN_RULE_SPEC;
- case ZN_RELIEF_RAISED_RULE:
- return RELIEF_RAISED_RULE_SPEC;
- default:
- return "unknown relief";
- }
-}
-
-/*
- ****************************************************************
- *
- * Code for borders.
- *
- ****************************************************************
- */
-#define BORDER_LEFT_SPEC "left"
-#define BORDER_RIGHT_SPEC "right"
-#define BORDER_TOP_SPEC "top"
-#define BORDER_BOTTOM_SPEC "bottom"
-#define BORDER_CONTOUR_SPEC "contour"
-#define BORDER_COUNTER_OBLIQUE_SPEC "counteroblique"
-#define BORDER_OBLIQUE_SPEC "oblique"
-#define NO_BORDER_SPEC "noborder"
-
-int
-ZnGetBorder(ZnWInfo *wi,
- Tcl_Obj *name,
- ZnBorder *border)
-{
- unsigned int j, len, largc;
- Tcl_Obj **largv;
- char *str;
-
- *border = ZN_NO_BORDER;
- if (Tcl_ListObjGetElements(wi->interp, name,
- &largc, &largv) == TCL_ERROR) {
- border_error:
- Tcl_AppendResult(wi->interp, "bad line shape \"", Tcl_GetString(name),
- "\": must be a list of ",
- BORDER_LEFT_SPEC, ", ",
- BORDER_RIGHT_SPEC, ", ",
- BORDER_TOP_SPEC, ", ",
- BORDER_BOTTOM_SPEC, ", ",
- BORDER_COUNTER_OBLIQUE_SPEC, ", ",
- BORDER_OBLIQUE_SPEC, " or ",
- BORDER_CONTOUR_SPEC, ", ",
- NO_BORDER_SPEC, " alone",
- NULL);
- return TCL_ERROR;
- }
- for (j = 0; j < largc; j++) {
- str = Tcl_GetString(largv[j]);
- len = strlen(str);
- if (strncmp(str, BORDER_LEFT_SPEC, len) == 0) {
- *border |= ZN_LEFT_BORDER;
- }
- else if (strncmp(str, BORDER_RIGHT_SPEC, len) == 0) {
- *border |= ZN_RIGHT_BORDER;
- }
- else if (strncmp(str, BORDER_TOP_SPEC, len) == 0) {
- *border |= ZN_TOP_BORDER;
- }
- else if (strncmp(str, BORDER_BOTTOM_SPEC, len) == 0) {
- *border |= ZN_BOTTOM_BORDER;
- }
- else if (strncmp(str, BORDER_CONTOUR_SPEC, len) == 0) {
- *border |= ZN_CONTOUR_BORDER;
- }
- else if (strncmp(str, BORDER_OBLIQUE_SPEC, len) == 0) {
- *border |= ZN_OBLIQUE;
- }
- else if (strncmp(str, BORDER_COUNTER_OBLIQUE_SPEC, len) == 0) {
- *border |= ZN_COUNTER_OBLIQUE;
- }
- else if (strncmp(str, NO_BORDER_SPEC, len) == 0) {
- *border = ZN_NO_BORDER;
- }
- else {
- goto border_error;
- }
- }
- return TCL_OK;
-}
-
-/*
- * name must be large enough to hold the returned string.
- * 64 chars should be enough with the current values.
- */
-void
-ZnNameOfBorder(ZnBorder border,
- char *name)
-{
- if (border == ZN_NO_BORDER) {
- strcpy(name, NO_BORDER_SPEC);
- return;
- }
- name[0] = 0;
- if ((border & ZN_CONTOUR_BORDER) == ZN_CONTOUR_BORDER) {
- strcat(name, BORDER_CONTOUR_SPEC);
- }
- else {
- if (border & ZN_LEFT_BORDER) {
- strcat(name, BORDER_LEFT_SPEC);
- }
- if (border & ZN_RIGHT_BORDER) {
- if (name[0] != 0) {
- strcat(name, " ");
- }
- strcat(name, BORDER_RIGHT_SPEC);
- }
- if (border & ZN_TOP_BORDER) {
- if (name[0] != 0) {
- strcat(name, " ");
- }
- strcat(name, BORDER_TOP_SPEC);
- }
- if (border & ZN_BOTTOM_BORDER) {
- if (name[0] != 0) {
- strcat(name, " ");
- }
- strcat(name, BORDER_BOTTOM_SPEC);
- }
- }
- if (border & ZN_OBLIQUE) {
- if (name[0] != 0) {
- strcat(name, " ");
- }
- strcat(name, BORDER_OBLIQUE_SPEC);
- }
- if (border & ZN_COUNTER_OBLIQUE) {
- if (name[0] != 0) {
- strcat(name, " ");
- }
- strcat(name, BORDER_COUNTER_OBLIQUE_SPEC);
- }
-}
-
-/*
- ****************************************************************
- *
- * Code for line shapes.
- *
- ****************************************************************
- */
-#define STRAIGHT_SPEC "straight"
-#define RIGHT_LIGHTNING_SPEC "rightlightning"
-#define LEFT_LIGHTNING_SPEC "leftlightning"
-#define RIGHT_CORNER_SPEC "rightcorner"
-#define LEFT_CORNER_SPEC "leftcorner"
-#define DOUBLE_RIGHT_CORNER_SPEC "doublerightcorner"
-#define DOUBLE_LEFT_CORNER_SPEC "doubleleftcorner"
-
-int
-ZnGetLineShape(ZnWInfo *wi,
- char *name,
- ZnLineShape *line_shape)
-{
- unsigned int len;
-
- len = strlen(name);
- if (strncmp(name, STRAIGHT_SPEC, len) == 0) {
- *line_shape = ZN_LINE_STRAIGHT;
- }
- else if (strncmp(name, RIGHT_LIGHTNING_SPEC, len) == 0) {
- *line_shape = ZN_LINE_RIGHT_LIGHTNING;
- }
- else if (strncmp(name, LEFT_LIGHTNING_SPEC, len) == 0) {
- *line_shape = ZN_LINE_LEFT_LIGHTNING;
- }
- else if (strncmp(name, RIGHT_CORNER_SPEC, len) == 0) {
- *line_shape = ZN_LINE_RIGHT_CORNER;
- }
- else if (strncmp(name, LEFT_CORNER_SPEC, len) == 0) {
- *line_shape = ZN_LINE_LEFT_CORNER;
- }
- else if (strncmp(name, DOUBLE_RIGHT_CORNER_SPEC, len) == 0) {
- *line_shape = ZN_LINE_DOUBLE_RIGHT_CORNER;
- }
- else if (strncmp(name, DOUBLE_LEFT_CORNER_SPEC, len) == 0) {
- *line_shape = ZN_LINE_DOUBLE_LEFT_CORNER;
- }
- else {
- Tcl_AppendResult(wi->interp, "bad line shape \"", name, "\": must be ",
- STRAIGHT_SPEC, ", ",
- RIGHT_LIGHTNING_SPEC, ", ",
- LEFT_LIGHTNING_SPEC, ", ",
- RIGHT_CORNER_SPEC, ", ",
- LEFT_CORNER_SPEC, ", ",
- DOUBLE_RIGHT_CORNER_SPEC, ", ",
- DOUBLE_LEFT_CORNER_SPEC,
- NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-char *
-ZnNameOfLineShape(ZnLineShape line_shape)
-{
- switch (line_shape) {
- case ZN_LINE_STRAIGHT:
- return STRAIGHT_SPEC;
- case ZN_LINE_RIGHT_LIGHTNING:
- return RIGHT_LIGHTNING_SPEC;
- case ZN_LINE_LEFT_LIGHTNING:
- return LEFT_LIGHTNING_SPEC;
- case ZN_LINE_RIGHT_CORNER:
- return RIGHT_CORNER_SPEC;
- case ZN_LINE_LEFT_CORNER:
- return LEFT_CORNER_SPEC;
- case ZN_LINE_DOUBLE_RIGHT_CORNER:
- return DOUBLE_RIGHT_CORNER_SPEC;
- case ZN_LINE_DOUBLE_LEFT_CORNER:
- return DOUBLE_LEFT_CORNER_SPEC;
- default:
- return "unknown line shape";
- }
-}
-
-/*
- ****************************************************************
- *
- * Code for line styles.
- *
- ****************************************************************
- */
-#define SIMPLE_SPEC "simple"
-#define DASHED_SPEC "dashed"
-#define DOTTED_SPEC "dotted"
-#define MIXED_SPEC "mixed"
-
-int
-ZnGetLineStyle(ZnWInfo *wi,
- char *name,
- ZnLineStyle *line_style)
-{
- unsigned int len;
-
- len = strlen(name);
- if (strncmp(name, SIMPLE_SPEC, len) == 0)
- *line_style = ZN_LINE_SIMPLE;
- else if (strncmp(name, DASHED_SPEC, len) == 0)
- *line_style = ZN_LINE_DASHED;
- else if (strncmp(name, MIXED_SPEC, len) == 0)
- *line_style = ZN_LINE_MIXED;
- else if (strncmp(name, DOTTED_SPEC, len) == 0)
- *line_style = ZN_LINE_DOTTED;
- else {
- Tcl_AppendResult(wi->interp, "bad line style \"", name, "\": must be ",
- SIMPLE_SPEC, ", ",
- DASHED_SPEC, ", ",
- DOTTED_SPEC, ", ",
- MIXED_SPEC,
- NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-char *
-ZnNameOfLineStyle(ZnLineStyle line_style)
-{
- switch (line_style) {
- case ZN_LINE_SIMPLE:
- return SIMPLE_SPEC;
- case ZN_LINE_DASHED:
- return DASHED_SPEC;
- case ZN_LINE_MIXED:
- return MIXED_SPEC;
- case ZN_LINE_DOTTED:
- return DOTTED_SPEC;
- default:
- return "unknown line style";
- }
-}
-
-/*
- ****************************************************************
- *
- * Code for leader anchors.
- *
- * Format is: lChar leftLeaderAnchor [ lChar rightLeaderAnchor]
- *
- * If lChar is a '|', leftLeaderAnchor and rightLeaderAnchor are the indices
- * of the fields that serve to anchor the label's leader. More specifically
- * the bottom left corner of the left field and the bottom right corner of
- * the right field are used as the anchors.
- * If lChar is '%', leftLeaderAnchor and rightLeaderAnchor should be
- * specified as 'valxval', 'val' being a percentage (max 100) of the
- * width/height of the label bounding box.
- * If rightLeaderAnchor is not specified it defaults to leftLeaderAnchor.
- * If neither of them are specified, the center of the label is used as an
- * anchor.
- *
- ****************************************************************
- */
-int
-ZnGetLeaderAnchors(ZnWInfo *wi,
- char *name,
- ZnLeaderAnchors *leader_anchors)
-{
- int anchors[4];
- int index, num_tok, anchor_index=0;
-
- *leader_anchors = NULL;
- while (*name && (*name == ' ')) {
- name++;
- }
- while (*name && (anchor_index < 4)) {
- switch (*name) {
- case '|':
- num_tok = sscanf(name, "|%d%n", &anchors[anchor_index], &index);
- if (num_tok != 1) {
- la_error:
- Tcl_AppendResult(wi->interp, " incorrect leader anchors \"",
- name, "\"", NULL);
- return TCL_ERROR;
- }
- anchors[anchor_index+1] = -1;
- break;
- case '%':
- num_tok = sscanf(name, "%%%dx%d%n", &anchors[anchor_index],
- &anchors[anchor_index+1], &index);
- if (num_tok != 2) {
- goto la_error;
- }
- if (anchors[anchor_index] < 0) {
- anchors[anchor_index] = 0;
- }
- if (anchors[anchor_index] > 100) {
- anchors[anchor_index] = 100;
- }
- if (anchors[anchor_index+1] < 0) {
- anchors[anchor_index+1] = 0;
- }
- if (anchors[anchor_index+1] > 100) {
- anchors[anchor_index+1] = 100;
- }
- break;
- default:
- goto la_error;
- }
- anchor_index += 2;
- name += index;
- }
- /*
- * If empty, pick the default (center of the bounding box).
- */
- if (anchor_index != 0) {
- *leader_anchors = ZnMalloc(sizeof(ZnLeaderAnchorsStruct));
- (*leader_anchors)->left_x = anchors[0];
- (*leader_anchors)->left_y = anchors[1];
- if (anchor_index == 2) {
- (*leader_anchors)->right_x = (*leader_anchors)->left_x;
- (*leader_anchors)->right_y = (*leader_anchors)->left_y;
- }
- else {
- (*leader_anchors)->right_x = anchors[2];
- (*leader_anchors)->right_y = anchors[3];
- }
- }
- return TCL_OK;
-}
-
-/*
- * name must be large enough to hold the returned string.
- */
-void
-ZnNameOfLeaderAnchors(ZnLeaderAnchors leader_anchors,
- char *name)
-{
- unsigned int count;
-
- if (!leader_anchors) {
- strcpy(name, "%50x50");
- }
- else {
- if (leader_anchors->left_y < 0) {
- count = sprintf(name, "|%d", leader_anchors->left_x);
- }
- else {
- count = sprintf(name, "%%%dx%d", leader_anchors->left_x,
- leader_anchors->left_y);
- }
- name += count;
- if (leader_anchors->right_y < 0) {
- sprintf(name, "|%d", leader_anchors->right_x);
- }
- else {
- sprintf(name, "%%%dx%d", leader_anchors->right_x, leader_anchors->right_y);
- }
- }
-}
-
-/*
- ******************************************************************
- *
- * Code for label formats.
- *
- ******************************************************************
- */
-static Tcl_HashTable format_cache;
-static ZnBool format_inited = False;
-
-
-static char
-CharToAttach(int attach)
-{
- switch (attach) {
- case '>':
- return ZN_LF_ATTACH_FWD;
- case '<':
- return ZN_LF_ATTACH_BWD;
- case '^':
- return ZN_LF_ATTACH_LEFT;
- case '$':
- return ZN_LF_ATTACH_RIGHT;
- case '+':
- default:
- return ZN_LF_ATTACH_PIXEL;
- }
-}
-
-static char
-CharToDim(int dim)
-{
- switch (dim) {
- case 'f':
- return ZN_LF_DIM_FONT;
- case 'i':
- return ZN_LF_DIM_ICON;
- case 'a':
- return ZN_LF_DIM_AUTO;
- case 'l':
- return ZN_LF_DIM_LABEL;
- case 'x':
- default:
- return ZN_LF_DIM_PIXEL;
- }
-}
-
-/*
- * The new format is as follow. Parameters between [] are
- * optional and take default values when omitted. The spaces can appear
- * between blocks but not inside.
- *
- * [ WidthxHeight ] [ field0Spec ][ field1Spec ]...[ fieldnSpec ]
- *
- * Width and Height set the size of the clipping box surrounding
- * the label. If it is not specified, there will be no clipping.
- * It it is specified alone it is the size of the only displayed
- * field (0).
- *
- * fieldSpec is:
- * sChar fieldWidth sChar fieldHeight [pChar fieldX pChar fieldY].
- *
- * Each field description refers to the field of same index in the field
- * array.
- * If sChar is 'x', the dimension is in pixel. If sChar is 'f', the
- * dimension is in percentage of the mean width/height of a character (in the
- * field font). If sChar is 'i', the dimension is in percentage of the size
- * of the image in the field. If sChar is 'a', the dimension is automatically
- * adjusted to match the field's content plus the given value in pixels.
- * If pChar is '+' the position is in pixel (possibly negative). If it is
- * '<' the position is the index of the field at the left/top of which the
- * current field should be attached. If it is '>' the position is the index
- * of the field at the right/bottom of which the current field should be
- * attached. If pChar is '^' the position is the index of the field used to
- * align the left/top border (left on left or top on top). If pChar is '$' the
- * position is the index of the field used to align the right/bottom border
- * (right on right or bottom on bottom).
- * The positional parameters can be omitted if there is only one field.
- *
- */
-ZnLabelFormat
-ZnLFCreate(Tcl_Interp *interp,
- char *format_str,
- unsigned int num_fields)
-{
- ZnList fields;
- Tcl_HashEntry *entry;
- ZnFieldFormatStruct field_struct;
- ZnFieldFormat field_array;
- ZnLabelFormat format;
- int width, height;
- ZnDim c_width=0.0, c_height=0.0;
- int index, num_tok, num_ffs, new;
- unsigned int field_index=0;
- char *ptr = format_str, *next_ptr;
- char x_char, y_char;
-
- if (!format_inited) {
- Tcl_InitHashTable(&format_cache, TCL_STRING_KEYS);
- format_inited = True;
- }
- entry = Tcl_CreateHashEntry(&format_cache, format_str, &new);
- if (!new) {
- format = (ZnLabelFormat) Tcl_GetHashValue(entry);
- if (format->num_fields <= num_fields) {
- format->ref_count++;
- return format;
- }
- else {
- Tcl_AppendResult(interp, "too many fields in label format: \"",
- format_str, "\"", NULL);
- return NULL;
- }
- }
-
- fields = ZnListNew(1, sizeof(ZnFieldFormatStruct));
-
- /*
- * Try to see if it starts with a number or a leader spec.
- */
- while (*ptr && (*ptr == ' ')) {
- ptr++;
- }
- if (!*ptr) {
- goto lf_error_syn;
- }
- if ((*ptr != 'x') && (*ptr != 'f') && (*ptr != 'i') &&
- (*ptr != 'a') && (*ptr != 'l')) {
- c_width = (ZnDim) strtod(ptr, &next_ptr);
- if ((ptr == next_ptr) || (*next_ptr != 'x')) {
- lf_error_syn:
- Tcl_AppendResult(interp, "invalid label format specification \"",
- ptr, "\"", NULL);
- lf_error:
- Tcl_DeleteHashEntry(entry);
- ZnListFree(fields);
- return NULL;
- }
- ptr = next_ptr+1;
- c_height = (ZnDim) strtod(ptr, &next_ptr);
- if (ptr == next_ptr) {
- goto lf_error_syn;
- }
- ptr = next_ptr;
- }
- if (!*ptr) {
- /* It is a simple spec, one field. */
- field_struct.x_attach = field_struct.y_attach = ZN_LF_ATTACH_PIXEL;
- field_struct.x_dim = field_struct.y_dim = ZN_LF_DIM_PIXEL;
- field_struct.x_spec = field_struct.y_spec = 0;
- field_struct.width_spec = (short) c_width;
- field_struct.height_spec = (short) c_height;
- c_width = c_height = 0.0;
- ZnListAdd(fields, &field_struct, ZnListTail);
- goto lf_end_parse;
- }
-
- /*
- * Parse the field specs.
- */
- lf_parse2:
- while (*ptr && (*ptr == ' ')) {
- ptr++;
- }
- if (!*ptr) {
- goto lf_end_parse;
- }
- /* Preset the default field values. */
- field_struct.x_spec = field_struct.y_spec = 0;
- field_struct.x_attach = field_struct.y_attach = ZN_LF_ATTACH_PIXEL;
- field_struct.x_dim = field_struct.y_dim = ZN_LF_DIM_PIXEL;
- if ((*ptr == 'x') || (*ptr == 'f') || (*ptr == 'i') ||
- (*ptr == 'a') || (*ptr == 'l')) {
- num_tok = sscanf(ptr, "%c%d%c%d%n", &x_char, &width,
- &y_char, &height, &index);
- if (num_tok != 4) {
- goto lf_error_syn;
- }
- if (width < 0) {
- width = 0;
- }
- if (height < 0) {
- height = 0;
- }
- field_struct.x_dim = CharToDim(x_char);
- field_struct.y_dim = CharToDim(y_char);
-
- ptr += index;
- if ((*ptr == '>') || (*ptr == '<') || (*ptr == '+') ||
- (*ptr == '^') || (*ptr == '$')) {
- num_tok = sscanf(ptr, "%c%d%c%d%n", &x_char, &field_struct.x_spec,
- &y_char, &field_struct.y_spec, &index);
- if (num_tok != 4) {
- goto lf_error_syn;
- }
- field_struct.x_attach = CharToAttach(x_char);
- field_struct.y_attach = CharToAttach(y_char);
-
- ptr += index;
- }
- else if (!*ptr || (field_index != 0)) {
- /* An incomplete field spec is an error if there are several fields. */
- Tcl_AppendResult(interp, "incomplete field in label format: \"",
- ptr-index, "\"", NULL);
- goto lf_error;
- }
- if (field_index >= num_fields) {
- Tcl_AppendResult(interp, "too many fields in label format: \"",
- format_str, "\"", NULL);
- goto lf_error;
- }
- field_struct.width_spec = (short) width;
- field_struct.height_spec = (short) height;
- ZnListAdd(fields, &field_struct, ZnListTail);
- field_index++;
- goto lf_parse2;
- }
- else {
- goto lf_error_syn;
- }
-
- lf_end_parse:
- field_array = (ZnFieldFormat) ZnListArray(fields);
- num_ffs = ZnListSize(fields);
-
- format = (ZnLabelFormat) ZnMalloc(sizeof(ZnLabelFormatStruct) +
- (num_ffs-1) * sizeof(ZnFieldFormatStruct));
- format->clip_width = (short) c_width;
- format->clip_height = (short) c_height;
- format->num_fields = num_ffs;
- memcpy(&format->fields, field_array, num_ffs * sizeof(ZnFieldFormatStruct));
- ZnListFree(fields);
-
- format->ref_count = 1;
- format->entry = entry;
- Tcl_SetHashValue(entry, (ClientData) format);
-
- return format;
-}
-
-
-ZnLabelFormat
-ZnLFDuplicate(ZnLabelFormat lf)
-{
- lf->ref_count++;
- return lf;
-}
-
-
-void
-ZnLFDelete(ZnLabelFormat lf)
-{
- lf->ref_count--;
- if (lf->ref_count == 0) {
- Tcl_DeleteHashEntry(lf->entry);
- ZnFree(lf);
- }
-}
-
-
-char *
-ZnLFGetString(ZnLabelFormat lf)
-{
- return Tcl_GetHashKey(&format_cache, lf->entry);
-
-#if 0
- ZnFieldFormat ff;
- char *ptr;
- char x_char, y_char, w_char, h_char;
- unsigned int i, count;
-
- ptr = str;
- if ((lf->clip_width != 0) || (lf->clip_height != 0)) {
- count = sprintf(ptr, "%dx%d", lf->clip_width, lf->clip_height);
- ptr += count;
- }
- if (lf->left_y < 0) {
- count = sprintf(ptr, "|%d", lf->left_x);
- }
- else {
- count = sprintf(ptr, "%%%dx%d", lf->left_x, lf->left_y);
- }
- ptr += count;
- if (lf->right_y < 0) {
- count = sprintf(ptr, "|%d", lf->right_x);
- }
- else {
- count = sprintf(ptr, "%%%dx%d", lf->right_x, lf->right_y);
- }
- ptr += count;
- for (i = 0; i < lf->num_fields; i++) {
- ff = &lf->fields[i];
- x_char = AttachToChar(ff->x_attach);
- y_char = AttachToChar(ff->y_attach);
- w_char = DimToChar(ff->x_dim);
- h_char = DimToChar(ff->y_dim);
- count = sprintf(ptr, "%c%d%c%d%c%d%c%d",
- w_char, ff->width_spec, h_char, ff->height_spec,
- x_char, ff->x_spec, y_char, ff->y_spec);
- ptr += count;
- }
- *ptr = 0;
-#endif
-}
-
-
-/*
- * If the clip box has both its width and its height
- * set to zero, it means that there is no clipbox.
- */
-ZnBool
-ZnLFGetClipBox(ZnLabelFormat lf,
- ZnDim *w,
- ZnDim *h)
-{
- if ((lf->clip_width == 0) && (lf->clip_height == 0)) {
- return False;
- }
-
- *w = (ZnDim) lf->clip_width;
- *h = (ZnDim) lf->clip_height;
-
- return True;
-}
-
-
-void
-ZnLFGetField(ZnLabelFormat lf,
- unsigned int field,
- char *x_attach,
- char *y_attach,
- char *x_dim,
- char *y_dim,
- int *x_spec,
- int *y_spec,
- short *width_spec,
- short *height_spec)
-{
- ZnFieldFormat fptr;
-
- fptr = &lf->fields[field];
- *x_attach = fptr->x_attach;
- *y_attach = fptr->y_attach;
- *x_dim = fptr->x_dim;
- *y_dim = fptr->y_dim;
- *x_spec = fptr->x_spec;
- *y_spec = fptr->y_spec;
- *width_spec = fptr->width_spec;
- *height_spec = fptr->height_spec;
-}
-
-
-/*
- ****************************************************************
- *
- * Code for line ends.
- *
- ****************************************************************
- */
-static Tcl_HashTable line_end_cache;
-static ZnBool line_end_inited = False;
-
-
-ZnLineEnd
-ZnLineEndCreate(Tcl_Interp *interp,
- char *line_end_str)
-{
- Tcl_HashEntry *entry;
- ZnLineEnd le;
- int new, argc;
- ZnReal a, b, c;
-
- if (!line_end_inited) {
- Tcl_InitHashTable(&line_end_cache, TCL_STRING_KEYS);
- line_end_inited = True;
- }
-
- entry = Tcl_CreateHashEntry(&line_end_cache, line_end_str, &new);
- if (!new) {
- le = (ZnLineEnd) Tcl_GetHashValue(entry);
- le->ref_count++;
- return le;
- }
-
- argc = sscanf(line_end_str, "%lf %lf %lf", &a, &b, &c);
- if (argc == 3) {
- le = (ZnLineEnd) ZnMalloc(sizeof(ZnLineEndStruct));
- le->shape_a = a;
- le->shape_b = b;
- le->shape_c = c;
- le->entry = entry;
- le->ref_count = 1;
- Tcl_SetHashValue(entry, (ClientData) le);
- return le;
- }
- else {
- Tcl_AppendResult(interp, "incorrect line end spec: \"",
- line_end_str, "\", should be: shapeA shapeB shapeC", NULL);
- return NULL;
- }
-}
-
-
-char *
-ZnLineEndGetString(ZnLineEnd le)
-{
- return Tcl_GetHashKey(&line_end_cache, le->entry);
-}
-
-
-void
-ZnLineEndDelete(ZnLineEnd le)
-{
- le->ref_count--;
- if (le->ref_count == 0) {
- Tcl_DeleteHashEntry(le->entry);
- ZnFree(le);
- }
-}
-
-
-ZnLineEnd
-ZnLineEndDuplicate(ZnLineEnd le)
-{
- le->ref_count++;
- return le;
-}
-
-
-/*
- ******************************************************************
- *
- * Code for fill rules. They are directly inhereted from the
- * GLU tesselator constants.
- *
- ******************************************************************
- */
-#define FILL_RULE_ODD_SPEC "odd"
-#define FILL_RULE_NON_ZERO_SPEC "nonzero"
-#define FILL_RULE_POSITIVE_SPEC "positive"
-#define FILL_RULE_NEGATIVE_SPEC "negative"
-#define FILL_RULE_ABS_GEQ_2_SPEC "abs_geq_2"
-
-int
-ZnGetFillRule(ZnWInfo *wi,
- char *name,
- ZnFillRule *fill_rule)
-{
- unsigned int len;
-
- len = strlen(name);
- if (strncmp(name, FILL_RULE_ODD_SPEC, len) == 0) {
- *fill_rule = GLU_TESS_WINDING_ODD;
- }
- else if (strncmp(name, FILL_RULE_NON_ZERO_SPEC, len) == 0) {
- *fill_rule = GLU_TESS_WINDING_NONZERO;
- }
- else if (strncmp(name, FILL_RULE_POSITIVE_SPEC, len) == 0) {
- *fill_rule = GLU_TESS_WINDING_POSITIVE;
- }
- else if (strncmp(name, FILL_RULE_NEGATIVE_SPEC, len) == 0) {
- *fill_rule = GLU_TESS_WINDING_NEGATIVE;
- }
- else if (strncmp(name, FILL_RULE_ABS_GEQ_2_SPEC, len) == 0) {
- *fill_rule = GLU_TESS_WINDING_ABS_GEQ_TWO;
- }
- else {
- Tcl_AppendResult(wi->interp, "bad fill rule \"", name, "\": must be ",
- FILL_RULE_ODD_SPEC, ", ",
- FILL_RULE_NON_ZERO_SPEC, ", ",
- FILL_RULE_POSITIVE_SPEC, ", ",
- FILL_RULE_NEGATIVE_SPEC, ", ",
- FILL_RULE_ABS_GEQ_2_SPEC,
- NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-char *
-ZnNameOfFillRule(ZnFillRule fill_rule)
-{
- switch (fill_rule) {
- case GLU_TESS_WINDING_ODD:
- return FILL_RULE_ODD_SPEC;
- case GLU_TESS_WINDING_NONZERO:
- return FILL_RULE_NON_ZERO_SPEC;
- case GLU_TESS_WINDING_POSITIVE:
- return FILL_RULE_POSITIVE_SPEC;
- case GLU_TESS_WINDING_NEGATIVE:
- return FILL_RULE_NEGATIVE_SPEC;
- case GLU_TESS_WINDING_ABS_GEQ_TWO:
- return FILL_RULE_ABS_GEQ_2_SPEC;
- default:
- return "unknown fill rule";
- }
-}
-
-
-/*
- ******************************************************************
- *
- * Code for auto alignments in fields.
- *
- ******************************************************************
- */
-int
-ZnGetAutoAlign(ZnWInfo *wi,
- char *name,
- ZnAutoAlign *aa)
-{
- int j;
-
- if (strcmp(name, "-") == 0) {
- aa->automatic = False;
- }
- else if (strlen(name) == 3) {
- aa->automatic = True;
- for (j = 0; j < 3; j++) {
- switch(name[j]) {
- case 'l':
- case 'L':
- aa->align[j] = TK_JUSTIFY_LEFT;
- break;
- case 'c':
- case 'C':
- aa->align[j] = TK_JUSTIFY_CENTER;
- break;
- case 'r':
- case 'R':
- aa->align[j] = TK_JUSTIFY_RIGHT;
- break;
- default:
- goto aa_error;
- }
- }
- }
- else {
- aa_error:
- Tcl_AppendResult(wi->interp, "invalid auto alignment specification \"", name,
- "\" should be - or a triple of lcr", NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- * name must be large enough to hold the returned string.
- * 64 chars should be enough with the current values.
- */
-void
-ZnNameOfAutoAlign(ZnAutoAlign *aa,
- char *name)
-{
- unsigned int i;
-
- if (aa->automatic == False) {
- strcpy(name, "-");
- }
- else {
- name[0] = 0;
- for (i = 0; i < 3; i++) {
- switch (aa->align[i]) {
- case TK_JUSTIFY_LEFT:
- strcat(name, "l");
- break;
- case TK_JUSTIFY_CENTER:
- strcat(name, "c");
- break;
- case TK_JUSTIFY_RIGHT:
- strcat(name, "r");
- break;
- }
- }
- }
-}
diff --git a/generic/Attrs.h b/generic/Attrs.h
deleted file mode 100644
index fad8134..0000000
--- a/generic/Attrs.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Attrs.h -- Header for the attribute manipulation routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Fri Dec 31 10:06:37 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Attrs_h
-#define _Attrs_h
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-
-#include <Types.h>
-
-
-struct _ZnWInfo;
-
-/*
- * Type and constant values for line styles.
- */
-typedef unsigned char ZnLineStyle;
-
-#define ZN_LINE_SIMPLE 0
-#define ZN_LINE_DASHED 1
-#define ZN_LINE_MIXED 2
-#define ZN_LINE_DOTTED 3
-
-int ZnGetLineStyle(struct _ZnWInfo *wi, char *name, ZnLineStyle *line_style);
-char *ZnNameOfLineStyle(ZnLineStyle line_style);
-
-
-/*
- * Type and constant values for line shapes.
- */
-typedef unsigned char ZnLineShape;
-
-#define ZN_LINE_STRAIGHT 0
-#define ZN_LINE_LEFT_LIGHTNING 1
-#define ZN_LINE_LEFT_CORNER 2
-#define ZN_LINE_DOUBLE_LEFT_CORNER 3
-#define ZN_LINE_RIGHT_LIGHTNING 4
-#define ZN_LINE_RIGHT_CORNER 5
-#define ZN_LINE_DOUBLE_RIGHT_CORNER 6
-
-int ZnGetLineShape(struct _ZnWInfo *wi, char *name, ZnLineShape *line_shape);
-char *ZnNameOfLineShape(ZnLineShape line_shape);
-
-
-/*
- * Type and constant values for relief styles.
- */
-typedef unsigned char ZnReliefStyle;
-#define ZN_RELIEF_FLAT 0
-#define ZN_RELIEF_RAISED 1
-#define ZN_RELIEF_SUNKEN 2
-#define ZN_RELIEF_GROOVE (ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN)
-#define ZN_RELIEF_RIDGE (ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED)
-#define ZN_RELIEF_ROUND_SUNKEN (ZN_RELIEF_ROUND|ZN_RELIEF_SUNKEN)
-#define ZN_RELIEF_ROUND_RAISED (ZN_RELIEF_ROUND|ZN_RELIEF_RAISED)
-#define ZN_RELIEF_ROUND_GROOVE (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN)
-#define ZN_RELIEF_ROUND_RIDGE (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED)
-#define ZN_RELIEF_SUNKEN_RULE (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN|ZN_RELIEF_RULE)
-#define ZN_RELIEF_RAISED_RULE (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED|ZN_RELIEF_RULE)
-#define ZN_RELIEF_ROUND 0x80
-#define ZN_RELIEF_TWO_FACES 0x40
-#define ZN_RELIEF_RULE 0x20
-#define ZN_RELIEF_MASK 0x3
-
-/*
- * Number of steps for relief drawing. This translate in
- * RELIEF_STEPS*2+1 color shades in the color gradient.
- */
-#define ZN_RELIEF_STEPS 6
-
-int ZnGetRelief(struct _ZnWInfo *wi, char *name, ZnReliefStyle *relief);
-char *ZnNameOfRelief(ZnReliefStyle relief);
-
-
-/*
- * Type and constant values for borders.
- */
-typedef unsigned char ZnBorder;
-#define ZN_NO_BORDER 0
-#define ZN_LEFT_BORDER 1
-#define ZN_RIGHT_BORDER 2
-#define ZN_TOP_BORDER 4
-#define ZN_BOTTOM_BORDER 8
-#define ZN_CONTOUR_BORDER (ZN_LEFT_BORDER|ZN_RIGHT_BORDER|ZN_TOP_BORDER|ZN_BOTTOM_BORDER)
-#define ZN_COUNTER_OBLIQUE 16
-#define ZN_OBLIQUE 32
-
-void ZnNameOfBorder(ZnBorder border, char *str);
-int ZnGetBorder(struct _ZnWInfo *wi, Tcl_Obj *name, ZnBorder *border);
-
-
-/*
- * Type for leader anchors.
- */
-typedef struct {
- int left_x; /* left leader anchor field or percent of bbox */
- int right_x; /* right leader anchor field or percent of bbox */
- short left_y; /* left leader percent of bbox or < 0 if field */
- short right_y; /* right leader percent of bbox or < 0 if field */
-} ZnLeaderAnchorsStruct, *ZnLeaderAnchors;
-
-int ZnGetLeaderAnchors(struct _ZnWInfo *wi, char *name, ZnLeaderAnchors *leader_anchors);
-void ZnNameOfLeaderAnchors(ZnLeaderAnchors leader_anchors, char *name);
-
-
-/*
- * Type and constant values for automatic alignments.
- */
-typedef struct {
- ZnBool automatic;
- Tk_Justify align[3];
-} ZnAutoAlign;
-#define ZN_AA_LEFT 0
-#define ZN_AA_CENTER 1
-#define ZN_AA_RIGHT 2
-
-int ZnGetAutoAlign(struct _ZnWInfo *wi, char *name, ZnAutoAlign *aa);
-void ZnNameOfAutoAlign(ZnAutoAlign *aa, char *name);
-
-
-/*
- * Label Formats.
- */
-
-/*
- * field flags.
- */
-#define ZN_LF_ATTACH_PIXEL 0
-#define ZN_LF_ATTACH_FWD 1
-#define ZN_LF_ATTACH_BWD 2
-#define ZN_LF_ATTACH_LEFT 3 /* Align left on left or top on top */
-#define ZN_LF_ATTACH_RIGHT 4 /* Align right on right or bottom on bottom */
-
-#define ZN_LF_DIM_PIXEL 0
-#define ZN_LF_DIM_FONT 1
-#define ZN_LF_DIM_ICON 2
-#define ZN_LF_DIM_AUTO 3
-#define ZN_LF_DIM_LABEL 4
-
-typedef struct {
- int x_spec;
- int y_spec;
- short width_spec;
- short height_spec;
- char x_attach;
- char y_attach;
- char x_dim;
- char y_dim;
-} ZnFieldFormatStruct, *ZnFieldFormat;
-
-typedef struct {
- short clip_width;
- short clip_height;
- unsigned int num_fields;
- Tcl_HashEntry *entry;
- unsigned int ref_count;
- ZnFieldFormatStruct fields[1];
-} ZnLabelFormatStruct, *ZnLabelFormat;
-
-
-ZnLabelFormat
-ZnLFCreate(Tcl_Interp * /* interp */,
- char * /* format_str */,
- unsigned int /* num_fields */);
-ZnLabelFormat
-ZnLFDuplicate(ZnLabelFormat /* label_format */);
-void
-ZnLFDelete(ZnLabelFormat /* label_format */);
-char *
-ZnLFGetString(ZnLabelFormat /* label_format */);
-ZnBool
-ZnLFGetClipBox(ZnLabelFormat /* label_format */,
- ZnDim * /* width */,
- ZnDim * /* height */);
-#define ZnLFNumFields(lf) ((lf)->num_fields)
-void
-ZnLFGetField(ZnLabelFormat /* label_format */,
- unsigned int /* field */,
- char * /* x_attach */,
- char * /* y_attach */,
- char * /* x_dim */,
- char * /* y_dim */,
- int * /* x_spec */,
- int * /* y_spec */,
- short * /* width_spec */,
- short * /* height_spec */);
-
-/*
- * Line Ends.
- */
-typedef struct {
- ZnReal shape_a;
- ZnReal shape_b;
- ZnReal shape_c;
- Tcl_HashEntry *entry;
- unsigned int ref_count;
-} ZnLineEndStruct, *ZnLineEnd;
-
-ZnLineEnd
-ZnLineEndCreate(Tcl_Interp *interp,
- char *line_end_str);
-ZnLineEnd
-ZnLineEndDuplicate(ZnLineEnd le);
-void
-ZnLineEndDelete(ZnLineEnd le);
-char *
-ZnLineEndGetString(ZnLineEnd le);
-
-
-/*
- * Type and protypes for fill rules.
- */
-typedef unsigned int ZnFillRule;
-
-char *ZnNameOfFillRule(ZnFillRule fill_rule);
-int ZnGetFillRule(struct _ZnWInfo *wi, char *name, ZnFillRule *fill_rule);
-
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _Attrs_h */
diff --git a/generic/CharsetISO8859-15.h b/generic/CharsetISO8859-15.h
deleted file mode 100644
index 1dbf21e..0000000
--- a/generic/CharsetISO8859-15.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * These chars are those found in iso8859-15.
- * They are encoded in iso8859-15 right in this file and sorted
- * by ascending value, _keep_ them sorted this way, a dichotomic
- * search rely on this to locate the glyphs and infos.
- */
-static unsigned char *ZnDefaultCharset =
- " !\"#$%&'()*+,-./"
- "0123456789"
- ":;<=>?@"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "[\\]^_`"
- "abcdefghijklmnopqrstuvwxyz"
- "{|}~"
- "¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿"
- "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß"
- "àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
- "¾";
diff --git a/generic/CharsetUTF8.h b/generic/CharsetUTF8.h
deleted file mode 100644
index 9fee91e..0000000
--- a/generic/CharsetUTF8.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * These chars are those found in iso8859-15 and iso8859-1.
- * They are encoded in UTF8 right in this file and sorted
- * by Unicode point, _keep_ them sorted this way, a dichotomic
- * search rely on this to locate the glyphs and infos.
- */
-static unsigned char *ZnDefaultCharset =
- " !\"#$%&'()*+,-./"
- "0123456789"
- ":;<=>?@"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "[\\]^_`"
- "abcdefghijklmnopqrstuvwxyz"
- "{|}~"
- "¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿"
- "ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖ×ØÙÚÛÜÃÞß"
- "àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
- "ŒœŠšŸŽž€";
-
-/*
- * Local Variables:
- * coding: utf-8
- * End:
- *
- */
diff --git a/generic/Color.c b/generic/Color.c
deleted file mode 100644
index 2165c99..0000000
--- a/generic/Color.c
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
- * Color.c -- Color management module.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Thu Dec 16 15:41:53 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * Most of this file is derived from Tk color code and thus
- * also copyrighted:
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
- *
- */
-
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "Types.h"
-#include "Image.h"
-#include "Color.h"
-#include "Geo.h"
-#include "Transfo.h"
-
-
-/*
- * Maximum size of a color name including the \0.
- */
-#define COLOR_NAME_SIZE 32
-
-/*
- * Maximum intensity for a color.
- */
-#define MAX_INTENSITY 65535
-
-/*
- * Hash table to map from a gradient's values (color, etc.) to a
- * gradient structure for those values.
- */
-static Tcl_HashTable gradient_table;
-
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ColorInit --
- *
- * Initialize the structure used for color management.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Read the code.
- *
- *----------------------------------------------------------------------
- */
-static void
-ColorInit()
-{
- initialized = 1;
- Tcl_InitHashTable(&gradient_table, TCL_STRING_KEYS);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnGetGradientColor
- * ZnInterpGradientColor --
- *
- *----------------------------------------------------------------------
- */
-XColor *
-ZnGetGradientColor(ZnGradient *grad,
- ZnReal position,
- unsigned short *alpha)
-{
- int index, min, max;
- XColor *shade=NULL;
-
- if ((grad->num_actual_colors == 1) || (position <= 0.0)) {
- if (alpha) {
- *alpha = grad->actual_colors[0].alpha;
- }
- return grad->actual_colors[0].rgb;
- }
- if (position >= 100.0) {
- if (alpha) {
- *alpha = grad->actual_colors[grad->num_actual_colors-1].alpha;
- }
- shade = grad->actual_colors[grad->num_actual_colors-1].rgb;
- }
- else {
- min = 0;
- max = grad->num_actual_colors-1;
- index = (max + min) / 2;
- while (max - min != 1) {
- /*printf("color index %d, min: %d, max: %d\n", index, min, max);*/
- if (grad->actual_colors[index].position < position) {
- min = index;
- }
- else {
- max = index;
- }
- index = (max + min) / 2;
- }
- shade = grad->actual_colors[index].rgb;
- if (alpha) {
- *alpha = grad->actual_colors[index].alpha;
- }
- }
-
- return shade;
-}
-
-void
-ZnInterpGradientColor(ZnGradient *grad,
- ZnReal position,
- XColor *color,
- unsigned short *alpha)
-{
- int index, min, max;
- ZnGradientColor *gc1, *gc2;
- ZnReal rel_pos;
-
- if ((grad->num_actual_colors == 1) || (position <= 0.0)) {
- *alpha = grad->actual_colors[0].alpha;
- *color = *grad->actual_colors[0].rgb;
- }
- else if (position >= 100.0) {
- *alpha = grad->actual_colors[grad->num_actual_colors-1].alpha;
- *color = *grad->actual_colors[grad->num_actual_colors-1].rgb;
- }
- else {
- min = 0;
- max = grad->num_actual_colors-1;
- index = (max + min) / 2;
- while (max - min != 1) {
- /*printf("color index %d, min: %d, max: %d\n", index, min, max);*/
- if (grad->actual_colors[index].position < position) {
- min = index;
- }
- else {
- max = index;
- }
- index = (max + min) / 2;
- }
- gc1 = &grad->actual_colors[index];
- gc2 = &grad->actual_colors[index+1];
- rel_pos = (position - gc1->position) * 100.0 / (gc2->position - gc1->position);
-
- if (rel_pos > gc1->control) {
- rel_pos = (rel_pos - gc1->control) * 100.0 / (100.0 - gc1->control);
- color->red = gc1->mid_rgb->red +
- (unsigned short) ((gc2->rgb->red - gc1->mid_rgb->red) * rel_pos / 100.0);
- color->green = gc1->mid_rgb->green +
- (unsigned short) ((gc2->rgb->green - gc1->mid_rgb->green) * rel_pos / 100.0);
- color->blue = gc1->mid_rgb->blue +
- (unsigned short) ((gc2->rgb->blue - gc1->mid_rgb->blue) * rel_pos / 100.0);
- *alpha = gc1->mid_alpha +
- (unsigned short) ((gc2->alpha - gc1->mid_alpha) * rel_pos / 100.0);
- }
- else {
- rel_pos = rel_pos * 100.0 / gc1->control;
- color->red = gc1->rgb->red +
- (unsigned short) ((gc1->mid_rgb->red - gc1->rgb->red) * rel_pos / 100.0);
- color->green = gc1->rgb->green +
- (unsigned short) ((gc1->mid_rgb->green - gc1->rgb->green) * rel_pos / 100.0);
- color->blue = gc1->rgb->blue +
- (unsigned short) ((gc1->mid_rgb->blue - gc1->rgb->blue) * rel_pos / 100.0);
- *alpha = gc1->alpha +
- (unsigned short) ((gc1->mid_alpha - gc1->alpha) * rel_pos / 100.0);
- }
- }
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnGradientFlat --
- *
- * Returns true if the gradient is defined by a single
- * color.
- *
- *--------------------------------------------------------------
- */
-ZnBool
-ZnGradientFlat(ZnGradient *grad)
-{
- return (grad->num_actual_colors == 1);
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnGetReliefGradient --
- *
- * Create a data structure containing a range of colors
- * used to display a 3D border. Name contains the base
- * color for the border. This is a slight variation on
- * the syntax of a gradient that make life easier in this
- * simple case.
- *
- * Results:
- * The return value is a token for a data structure
- * describing a gradient. This token may be passed
- * to the drawing routines.
- * If an error prevented the gradient from being created
- * then NULL is returned and an error message will be
- * left in interp.
- *
- * Side effects:
- * Data structures, etc. are allocated.
- * It is the caller's responsibility to eventually call
- * ZnFreeGradient to release the resources.
- *
- *--------------------------------------------------------------
- */
-ZnGradient *
-ZnGetReliefGradient(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_Uid name,
- unsigned short alpha)
-{
- XColor *base, light_color, dark_color, color;
- char color_name[COLOR_NAME_SIZE];
- char buffer[COLOR_NAME_SIZE*(3+2*ZN_RELIEF_STEPS)];
- int j, tmp1, tmp2;
- int red_range, green_range, blue_range;
-
- base = Tk_GetColor(interp, tkwin, name);
- /*
- * Compute the border gradient.
- *
- * Always consider that we are dealing with a color display with
- * enough colors available. If the colormap is full (stressed)
- * then just pray, the susbstitution algorithm may return something
- * adequate ;-).
- *
- * The extremum colors get computed using whichever formula results
- * in the greatest change in color:
- * 1. Lighter color is half-way to white, darker color is half
- * way to dark.
- * 2. Lighter color is 40% brighter than base, darker color
- * is 40% darker than base.
- * The first approach works better for unsaturated colors, the
- * second for saturated ones.
- *
- * NOTE: Colors are computed with integers not color shorts which
- * may lead to overflow errors.
- */
- tmp1 = (30 * (int) base->red)/100;
- tmp2 = ((int) base->red)/2;
- dark_color.red = MIN(tmp1, tmp2);
- tmp1 = (30 * (int) base->green)/100;
- tmp2 = ((int) base->green)/2;
- dark_color.green = MIN(tmp1, tmp2);
- tmp1 = (30 * (int) base->blue)/100;
- tmp2 = ((int) base->blue)/2;
- dark_color.blue = MIN(tmp1, tmp2);
-
- tmp1 = MAX_INTENSITY;/*(170 * (int) base->red)/10;*/
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
- }
- tmp2 = (MAX_INTENSITY + (int) base->red)/2;
- light_color.red = MAX(tmp1, tmp2);
- tmp1 = MAX_INTENSITY;/*(170 * (int) base->green)/10;*/
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
- }
- tmp2 = (MAX_INTENSITY + (int) base->green)/2;
- light_color.green = MAX(tmp1, tmp2);
- tmp1 = MAX_INTENSITY;/*(170 * (int) base->blue)/10;*/
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
- }
- tmp2 = (MAX_INTENSITY + (int) base->blue)/2;
- light_color.blue = MAX(tmp1, tmp2);
-
- buffer[0] = 0;
- sprintf(color_name, "#%02x%02x%02x;%d|",
- dark_color.red/256, dark_color.green/256, dark_color.blue/256, alpha);
- red_range = (int) base->red - (int) dark_color.red;
- green_range = (int) base->green - (int) dark_color.green;
- blue_range = (int) base->blue - (int) dark_color.blue;
- strcat(buffer, color_name);
- for (j = 1; j < ZN_RELIEF_STEPS; j++) {
- color.red =(int) dark_color.red + red_range * j/ZN_RELIEF_STEPS;
- color.green = (int) dark_color.green + green_range * j/ZN_RELIEF_STEPS;
- color.blue = (int) dark_color.blue + blue_range * j/ZN_RELIEF_STEPS;
- sprintf(color_name, "#%02x%02x%02x;%d %d|",
- color.red/256, color.green/256, color.blue/256, alpha, 50/ZN_RELIEF_STEPS*j);
- strcat(buffer, color_name);
- }
- sprintf(color_name, "#%02x%02x%02x;%d 50|",
- base->red/256, base->green/256, base->blue/256, alpha);
- strcat(buffer, color_name);
- red_range = (int) light_color.red - (int) base->red;
- green_range = (int) light_color.green - (int) base->green;
- blue_range = (int) light_color.blue - (int) base->blue;
- for (j = 1; j < ZN_RELIEF_STEPS; j++) {
- color.red = (int) base->red + red_range * j/ZN_RELIEF_STEPS;
- color.green = (int) base->green + green_range * j/ZN_RELIEF_STEPS;
- color.blue = (int) base->blue + blue_range * j/ZN_RELIEF_STEPS;
- sprintf(color_name, "#%02x%02x%02x;%d %d|",
- color.red/256, color.green/256, color.blue/256, alpha, 50+50/ZN_RELIEF_STEPS*j);
- strcat(buffer, color_name);
- }
- sprintf(color_name, "#%02x%02x%02x;%d",
- light_color.red/256, light_color.green/256, light_color.blue/256, alpha);
- strcat(buffer, color_name);
-
- /*printf("gradient relief: %s \n", buffer);*/
- return ZnGetGradient(interp, tkwin, buffer);
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnNameGradient
- * ZnDeleteGradientName --
- *
- * Save a gradient under a name or suppress the gradient
- * name binding. The save function returns false if the
- * name is already in use.
- *
- *--------------------------------------------------------------
- */
-ZnBool
-ZnNameGradient(Tcl_Interp *interp,
- Tk_Window tkwin,
- char *grad_descr,
- char *name)
-{
- Tcl_HashEntry *hash;
- int new;
- ZnGradient *grad;
- XColor color;
-
- /*
- * First try to find if the name interfere with a color name,
- * this must be avoided. Gradients may be described by a single
- * color name and gradient descriptions / names share the same
- * name space.
- */
- if (XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, &color)) {
- Tcl_AppendResult(interp, "gradient name \"", name,
- "\", is a color name", NULL);
- return False;
- }
- grad = ZnGetGradient(interp, tkwin, grad_descr);
- if (!grad) {
- Tcl_AppendResult(interp, "gradient specification \"", grad_descr,
- "\", is invalid", NULL);
- return False;
- }
- hash = Tcl_CreateHashEntry(&gradient_table, Tk_GetUid(name), &new);
- if (!new) {
- ZnFreeGradient(grad);
- Tcl_AppendResult(interp, "gradient name \"", name,
- "\", is already in use", NULL);
- return False;
- }
- else {
- Tcl_SetHashValue(hash, grad);
- }
-
- return True;
-}
-
-ZnBool
-ZnGradientNameExists(char *name)
-{
- if (!initialized) {
- return False;
- }
- return Tcl_FindHashEntry(&gradient_table, Tk_GetUid(name)) != NULL;
-}
-
-void
-ZnDeleteGradientName(char *name)
-{
- Tcl_HashEntry *hash;
-
- if (!initialized) {
- return;
- }
-
- hash = Tcl_FindHashEntry(&gradient_table, Tk_GetUid(name));
- if (hash) {
- Tcl_DeleteHashEntry(hash);
- ZnFreeGradient((ZnGradient *) Tcl_GetHashValue(hash));
- }
-}
-
-static void
-InterpolateGradientColor(Tk_Window tkwin,
- ZnGradientColor *gc1, /* First color */
- ZnGradientColor *gc2, /* Next color */
- ZnGradientColor *gc_interp,/* New interpolated color */
- ZnGradientColor *gc_adjust,/* Adjusted first color.
- * Needed if interested in
- * the range color1 interp
- * color. */
- int interp_pos,
- int min_pos,
- int span)
-{
- ZnReal pos1, pos2, ipos, interp_rel_pos, tmp;
- XColor rgb;
-
- //printf("interp_pos: %d, min_pos: %d, span: %d\n ", interp_pos, min_pos, span);
- pos1 = ((ZnReal)gc1->position-(ZnReal)min_pos)/(ZnReal)span;
- pos2 = ((ZnReal)gc2->position-(ZnReal)min_pos)/(ZnReal)span;
- ipos = ((ZnReal)interp_pos-(ZnReal)min_pos)/(ZnReal)span;
- interp_rel_pos = (ipos-pos1)*100/(pos2-pos1);
-
- //printf("pos1: %g, pos2: %g, interp_rel_pos: %g\n", pos1, pos2, interp_rel_pos);
- if (interp_rel_pos < gc1->control) {
- tmp = interp_rel_pos * 100.0 / gc1->control;
- //printf("rgb : %d, mid rgb : %d\n\n", gc1->rgb, gc1->mid_rgb);
- rgb.red = (unsigned short) (gc1->rgb->red + (gc1->mid_rgb->red - gc1->rgb->red) * tmp / 100.0);
- rgb.green = (unsigned short) (gc1->rgb->green + (gc1->mid_rgb->green - gc1->rgb->green) * tmp / 100.0);
- rgb.blue = (unsigned short) (gc1->rgb->blue + (gc1->mid_rgb->blue - gc1->rgb->blue) * tmp / 100.0);
- gc_interp->alpha = (unsigned char) (gc1->alpha + (gc1->mid_alpha - gc1->alpha) * tmp / 100.0);
- }
- else if (interp_rel_pos > gc1->control) {
- tmp = (interp_rel_pos - gc1->control) * 100.0 / (100.0 - gc1->control);
- rgb.red = (unsigned short) (gc1->mid_rgb->red + (gc2->rgb->red - gc1->mid_rgb->red)*tmp / 100.0);
- rgb.green = (unsigned short) (gc1->mid_rgb->green + (gc2->rgb->green - gc1->mid_rgb->green)*tmp / 100.0);
- rgb.blue = (unsigned short) (gc1->mid_rgb->blue + (gc2->rgb->blue - gc1->mid_rgb->blue)*tmp / 100.0);
- gc_interp->alpha = (unsigned char) (gc1->mid_alpha + (gc2->alpha - gc1->mid_alpha)*tmp / 100.0);
- }
- else {
- rgb = *gc1->mid_rgb;
- gc_interp->alpha = gc1->mid_alpha;
- }
- gc_interp->rgb = Tk_GetColorByValue(tkwin, &rgb);
-
- if (!gc_adjust) {
- /*
- * Interested in the segment from the interpolated color
- * to color 2.
- */
- gc_interp->position = 0;
- if (interp_rel_pos < gc1->control) {
- gc_interp->control = gc1->control - (int) interp_rel_pos;
- gc_interp->mid_rgb = Tk_GetColorByValue(tkwin, gc1->mid_rgb);
- gc_interp->mid_alpha = gc1->mid_alpha;
- }
- else {
- rgb.red = gc_interp->rgb->red+(gc2->rgb->red-gc_interp->rgb->red)/2;
- rgb.green = gc_interp->rgb->green+(gc2->rgb->green-gc_interp->rgb->green)/2;
- rgb.blue = gc_interp->rgb->blue+(gc2->rgb->blue-gc_interp->rgb->blue)/2;
- gc_interp->mid_rgb = Tk_GetColorByValue(tkwin, &rgb);
- gc_interp->mid_alpha = gc_interp->alpha + (gc2->alpha - gc_interp->alpha)/2;
- gc_interp->control = 50;
- }
- }
- else {
- /*
- * Interested in the segment from color 1 (color adjusted) to
- * the interpolated color.
- */
- gc_interp->position = 100;
- gc_interp->mid_rgb = NULL;
- gc_interp->mid_alpha = 100;
- if (interp_rel_pos <= gc1->control) {
- rgb.red = gc1->rgb->red+(gc_interp->rgb->red-gc1->rgb->red)/2;
- rgb.green = gc1->rgb->green+(gc_interp->rgb->green-gc1->rgb->green)/2;
- rgb.blue = gc1->rgb->blue+(gc_interp->rgb->blue-gc1->rgb->blue)/2;
- Tk_FreeColor(gc_adjust->mid_rgb);
- gc_adjust->mid_rgb = Tk_GetColorByValue(tkwin, &rgb);
- gc_adjust->mid_alpha = gc1->alpha + (gc_interp->alpha - gc1->alpha)/2;
- gc_adjust->control = 50;
- }
- }
- //printf("out of InterpolateGradientColor\n");
-}
-
-
-static void
-ReduceGradient(Tk_Window tkwin,
- ZnGradient *grad)
-{
- ZnReal dx, dy, len, angle;
- ZnTransfo t;
- ZnPoint pbbox[4], pgrad[4];
- ZnReal maxx, minx, span, start_in_new, end_in_new;
- int minx100, maxx100, span100;
- int i, j, first_color, last_color;
- ZnBool interpolate_first, interpolate_last;
-
- //printf("In ReduceGradient\n");
- dx = grad->e.x - grad->p.x;
- dy = grad->e.y - grad->p.y;
- len = sqrt(dx*dx+dy*dy);
- angle = acos(dx/len);
- if (dy < 0) {
- angle = 2*M_PI - angle;
- }
- grad->angle = (int) -ZnRadDeg(angle);
-
- if (grad->type == ZN_CONICAL_GRADIENT) {
- unchanged:
- grad->actual_colors = grad->colors_in;
- grad->num_actual_colors = grad->num_colors_in;
- return;
- }
-
- ZnTransfoSetIdentity(&t);
- ZnTranslate(&t, -grad->p.x, -grad->p.y, False);
- ZnRotateRad(&t, -angle);
- ZnScale(&t, 1/len, 1/len);
- pbbox[0].x = -50;
- pbbox[0].y = 50;
- pbbox[1].x = 50;
- pbbox[1].y = 50;
- pbbox[2].x = 50;
- pbbox[2].y = -50;
- pbbox[3].x = -50;
- pbbox[3].y = -50;
- ZnTransformPoints(&t, pbbox, pgrad, 4);
- maxx = minx = pgrad[0].x;
- for (i = 1; i < 4; i++) {
- if (pgrad[i].x > maxx) {
- maxx = pgrad[i].x;
- }
- if (pgrad[i].x < minx) {
- minx = pgrad[i].x;
- }
- }
-
- span = maxx-minx;
- if (grad->type == ZN_RADIAL_GRADIENT) {
- start_in_new = 0;
- end_in_new = 100/span;
- }
- else {
- start_in_new = -minx*100/span;
- end_in_new = (1-minx)*100/span;
- }
-
- //printf("minx: %g, maxx: %g, start%%: %g, end%%: %g\n",
- // minx, maxx, start_in_new, end_in_new);
-
- /*
- * Gradient is unchanged
- */
- if ((ABS(start_in_new) < PRECISION_LIMIT) &&
- (ABS(end_in_new-100.0) < PRECISION_LIMIT)) {
- goto unchanged;
- }
- //printf("start_in_new: %g, end_in_new: %g\n", start_in_new, end_in_new);
- if ((start_in_new > 100.0) || (end_in_new < 0.0)) {
- grad->num_actual_colors = 1;
- grad->actual_colors = ZnMalloc(sizeof(ZnGradientColor));
- grad->actual_colors[0].position = 0;
- grad->actual_colors[0].mid_rgb = NULL;
- if (end_in_new < 0.0) {
- grad->actual_colors[0].alpha = grad->colors_in[grad->num_colors_in-1].alpha;
- grad->actual_colors[0].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[grad->num_colors_in-1].rgb);
- }
- else {
- grad->actual_colors[0].alpha = grad->colors_in[0].alpha;
- grad->actual_colors[0].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].rgb);
- }
- return;
- }
-
- grad->num_actual_colors = grad->num_colors_in;
- interpolate_first = False;
- minx100 = (int) (minx*100);
- maxx100 = (int) (maxx*100);
- span100 = (int) (span*100);
-
- if (start_in_new < 0.0) {
- /*
- * The gradient starts outside the bbox,
- * Find the color at the bbox edge. First
- * find the correct gradient segment and then
- * interpolate to get the color.
- */
- first_color = 1;
- while ((first_color < (int) grad->num_colors_in) &&
- (grad->colors_in[first_color].position < minx100)) {
- first_color++;
- grad->num_actual_colors--;
- }
- if (grad->colors_in[first_color].position == minx100) {
- grad->num_actual_colors--;
- }
- else {
- interpolate_first = True;
- /*printf("interpolate first color\n");*/
- }
- }
- else {
- first_color = 0;
- if (grad->type != ZN_RADIAL_GRADIENT) {
- grad->num_actual_colors++;
- }
- }
- interpolate_last = False;
- if (end_in_new > 100.0) {
- /*
- * The gradient ends outside the bbox,
- * Find the color at the bbox edge. First
- * find the correct gradient segment and then
- * interpolate to get the color.
- */
- last_color = grad->num_colors_in-2;
- while ((last_color >= 0) &&
- (grad->colors_in[last_color].position > maxx100)) {
- last_color--;
- grad->num_actual_colors--;
- }
- if (grad->colors_in[last_color].position == maxx100) {
- grad->num_actual_colors--;
- }
- else {
- interpolate_last = True;
- /*printf("interpolate last color\n");*/
- }
- }
- else {
- last_color = grad->num_colors_in-1;
- grad->num_actual_colors++;
- }
-
- grad->actual_colors = ZnMalloc(grad->num_actual_colors*sizeof(ZnGradientColor));
- j = 0;
- if (interpolate_first) {
- //printf("Interpolate first color, index: %d\n", first_color);
- InterpolateGradientColor(tkwin,
- &grad->colors_in[first_color-1],
- &grad->colors_in[first_color],
- &grad->actual_colors[j],
- NULL,
- minx100, minx100, span100);
- j++;
- }
- else if ((first_color == 0) && (grad->type != ZN_RADIAL_GRADIENT)) {
- grad->actual_colors[j] = grad->colors_in[0];
- grad->actual_colors[j].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].rgb);
- if (grad->colors_in[0].mid_rgb) {
- grad->actual_colors[j].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].mid_rgb);
- }
- grad->actual_colors[0].position = 0;
- grad->actual_colors[0].control = 50;
- j++;
- /*printf("adding a color at start\n");*/
- }
-
- /*printf("first color: %d, last color: %d, num colors: %d\n",
- first_color, last_color, grad->num_actual_colors);*/
- for (i = first_color; i <= last_color; i++, j++) {
- grad->actual_colors[j] = grad->colors_in[i];
- grad->actual_colors[j].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].rgb);
- if (grad->colors_in[i].mid_rgb) {
- grad->actual_colors[j].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].mid_rgb);
- }
- grad->actual_colors[j].position = (grad->colors_in[i].position-minx100)*100/span100;
- grad->actual_colors[j].control = grad->colors_in[i].control;
- /*printf("i: %d, j: %d, minx: %d, span: %d, position av: %d position ap: %d\n",
- i, j, minx100, span100, grad->colors_in[i].position, grad->actual_colors[j].position);*/
- }
-
- if (interpolate_last) {
- //printf("Interpolate last color\n");
- InterpolateGradientColor(tkwin,
- &grad->colors_in[last_color],
- &grad->colors_in[last_color+1],
- &grad->actual_colors[j],
- &grad->actual_colors[j-1],
- maxx100, minx100, span100);
- }
- else if (last_color == ((int) grad->num_colors_in)-1) {
- i = grad->num_colors_in-1;
- grad->actual_colors[j] = grad->colors_in[i];
- grad->actual_colors[j].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].rgb);
- if (grad->colors_in[i].mid_rgb) {
- grad->actual_colors[j].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].mid_rgb);
- }
- /*printf("adding a color at end\n");*/
- }
- grad->actual_colors[j].position = 100;
- //for (i=0; i<grad->num_actual_colors; i++) printf("control %d: %d\n", i, grad->actual_colors[i].control);
- //printf("Out of ReduceGradient\n");
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnGetGradient --
- *
- * Create a data structure containing a range of colors
- * used to display a gradient.
- *
- * The gradient should have the following syntax:
- *
- * gradient := [graddesc|]color[|....|color]
- * where the | are real characters not meta-syntax.
- *
- * graddesc := =type args
- * where type := axial | radial | path
- *
- * If type = axial
- * args := angle (0..360) | xs ys xe ye (reals)
- *
- * The first form define the axial gradiant by its slope.
- * With this syntax the gradient fits the whole shape.
- * This is a backward compatible syntax.
- * The second form specifies a vector which will be used
- * to draw the gradient. The vector defines both the angle
- * and the gradient area. Parts of the shape that lie before
- * the vector origin are filled with the first color and
- * parts that lie after the vector end are filled with the
- * last color.
- *
- * If type = radial or path
- * args := xs ys [xe ye] (reals)
- *
- * The vector specified by the 4 coordinates defines the
- * gradient area. Parts of the shape that lie before
- * the vector origin are filled with the first color and
- * parts that lie after the vector end are filled with the
- * last color. The vector end may be omitted, in such case
- * the gradient fits exactly the whole shape to be filled,
- * this is backward compatible with older gradients.
- *
- * color := colorvalue | colorvalue position |
- * colorvalue control position
- * where position and control are in (0..100)
- *
- * colorvalue := (colorname | #rgb | cievalue)[;alpha]
- * where alpha is in (0..100)
- *
- * Results:
- * The return value is a token for a data structure
- * describing a gradient. This token may be passed
- * to the drawing routines.
- * If an error prevented the gradient from being created
- * then NULL is returned and an error message will be
- * left in interp.
- *
- * Side effects:
- * Data structures, etc. are allocated.
- * It is the caller's responsibility to eventually call
- * ZnFreeGradient to release the resources.
- *
- *--------------------------------------------------------------
- */
-ZnGradient *
-ZnGetGradientByValue(ZnGradient *grad)
-{
- grad->ref_count++;
- return grad;
-}
-
-
-static int
-ParseRealList(const char *str,
- const char *stop,
- ZnReal *list,
- int max)
-{
- int num;
- char *end;
-
- num = 0;
- while ((num < max) && (str != stop)) {
- list[num] = strtod(str, &end);
- if (end == str) {
- /* A syntax error occured, return a 0 count
- * as a hint for the caller.
- */
- return 0;
- }
- num++;
- str = end+strspn(end, " \t");
- }
- return num;
-}
-
-ZnGradient *
-ZnGetGradient(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_Uid desc)
-{
- #define SEGMENT_SIZE 64
- Tcl_HashEntry *hash;
- ZnGradient *grad;
- unsigned int i, j, nspace, num_colors;
- unsigned int size, num_coords=0;
- char type;
- char const *scan_ptr, *next_ptr, *str_ptr;
- ZnReal angle, position, control;
- ZnReal coords[4];
- char *color_ptr, *end, segment[SEGMENT_SIZE];
- ZnGradientColor *first, *last;
- XColor color;
- int new, red_range, green_range, blue_range;
- ZnBool simple;
-
- //printf("ZnGetGradient : %s\n", desc);
- if (!desc || !*desc) {
- return NULL;
- }
- if (!initialized) {
- ColorInit();
- }
-
- /*
- * First, check to see if there's already a gradient that will work
- * for this request.
- */
- desc = Tk_GetUid(desc);
-
- /*printf("get gradient: %s\n", desc);*/
- hash = Tcl_CreateHashEntry(&gradient_table, desc, &new);
- if (!new) {
- grad = (ZnGradient *) Tcl_GetHashValue(hash);
- grad->ref_count++;
- return grad;
- }
-
- /*
- * No satisfactory gradient exists yet. Initialize a new one.
- */
- type = ZN_AXIAL_GRADIENT;
- angle = 0.0;
- /*
- * Skip the trailing spaces.
- */
- while (*desc == ' ') {
- desc++;
- }
- /*
- * Count the sections in the description. It should give
- * the number of colors plus may be the gradient description.
- */
- scan_ptr = desc;
- /*
- * If the first section is the gradient description, start color
- * counts up from zero.
- */
- num_colors = (*scan_ptr == '=') ? 0 : 1;
- while ((scan_ptr = strchr(scan_ptr, '|'))) {
- num_colors++;
- scan_ptr++;
- }
- if (num_colors == 0) {
- Tcl_AppendResult(interp, "gradient should have at least one color \"",
- desc, "\",", NULL);
- grad_err1:
- Tcl_DeleteHashEntry(hash);
- /*printf("ZnGetGradient error : %s\n", desc);*/
- return NULL;
- }
- /*
- * Then look at the gradient type.
- */
- scan_ptr = desc;
- /*
- * next_ptr can't be NULL in the following code,
- * we checked that at least one color was specified
- * after the gradient description.
- */
- next_ptr = strchr(scan_ptr, '|');
- if (*scan_ptr == '=') {
- scan_ptr++;
- if ((*scan_ptr == 'a') && (strncmp(scan_ptr, "axial", 5) == 0)) {
- scan_ptr += 5;
- num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
- if ((num_coords != 1) && (num_coords != 4)) {
- grad_err3:
- Tcl_AppendResult(interp, "invalid gradient parameter \"",
- desc, "\",", NULL);
- goto grad_err1;
- }
- angle = (int) coords[0];
- }
- else if ((*scan_ptr == 'c') && (strncmp(scan_ptr, "conical", 7) == 0)) {
- scan_ptr += 7;
- type = ZN_CONICAL_GRADIENT;
- num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
- if ((num_coords < 1) && (num_coords > 4)) {
- goto grad_err3;
- }
- angle = (int) coords[0];
- }
- else if (((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) ||
- ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0))) {
- if (*scan_ptr == 'r') {
- type = ZN_RADIAL_GRADIENT;
- scan_ptr += 6;
- }
- else {
- type = ZN_PATH_GRADIENT;
- scan_ptr += 4;
- }
- num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
- if ((num_coords != 2) && (num_coords != 4)) {
- goto grad_err3;
- }
- }
- else {
- Tcl_AppendResult(interp, "invalid gradient type \"",
- desc, "\"", NULL);
- goto grad_err1;
- }
- scan_ptr = next_ptr + 1;
- next_ptr = strchr(scan_ptr, '|');
- }
-
- /*
- * Create the gradient structure.
- */
- grad = (ZnGradient *) ZnMalloc(sizeof(ZnGradient) +
- sizeof(ZnGradientColor)*(num_colors-1));
- grad->ref_count = 1;
- simple = True;
- grad->num_colors_in = num_colors;
- grad->type = type;
- grad->p.x = grad->p.y = grad->e.x = grad->e.y = 0.0;
- grad->angle = 0;
-
- switch (type) {
- case ZN_AXIAL_GRADIENT:
- if ((num_coords == 4) &&
- ((coords[0] != coords[2]) || (coords[1] != coords[3]))) {
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- simple = False;
- grad->e.x = coords[2];
- grad->e.y = coords[3];
- }
- else {
- grad->angle = (int) angle;
- }
- break;
- case ZN_CONICAL_GRADIENT:
- if ((num_coords == 4) &&
- ((coords[0] != coords[2]) || (coords[1] != coords[3]))) {
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- simple = False;
- grad->e.x = coords[2];
- grad->e.y = coords[3];
- }
- else if (num_coords == 2) {
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- }
- else if (num_coords == 3) {
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- grad->angle = (int) coords[2];
- }
- else {
- grad->angle = (int) angle;
- }
- break;
- case ZN_RADIAL_GRADIENT:
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- if ((num_coords == 4) &&
- ((coords[0] != coords[2]) || (coords[1] != coords[3]))) {
- simple = False;
- grad->e.x = coords[2];
- grad->e.y = coords[3];
- }
- break;
- case ZN_PATH_GRADIENT:
- grad->p.x = coords[0];
- grad->p.y = coords[1];
- break;
- }
- grad->hash = hash;
- Tcl_SetHashValue(hash, grad);
-
- for (i = 0; i < num_colors; i++) {
- grad->colors_in[i].alpha = 100;
- /*
- * Try to parse the color name.
- */
- nspace = strspn(scan_ptr, " \t");
- scan_ptr += nspace;
- str_ptr = strpbrk(scan_ptr, " \t|");
- if (str_ptr) {
- size = str_ptr - scan_ptr;
- }
- else {
- size = strlen(scan_ptr);
- }
- if (size > (SEGMENT_SIZE-1)) {
- Tcl_AppendResult(interp, "color name too long in gradient \"",
- desc, "\",", NULL);
- grad_err2:
- for (j = 0; j < i; j++) {
- Tk_FreeColor(grad->colors_in[j].rgb);
- }
- ZnFree(grad);
- goto grad_err1;
- }
- strncpy(segment, scan_ptr, size);
- segment[size] = 0;
- scan_ptr += size;
- /*
- * Try to parse the color position.
- */
- grad->colors_in[i].position = 0;
- grad->colors_in[i].control = 50;
- position = strtod(scan_ptr, &end);
- if (end != scan_ptr) {
- grad->colors_in[i].position = (int) position;
- scan_ptr = end;
- /*
- * Try to parse the control point
- */
- control = strtod(scan_ptr, &end);
- if (end != scan_ptr) {
- grad->colors_in[i].control = (int) control;
- scan_ptr = end;
- }
- }
- nspace = strspn(scan_ptr, " \t");
- if ((scan_ptr[nspace] != 0) && (scan_ptr+nspace != next_ptr)) {
- Tcl_AppendResult(interp, "incorrect color description in gradient \"",
- desc, "\",", NULL);
- goto grad_err2;
- }
-
- color_ptr = strchr(segment, ';');
- if (color_ptr) {
- *color_ptr = 0;
- }
- grad->colors_in[i].rgb = Tk_GetColor(interp, tkwin, Tk_GetUid(segment));
- if (grad->colors_in[i].rgb == NULL) {
- Tcl_AppendResult(interp, "incorrect color value in gradient \"",
- desc, "\",", NULL);
- goto grad_err2;
- }
- if (color_ptr) {
- color_ptr++;
- grad->colors_in[i].alpha = atoi(color_ptr);
- }
- if (i == 0) {
- grad->colors_in[i].position = 0;
- }
- else if (i == num_colors - 1) {
- grad->colors_in[i].position = 100;
- }
- if ((i > 0) &&
- ((grad->colors_in[i].position > 100) ||
- (grad->colors_in[i].position < grad->colors_in[i-1].position))) {
- Tcl_AppendResult(interp, "incorrect color position in gradient \"",
- desc, "\",", NULL);
- goto grad_err2;
- }
- if (grad->colors_in[i].control > 100) {
- grad->colors_in[i].control = 100;
- }
- if (grad->colors_in[i].alpha > 100) {
- grad->colors_in[i].alpha = 100;
- }
- if (next_ptr) {
- scan_ptr = next_ptr + 1;
- next_ptr = strchr(scan_ptr, '|');
- }
- }
-
- /*
- * Compute the mid alpha and mid color values. These will be
- * used by the gradient rendering primitives when a control
- * is not at mid range. The last color has no mid_* values.
- */
- for (i = 0; i < grad->num_colors_in-1; i++) {
- first = &grad->colors_in[i];
- last = &grad->colors_in[i+1];
- red_range = (int) last->rgb->red - (int) first->rgb->red;
- green_range = (int) last->rgb->green - (int) first->rgb->green;
- blue_range = (int) last->rgb->blue - (int) first->rgb->blue;
- color.red =(int) first->rgb->red + red_range/2;
- color.green = (int) first->rgb->green + green_range/2;
- color.blue = (int) first->rgb->blue + blue_range/2;
- first->mid_rgb = Tk_GetColorByValue(tkwin, &color);
- first->mid_alpha = first->alpha + (last->alpha-first->alpha)/2;
- }
- grad->colors_in[grad->num_colors_in-1].mid_rgb = NULL;
-
- /*
- * If the gradient is 'simple' ie. described by a single point
- * or an angle for axial gradients, the processing is finished.
- * If not, we have to reduce the gradient to a simple one by adding
- * or suppressing colors and adjusting the relative position of
- * each remaining color.
- */
- if (simple) {
- grad->num_actual_colors = grad->num_colors_in;
- grad->actual_colors = grad->colors_in;
- }
- else if (type != ZN_PATH_GRADIENT) {
- ReduceGradient(tkwin, grad);
- }
-
- //printf("num in: %d, num actual: %d\n", grad->num_colors_in,grad->num_actual_colors);
- //printf("ZnGetGradient end : %s\n", desc);
- return grad;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnNameOfGradient --
- *
- * Given a gradient, return a textual string identifying
- * the gradient.
- *
- * Results:
- * The return value is the string that was used to create
- * the gradient.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-char *
-ZnNameOfGradient(ZnGradient *grad)
-{
- return (char *) grad->hash->key.words;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnFreeGradient --
- *
- * This procedure is called when a gradient is no longer
- * needed. It frees the resources associated with the
- * gradient. After this call, the caller should never
- * again use the gradient.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Resources are freed.
- *
- *--------------------------------------------------------------
- */
-void
-ZnFreeGradient(ZnGradient *grad)
-{
- unsigned int i;
-
- grad->ref_count--;
- if (grad->ref_count == 0) {
- Tcl_DeleteHashEntry(grad->hash);
- for (i = 0; i < grad->num_colors_in; i++) {
- Tk_FreeColor(grad->colors_in[i].rgb);
- if (grad->colors_in[i].mid_rgb) {
- Tk_FreeColor(grad->colors_in[i].mid_rgb);
- }
- }
- if (grad->actual_colors != grad->colors_in) {
- for (i = 0; i < grad->num_actual_colors; i++) {
- Tk_FreeColor(grad->actual_colors[i].rgb);
- if (grad->actual_colors[i].mid_rgb) {
- Tk_FreeColor(grad->actual_colors[i].mid_rgb);
- }
- }
- ZnFree(grad->actual_colors);
- }
- ZnFree(grad);
- }
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnComposeAlpha --
- *
- * This procedure takes two alpha values in percent and
- * returns the composite value between 0 and 65535.
- *
- *--------------------------------------------------------------
- */
-int
-ZnComposeAlpha(unsigned short alpha1,
- unsigned short alpha2)
-{
- return (alpha1*alpha2/100)*65535/100;
-}
diff --git a/generic/Color.h b/generic/Color.h
deleted file mode 100644
index b8952ca..0000000
--- a/generic/Color.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Color.h -- Header for color routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Thu Dec 16 15:41:04 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Color_h
-#define _Color_h
-
-
-#include "Types.h"
-#include "Geo.h"
-
-
-/*
- * Types of gradients.
- */
-#define ZN_AXIAL_GRADIENT 0
-#define ZN_RADIAL_GRADIENT 1
-#define ZN_PATH_GRADIENT 2
-#define ZN_CONICAL_GRADIENT 3
-
-typedef struct _ZnGradientColor {
- unsigned char position; /* Color starting position along the gradient axis.
- * This is in percent of the gradient total size. */
- unsigned char control; /* Middle-shade position in percent of this color
- * size along the gradient axis. */
- unsigned char alpha; /* The color alpha channel in percent */
- unsigned char mid_alpha;
- XColor *rgb; /* The actual color description */
- XColor *mid_rgb;
-} ZnGradientColor;
-
-typedef struct _ZnGradient {
- int ref_count;
- Tcl_HashEntry *hash;
- char type; /* Either ZN_AXIAL_GRADIENT, ZN_RADIAL_GRADIENT or
- * ZN_PATH_GRADIENT. */
- int angle; /* Angle for an axial gradient (Degrees). */
- ZnPoint p; /* Start for an axial/radial/path gradiant. In
- * percent of the bbox. */
- ZnPoint e; /* End of the axial/radial gradiant in percent
- * of bbox. */
- unsigned int num_actual_colors;/* Number of adjusted colors */
- ZnGradientColor *actual_colors;/* Actual adjusted gradient color spec. May
- * be the same array as color_spec. */
- unsigned int num_colors_in; /* Number of colors in gradient spec. */
- ZnGradientColor colors_in[1]; /* Gradient color spec */
-} ZnGradient;
-
-
-#define ZnGetGradientPixel(gradient, position) \
- ZnPixel(ZnGetGradientColor(gradient, position, NULL))
-
-ZnGradient *ZnGetGradient(Tcl_Interp *interp, Tk_Window tkwin,
- Tk_Uid name);
-ZnGradient *ZnGetGradientByValue(ZnGradient *gradient);
-ZnGradient *ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin,
- Tk_Uid name, unsigned short alpha);
-ZnBool ZnGradientFlat(ZnGradient *grad);
-XColor *ZnGetGradientColor(ZnGradient *gradient, ZnReal position,
- unsigned short *alpha);
-void ZnInterpGradientColor(ZnGradient *gradient, ZnReal position,
- XColor *color, unsigned short *alpha);
-char *ZnNameOfGradient(ZnGradient *gradient);
-void ZnFreeGradient(ZnGradient *gradient);
-void ZnDeleteGradientName(char *name);
-ZnBool ZnGradientNameExists(char *name);
-ZnBool ZnNameGradient(Tcl_Interp *interp, Tk_Window tkwin,
- char *grad_descr, char *name);
-int ZnComposeAlpha(unsigned short alpha1, unsigned short alpha2);
-
-#endif /* _Color_h */
diff --git a/generic/Curve.c b/generic/Curve.c
deleted file mode 100644
index c73d467..0000000
--- a/generic/Curve.c
+++ /dev/null
@@ -1,2260 +0,0 @@
-/*
- * Curve.c -- Implementation of curve item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Fri Mar 25 15:32:17 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-#include "Draw.h"
-#include "Item.h"
-#include "Geo.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Image.h"
-#include "Color.h"
-#include "tkZinc.h"
-
-#include <GL/glu.h>
-#include <ctype.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 CLOSED_BIT 1<<2 /* If the outline should be closed automatically */
-#define SMOOTH_RELIEF_BIT 1<<3 /* If the relief should be continuous (arc) or discrete (angle) */
-
-#define FIRST_END_OK 1<<6
-#define LAST_END_OK 1<<7
-#define FILLED_OK 1<<8
-#define RELIEF_OK 1<<10
-#define MARKER_OK 1<<12
-
-
-/*
- **********************************************************************************
- *
- * Specific Curve item record
- *
- **********************************************************************************
- */
-typedef struct _CurveItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoly shape;
- unsigned short flags;
- ZnImage marker;
- ZnLineEnd first_end; /* These two are considered only if relief is flat */
- ZnLineEnd last_end;
- ZnLineStyle line_style; /* This is considered only if relief is flat */
- int cap_style;
- int join_style;
- ZnReliefStyle relief;
- ZnDim line_width; /* If 0 the path is not drawn, if <2 relief is flat */
- ZnGradient *fill_color;
- ZnImage line_pattern;
- ZnGradient *line_color;
- ZnGradient *marker_color;
- int fill_rule;
- ZnImage tile;
-
- /* Private data */
- ZnPoly outlines;
- ZnGradient *gradient;
- ZnTriStrip tristrip;
- ZnPoint *grad_geo;
-} CurveItemStruct, *CurveItem;
-
-static ZnAttrConfig cv_attrs[] = {
- { ZN_CONFIG_CAP_STYLE, "-capstyle", NULL,
- Tk_Offset(CurveItemStruct, cap_style), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-closed", NULL,
- Tk_Offset(CurveItemStruct, flags), CLOSED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
- Tk_Offset(CurveItemStruct, fill_color), 0,
- ZN_COORDS_FLAG|ZN_BORDER_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(CurveItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(CurveItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_FILL_RULE, "-fillrule", NULL,
- Tk_Offset(CurveItemStruct, fill_rule), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-firstend", NULL,
- Tk_Offset(CurveItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_JOIN_STYLE, "-joinstyle", NULL,
- Tk_Offset(CurveItemStruct, join_style), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-lastend", NULL,
- Tk_Offset(CurveItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
- Tk_Offset(CurveItemStruct, line_color), 0,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BITMAP, "-linepattern", NULL,
- Tk_Offset(CurveItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
- Tk_Offset(CurveItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-linewidth", NULL,
- Tk_Offset(CurveItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(CurveItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BITMAP, "-marker", NULL,
- Tk_Offset(CurveItemStruct, marker), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
- Tk_Offset(CurveItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(CurveItemStruct, relief), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(CurveItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-smoothrelief", NULL,
- Tk_Offset(CurveItemStruct, flags), SMOOTH_RELIEF_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(CurveItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_IMAGE, "-tile", NULL,
- Tk_Offset(CurveItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(CurveItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- unsigned int i, num_points, count;
- ZnPoint *p, *points;
- char *controls;
-
- cv->outlines.num_contours = 0;
- cv->outlines.contours = NULL;
- cv->tristrip.num_strips = 0;
- cv->tristrip.strips = NULL;
- cv->gradient = NULL;
- cv->grad_geo = NULL;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- CLEAR(cv->flags, CLOSED_BIT);
- CLEAR(cv->flags, SMOOTH_RELIEF_BIT);
- cv->fill_rule = GLU_TESS_WINDING_ODD;
- item->priority = 1;
-
- if (*argc < 1) {
- Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
- return TCL_ERROR;
- }
- if (ZnParseCoordList(wi, (*args)[0], &points,
- &controls, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- if (num_points == 0) {
- ZnPolyInit(&cv->shape);
- }
- else {
- /*
- * Scan the control array (if any) to detect malformed
- * curves (more than 2 consecutive control points).
- */
- if (controls) {
- count = 0;
- if ((controls[0]) || (controls[num_points-1])) {
- goto contr_err;
- }
- for (i = 1; i < num_points-1; i++) {
- switch (controls[i]) {
- case 'c':
- count++;
- if (count > 2) {
- goto contr_err;
- }
- break;
- case 0:
- count = 0;
- break;
- default:
- contr_err:
- ZnFree(controls);
- Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
- return TCL_ERROR;
- }
- }
- }
- /*
- * Make a local copy of the points. This is not necessary
- * for the optional control list.
- */
- p = ZnMalloc(num_points * sizeof(ZnPoint));
- /*printf("plain contour, numpoints: %d %g@%g\n",
- num_points, points[0].x, points[0].y);*/
- memcpy(p, points, num_points * sizeof(ZnPoint));
- ZnPolyContour1(&cv->shape, p, num_points, !ZnTestCCW(p, num_points));
- cv->shape.contours[0].controls = controls;
- }
- (*args)++;
- (*argc)--;
-
- CLEAR(cv->flags, FILLED_BIT);
- cv->first_end = NULL;
- cv->last_end = NULL;
- cv->line_style = ZN_LINE_SIMPLE;
- cv->relief = ZN_RELIEF_FLAT;
- cv->line_width = 1;
- cv->tile = ZnUnspecifiedImage;
- cv->line_pattern = ZnUnspecifiedImage;
- 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 = ZnUnspecifiedImage;
- cv->fill_color = ZnGetGradientByValue(wi->fore_color);
- cv->line_color = ZnGetGradientByValue(wi->fore_color);
- cv->marker_color = ZnGetGradientByValue(wi->fore_color);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- CurveItem cv = (CurveItem) item;
- unsigned int i;
- ZnContour *conts;
-
-
- if (cv->shape.num_contours) {
- conts = cv->shape.contours;
- if (cv->shape.contours != &cv->shape.contour1) {
- cv->shape.contours = (ZnContour *) ZnMalloc(cv->shape.num_contours*sizeof(ZnContour));
- }
- for (i = 0; i < cv->shape.num_contours; i++) {
- cv->shape.contours[i].num_points = conts[i].num_points;
- cv->shape.contours[i].cw = conts[i].cw;
- cv->shape.contours[i].points = ZnMalloc(conts[i].num_points*sizeof(ZnPoint));
- memcpy(cv->shape.contours[i].points, conts[i].points,
- conts[i].num_points*sizeof(ZnPoint));
- cv->shape.contours[i].controls = NULL;
- if (conts[i].controls) {
- cv->shape.contours[i].controls = ZnMalloc(conts[i].num_points*sizeof(char));
- memcpy(cv->shape.contours[i].controls, conts[i].controls,
- conts[i].num_points*sizeof(char));
- }
- }
- }
-
- if (cv->gradient) {
- cv->gradient = ZnGetGradientByValue(cv->gradient);
- }
- if (cv->first_end) {
- ZnLineEndDuplicate(cv->first_end);
- }
- if (cv->last_end) {
- ZnLineEndDuplicate(cv->last_end);
- }
- if (cv->tile != ZnUnspecifiedImage) {
- cv->tile = ZnGetImageByValue(cv->tile, ZnUpdateItemImage, item);
- }
- if (cv->line_pattern != ZnUnspecifiedImage) {
- cv->line_pattern = ZnGetImageByValue(cv->line_pattern, NULL, NULL);
- }
- if (cv->marker != ZnUnspecifiedImage) {
- cv->marker = ZnGetImageByValue(cv->marker, NULL, NULL);
- }
- cv->line_color = ZnGetGradientByValue(cv->line_color);
- cv->fill_color = ZnGetGradientByValue(cv->fill_color);
- cv->grad_geo = NULL;
- cv->marker_color = ZnGetGradientByValue(cv->marker_color);
- cv->tristrip.num_strips = 0;
- cv->tristrip.strips = NULL;
- cv->outlines.num_contours = 0;
- cv->outlines.contours = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- CurveItem cv = (CurveItem) item;
- unsigned int i;
-
- /*
- * Need to free the control array here, it is only known
- * by the Curve code.
- */
- for (i = 0; i < cv->shape.num_contours; i++) {
- if (cv->shape.contours[i].controls) {
- ZnFree(cv->shape.contours[i].controls);
- }
- }
- ZnPolyFree(&cv->shape);
-
- if (cv->grad_geo) {
- ZnFree(cv->grad_geo);
- }
- if (cv->first_end) {
- ZnLineEndDelete(cv->first_end);
- }
- if (cv->last_end) {
- ZnLineEndDelete(cv->last_end);
- }
- if (cv->gradient) {
- ZnFreeGradient(cv->gradient);
- }
- if (cv->tile != ZnUnspecifiedImage) {
- ZnFreeImage(cv->tile, ZnUpdateItemImage, item);
- cv->tile = ZnUnspecifiedImage;
- }
- if (cv->line_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(cv->line_pattern, NULL, NULL);
- cv->line_pattern = ZnUnspecifiedImage;
- }
- if (cv->marker != ZnUnspecifiedImage) {
- ZnFreeImage(cv->marker, NULL, NULL);
- cv->marker = ZnUnspecifiedImage;
- }
- ZnFreeGradient(cv->fill_color);
- ZnFreeGradient(cv->line_color);
- ZnFreeGradient(cv->marker_color);
-
- if (cv->tristrip.num_strips) {
- ZnTriFree(&cv->tristrip);
- }
- if (cv->outlines.num_contours) {
- ZnPolyFree(&cv->outlines);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * 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) && (cv->shape.num_contours >= 1));
-
- ASSIGN(cv->flags, RELIEF_OK,
- (cv->relief != ZN_RELIEF_FLAT) &&
- (cv->shape.num_contours >= 1) &&
- (cv->line_width > 1));
-
- ASSIGN(cv->flags, MARKER_OK,
- (cv->marker != ZnUnspecifiedImage) &&
- ISCLEAR(cv->flags, RELIEF_OK));
-
- ASSIGN(cv->flags, FIRST_END_OK,
- (cv->first_end != NULL) &&
- (cv->shape.num_contours == 1) && (cv->shape.contours[0].num_points > 1) &&
- ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
- ISCLEAR(cv->flags, RELIEF_OK) &&
- ISCLEAR(cv->flags, CLOSED_BIT));
- ASSIGN(cv->flags, LAST_END_OK,
- (cv->last_end != NULL) &&
- (cv->shape.num_contours == 1) && (cv->shape.contours[0].num_points > 1) &&
- ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
- ISCLEAR(cv->flags, RELIEF_OK) &&
- ISCLEAR(cv->flags, CLOSED_BIT));
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- int status = TCL_OK;
- XColor *color;
- unsigned short alpha;
-
- status = ZnConfigureAttributes(wi, item, item, cv_attrs, argc, argv, flags);
-
- if (cv->gradient &&
- (ISSET(*flags, ZN_BORDER_FLAG) || (cv->relief == ZN_RELIEF_FLAT))) {
- ZnFreeGradient(cv->gradient);
- cv->gradient = NULL;
- }
- if ((cv->relief != ZN_RELIEF_FLAT) && !cv->gradient) {
- color = ZnGetGradientColor(cv->line_color, 51.0, &alpha);
- cv->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- Tk_NameOfColor(color), alpha);
- if (cv->gradient == NULL) {
- status = TCL_ERROR;
- }
- }
-
- return status;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, cv_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-static void
-UpdateTristrip(CurveItem cv,
- ZnPoly *poly,
- ZnBool revert)
-{
- ZnCombineData *cdata, *cnext;
- GLdouble v[3];
- unsigned int j, k;
- int i;
-
- //printf("UpdateTristrips sur %d\n", ((ZnItem) cv)->id);
- gluTessProperty(ZnTesselator.tess, GLU_TESS_WINDING_RULE, (GLdouble) cv->fill_rule);
-
- if (cv->tristrip.num_strips == 0) {
- gluTessProperty(ZnTesselator.tess, GLU_TESS_BOUNDARY_ONLY, (GLdouble) GL_FALSE);
- gluTessBeginPolygon(ZnTesselator.tess, &cv->tristrip);
- /*
- * We need to take care of the final (after transformation) winding
- * direction of the polygon in order to have the right tesselation
- * taking place.
- */
- if (!revert) {
- for (j = 0; j < poly->num_contours; j++){
- gluTessBeginContour(ZnTesselator.tess);
- //printf("Début contour %d num_points %d\n", j, poly->contours[j].num_points);
- for (k = 0; k < poly->contours[j].num_points; k++) {
- /*printf("%g@%g ", poly->contours[j].points[k].x, poly->contours[j].points[k].y);*/
- v[0] = poly->contours[j].points[k].x;
- v[1] = poly->contours[j].points[k].y;
- v[2] = 0;
- gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[k]);
- }
- //printf("\n");
- gluTessEndContour(ZnTesselator.tess);
- }
- }
- else {
- for (j = 0; j < poly->num_contours; j++){
- gluTessBeginContour(ZnTesselator.tess);
- //printf("revert Début contour %d num_points %d\n", j, poly->contours[j].num_points);
- for (i = (int) (poly->contours[j].num_points-1); i >= 0; i--) {
- /*printf("%g@%g ", poly->contours[j].points[i].x, poly->contours[j].points[i].y);*/
- v[0] = poly->contours[j].points[i].x;
- v[1] = poly->contours[j].points[i].y;
- v[2] = 0;
- gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[i]);
- }
- //printf("\n");
- gluTessEndContour(ZnTesselator.tess);
- }
- }
- gluTessEndPolygon(ZnTesselator.tess);
- cdata = ZnTesselator.combine_list;
- //printf("Combine length: %d\n", ZnTesselator.combine_length);
- while (cdata) {
- ZnTesselator.combine_length--;
- cnext = cdata->next;
- ZnFree(cdata);
- cdata = cnext;
- }
- ZnTesselator.combine_list = NULL;
- }
- //printf("Fin UpdateTristrips sur %d\n", ((ZnItem) cv)->id);
-}
-
-static void
-UpdateOutlines(CurveItem cv,
- ZnPoly *poly,
- ZnBool revert)
-{
- ZnCombineData *cdata, *cnext;
- GLdouble v[3];
- unsigned int j, k;
- int i;
-
- //printf("UpdateOutlines sur %d\n", ((ZnItem) cv)->id);
- gluTessProperty(ZnTesselator.tess, GLU_TESS_WINDING_RULE, (GLdouble) cv->fill_rule);
-
- if (cv->outlines.num_contours == 0) {
- gluTessProperty(ZnTesselator.tess, GLU_TESS_BOUNDARY_ONLY, (GLdouble) GL_TRUE);
- gluTessBeginPolygon(ZnTesselator.tess, &cv->outlines);
-
- /*
- * We need to take care of the final (after transformation) winding
- * direction of the polygon in order to have the right tesselation
- * taking place.
- */
- if (!revert) {
- for (j = 0; j < poly->num_contours; j++){
- gluTessBeginContour(ZnTesselator.tess);
- for (k = 0; k < poly->contours[j].num_points; k++) {
- v[0] = poly->contours[j].points[k].x;
- v[1] = poly->contours[j].points[k].y;
- v[2] = 0;
- gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[k]);
- }
- gluTessEndContour(ZnTesselator.tess);
- }
- }
- else {
- for (j = 0; j < poly->num_contours; j++){
- gluTessBeginContour(ZnTesselator.tess);
- for (i = (int) (poly->contours[j].num_points-1); i >= 0; i--) {
- v[0] = poly->contours[j].points[i].x;
- v[1] = poly->contours[j].points[i].y;
- v[2] = 0;
- gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[i]);
- }
- gluTessEndContour(ZnTesselator.tess);
- }
- }
- gluTessEndPolygon(ZnTesselator.tess);
- cdata = ZnTesselator.combine_list;
- while (cdata) {
- ZnTesselator.combine_length--;
- cnext = cdata->next;
- ZnFree(cdata);
- cdata = cnext;
- }
- ZnTesselator.combine_list = NULL;
- }
- //printf("Fin UpdateOutlines sur %d\n", ((ZnItem) cv)->id);
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- unsigned int i, j;
- ZnPoint end_points[ZN_LINE_END_POINTS];
- ZnPoint *points;
- unsigned int num_points, num_contours, segment_start;
- ZnBBox bbox;
- ZnDim lw;
- ZnContour *c1, *c2;
- ZnPoly dev;
- ZnBool revert;
-
- ZnResetBBox(&item->item_bounding_box);
-
- /*printf("Curve CC: flags %x\n", cv->flags);*/
- SetRenderFlags(cv);
-
- num_contours = cv->shape.num_contours;
- if (num_contours == 0) {
- return;
- }
-
- if (cv->tristrip.num_strips) {
- ZnTriFree(&cv->tristrip);
- }
- if (cv->outlines.num_contours) {
- ZnPolyFree(&cv->outlines);
- };
-
- ZnPolyInit(&dev);
- if (num_contours != 1) {
- dev.contours = ZnMalloc(num_contours * sizeof(ZnContour));
- dev.num_contours = num_contours;
- }
- else {
- dev.contours = &dev.contour1;
- dev.num_contours = 1;
- }
-
- for (c1 = cv->shape.contours, c2 = dev.contours, i = 0;
- i < cv->shape.num_contours; i++, c1++, c2++) {
- c2->num_points = c1->num_points;
- /*
- * Add a point at the end of the contour to close it
- * if needed. Works only if a single contour is given, in
- * this case it can be used as a path. In the case of
- * multiple contours, the outline is automatically
- * closed by the tesselator.
- */
- if ((num_contours == 1) &&
- (c1->num_points > 2) &&
- ISSET(cv->flags, CLOSED_BIT) &&
- ((c1->points[0].x != c1->points[c1->num_points-1].x) ||
- (c1->points[0].y != c1->points[c1->num_points-1].y)) &&
- (c1->num_points > 2)) {
- c2->num_points++;
- }
- c2->points = ZnMalloc((c2->num_points)*sizeof(ZnPoint));
- /*printf("CC: \"%d\" num_points %d\n", item->id, c1->num_points);*/
- ZnTransformPoints(wi->current_transfo, c1->points, c2->points, c1->num_points);
- if (c1->num_points != c2->num_points) {
- c2->points[c2->num_points-1] = c2->points[0];
- }
- /*
- * Now expand the bezier segments into polylines.
- */
- if (c1->controls) {
- segment_start = 0;
- ZnListEmpty(ZnWorkPoints);
- ZnListAdd(ZnWorkPoints, &c2->points[0], ZnListTail);
- /*printf("moveto %g@%g\n", c2->points[0].x, c2->points[0].y);*/
- for (j = 1; j < c1->num_points; j++) {
- if (!c1->controls[j]) {
- if (segment_start != j-1) {
- /* traitement bezier */
- /*printf("arcto %g@%g %g@%g %g@%g\n",
- c2->points[segment_start+1].x, c2->points[segment_start+1].y,
- c2->points[j-1].x, c2->points[j-1].y,
- c2->points[j].x, c2->points[j].y);*/
- ZnGetBezierPoints(&c2->points[segment_start],
- &c2->points[segment_start+1], &c2->points[j-1],
- &c2->points[j], ZnWorkPoints, 0.5);
- }
- else {
- /*printf("lineto %g@%g\n", c2->points[j].x, c2->points[j].y);*/
- ZnListAdd(ZnWorkPoints, &c2->points[j], ZnListTail);
- }
- segment_start = j;
- }
- }
- /*
- * Must test if the last point is a control and the contour
- * is closed (either a mono contour with -closed or
- * multiple contours).
- */
- if (c1->controls[c1->num_points-1]) {
- ZnGetBezierPoints(&c2->points[segment_start],
- &c2->points[segment_start+1], &c2->points[c1->num_points-1],
- &c2->points[0], ZnWorkPoints, 0.5);
- }
-
- /*
- * Replace the original path by the expanded, closing it as
- * needed (one open contour).
- */
- num_points =ZnListSize(ZnWorkPoints);
- if (c2->num_points != c1->num_points) {
- num_points++;
- }
- c2->points = ZnRealloc(c2->points, num_points*sizeof(ZnPoint));
- memcpy(c2->points, ZnListArray(ZnWorkPoints), num_points*sizeof(ZnPoint));
- if (c2->num_points != c1->num_points) {
- c2->points[num_points-1] = c2->points[0];
- }
- c2->num_points = num_points;
- }
- }
-
- /*
- * Test the scale factors to see if we need to reverse the
- * polygons winding.
- */
- revert = (wi->current_transfo->_[0][0]*wi->current_transfo->_[1][1]) < 0;
- if (num_contours == 1) {
- if (cv->shape.contours[0].num_points > 2) {
- UpdateTristrip(cv, &dev, revert);
- /*if (!cv->tristrip.num_strips) {
- int kk;
- ZnPrintTransfo(wi->current_transfo);
- printf("id: %d, NumCont: %d, NumPoints: %d, Original: %d, Resultat: %d, NumTri: %d\n",
- item->id, num_contours,cv->shape.contours[0].num_points,
- cv->shape.contours[0].cw, cw_dev_contour1, cv->tristrip.num_strips);
- for (kk = 0; kk < cv->shape.contours[0].num_points; kk++) {
- printf("%g@%g ", cv->shape.contours[0].points[kk].x,
- cv->shape.contours[0].points[kk].y);
- }
- printf("\n");
- }*/
- }
- ZnPolyContour1(&cv->outlines, dev.contours[0].points, dev.contours[0].num_points,
- cv->shape.contours[0].cw);
- }
- else {
- UpdateTristrip(cv, &dev, revert);
- /*if (!cv->tristrip.num_strips) {
- ZnPrintTransfo(wi->current_transfo);
- printf("id: %d, NumCont: %d, NumPoints: %d, Original: %d, Resultat: %d, NumTri: %d\n",
- item->id, num_contours,cv->shape.contours[0].num_points,
- cv->shape.contours[0].cw, cw_dev_contour1, cv->tristrip.num_strips);
- }*/
- UpdateOutlines(cv, &dev, revert);
- ZnPolyFree(&dev);
- }
-
- lw = cv->line_width;
- num_contours = cv->outlines.num_contours;
- if (ISSET(cv->flags, RELIEF_OK)) {
- c2 = cv->outlines.contours;
- for (i = 0; i < num_contours; i++, c2++) {
- /*
- * Add to bounding box.
- */
- ZnGetPolygonReliefBBox(c2->points, c2->num_points, lw, &bbox);
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- }
- else {
- c2 = cv->outlines.contours;
- for (i = 0; i < num_contours; i++, c2++) {
- ZnAddPointsToBBox(&item->item_bounding_box, c2->points, c2->num_points);
- }
-
- /*
- * Take care of miters, markers and arrows.
- */
- c2 = cv->outlines.contours;
- for (j = 0; j < num_contours; j++, c2++) {
- if (c2->cw) {
- continue;
- }
- if (cv->join_style == JoinMiter) {
- ZnPoint miter_i, miter_o;
- for (i = c2->num_points-1, points = c2->points; i >= 3; i--, points++) {
- ZnGetMiterPoints(points, points+1, points+2, lw, &miter_i, &miter_o);
- ZnAddPointToBBox(&item->item_bounding_box, miter_i.x, miter_i.y);
- ZnAddPointToBBox(&item->item_bounding_box, miter_o.x, miter_o.y);
- }
- }
- /*
- * Add the markers.
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- int w, h;
- ZnBBox bbox;
-
- ZnSizeOfImage(cv->marker, &w, &h);
- w = w/2 + 2;
- h = h/2 + 2;
- num_points = c2->num_points;
- for (i = 0, points = c2->points; i < num_points; i++, points++) {
- bbox.orig.x = points->x - w;
- bbox.orig.y = points->y - h;
- bbox.corner.x = points->x + w;
- bbox.corner.y = points->y + h;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- }
- /*
- * Process arrows.
- */
- num_points = c2->num_points;
- points = c2->points;
- if (ISSET(cv->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], lw, cv->cap_style,
- cv->first_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2],
- lw, cv->cap_style, cv->last_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- }
-
- /*
- * Add the line width in all directions.
- * This overestimates the space needed to draw the polyline
- * but is simple.
- */
- 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;
-
- /*
- * 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;
- }
-
-#ifdef GL
- if (!ZnGradientFlat(cv->fill_color)) {
- if (!cv->grad_geo) {
- cv->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
- }
- ZnComputeGradient(cv->fill_color, wi, &cv->shape, cv->grad_geo);
- }
- else {
- if (cv->grad_geo) {
- ZnFree(cv->grad_geo);
- cv->grad_geo = NULL;
- }
- }
-#endif
-}
-
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- CurveItem cv = (CurveItem) item;
- ZnBBox bbox, *area = ta->area;
- ZnPoint *points;
- ZnPoint triangle[3];
- ZnPoint end_points[ZN_LINE_END_POINTS];
- unsigned int i, j, num_points, stop;
- int width, height, result=-1, result2;
- ZnBool first_done = False;
-
- if (cv->outlines.num_contours == 0) {
- return -1;
- }
- /*printf("============== poly %d ==============\n", item->id);*/
-
- if (ISSET(cv->flags, FILLED_OK)) {
- /*printf("testing surfaces\n");*/
- for (i = 0; i < cv->tristrip.num_strips; i++) {
- num_points = cv->tristrip.strips[i].num_points;
- points = cv->tristrip.strips[i].points;
- j = 0;
- stop = num_points-2;
- if (cv->tristrip.strips[i].fan) {
- triangle[0] = points[0];
- j++;
- points++;
- stop++;
- }
- for (; j < stop; j++, points++) {
- if (cv->tristrip.strips[i].fan) {
- triangle[1] = points[0];
- triangle[2] = points[1];
- }
- else {
- triangle[0] = points[0];
- triangle[1] = points[1];
- triangle[2] = points[2];
- }
- if (!first_done) {
- first_done = True;
- result = ZnPolygonInBBox(triangle, 3, area, NULL);
- }
- else {
- result2 = ZnPolygonInBBox(triangle, 3, area, NULL);
- if (result2 != result) {
- return 0;
- }
- }
- }
- }
- }
-
- if (cv->line_width > 0) {
- /*printf("testing lines\n");*/
- for (i = 0; i < cv->outlines.num_contours; i++) {
- num_points = cv->outlines.contours[i].num_points;
- points = cv->outlines.contours[i].points;
- if (!first_done) {
- first_done = True;
- if (ISCLEAR(cv->flags, RELIEF_OK)) {
- result = ZnPolylineInBBox(points, num_points,
- cv->line_width, cv->cap_style, cv->join_style, area);
- }
- else {
- result = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
- }
- if (result == 0) {
- return 0;
- }
- }
- else {
- if (ISCLEAR(cv->flags, RELIEF_OK)) {
- result2 = ZnPolylineInBBox(points, num_points,
- cv->line_width, cv->cap_style, cv->join_style, area);
- }
- else {
- result2 = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
- }
- if (result2 != result) {
- return 0;
- }
- }
- }
-
- /*
- * Check line ends (only on first contour).
- */
- points = cv->outlines.contours[0].points;
- num_points = cv->outlines.contours[0].num_points;
- if (ISSET(cv->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
- cv->first_end, end_points);
- if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
- cv->cap_style, cv->last_end, end_points);
- if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- }
-
- /*
- * Last, check markers
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- for (i = 0; i < cv->outlines.num_contours; i++) {
- points = cv->outlines.contours[i].points;
- num_points = cv->outlines.contours[i].num_points;
-
- if (ISSET(cv->flags, FIRST_END_OK)) {
- num_points--;
- points++;
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- num_points--;
- }
-
- ZnSizeOfImage(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 (ZnBBoxInBBox(&bbox, area) != result) {
- return 0;
- }
- }
- }
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- XGCValues values;
- unsigned int i, j, num_points=0;
- unsigned int gc_mask;
- ZnPoint *points=NULL;
- XPoint *xpoints=NULL;
-
- if ((cv->outlines.num_contours == 0) ||
- (ISCLEAR(cv->flags, FILLED_OK) &&
- !cv->line_width &&
- ISCLEAR(cv->flags, MARKER_OK))) {
- return;
- }
-
- /*
- * Fill if requested.
- */
- if (ISSET(cv->flags, FILLED_OK)) {
- values.foreground = ZnGetGradientPixel(cv->fill_color, 0.0);
- gc_mask = GCFillStyle;
- if (cv->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(cv->tile)) { /* Fill tiled */
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(cv->tile, wi->win);
- values.ts_x_origin = ZnNearestInt(item->item_bounding_box.orig.x);
- values.ts_y_origin = ZnNearestInt(item->item_bounding_box.orig.y);
- gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCTile;
- }
- else { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(cv->tile, wi->win);
- values.ts_x_origin = ZnNearestInt(item->item_bounding_box.orig.x);
- values.ts_y_origin = ZnNearestInt(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);
-
-
- for (i = 0; i < cv->tristrip.num_strips; i++) {
- num_points = cv->tristrip.strips[i].num_points;
- points = cv->tristrip.strips[i].points;
- if (cv->tristrip.strips[i].fan) {
- XPoint xpoints[3];
- xpoints[0].x = ZnNearestInt(points[0].x);
- xpoints[0].y = ZnNearestInt(points[0].y);
- xpoints[1].x = ZnNearestInt(points[1].x);
- xpoints[1].y = ZnNearestInt(points[1].y);
- for (j = 2; j < num_points; j++) {
- xpoints[2].x = ZnNearestInt(points[j].x);
- xpoints[2].y = ZnNearestInt(points[j].y);
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, 3, Convex, CoordModeOrigin);
- xpoints[1] = xpoints[2];
- }
- }
- else {
- ZnListAssertSize(ZnWorkXPoints, num_points);
- xpoints = ZnListArray(ZnWorkXPoints);
- for (j = 0; j < num_points; j++) {
- xpoints[j].x = ZnNearestInt(points[j].x);
- xpoints[j].y = ZnNearestInt(points[j].y);
- }
- for (j = 0; j < num_points-2; j++) {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- &xpoints[j], 3, Convex, CoordModeOrigin);
- }
- }
- }
- }
-
- /*
- * Draw the lines between points
- */
- if (cv->line_width) {
- ZnPoint end_points[ZN_LINE_END_POINTS];
- XPoint xp[ZN_LINE_END_POINTS];
-
- /*
- * Drawing with relief disables: ends, line style and line pattern.
- */
- if (ISSET(cv->flags, RELIEF_OK)) {
- for (j = 0; j < cv->outlines.num_contours; j++) {
- num_points = cv->outlines.contours[j].num_points;
- points = cv->outlines.contours[j].points;
- /*printf("Draw: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
- item->id,
- num_points, points[0].x, points[0].y,
- points[num_points-1].x, points[num_points-1].y,
- cv->outlines.contours[j].cw);*/
- ZnDrawPolygonRelief(wi, cv->relief, cv->gradient, points, num_points, cv->line_width);
- }
- }
- else {
- ZnSetLineStyle(wi, cv->line_style);
- values.foreground = ZnGetGradientPixel(cv->line_color, 0.0);
- values.line_width = (cv->line_width == 1) ? 0 : (int) cv->line_width;
- values.join_style = cv->join_style;
- values.cap_style = cv->cap_style;
- if (cv->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(cv->line_pattern, wi->win);
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCStipple|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground,
- &values);
- }
- for (j = 0; j < cv->outlines.num_contours; j++) {
- num_points = cv->outlines.contours[j].num_points;
- points = cv->outlines.contours[j].points;
- ZnListAssertSize(ZnWorkXPoints, num_points);
- xpoints = ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = ZnNearestInt(points[i].x);
- xpoints[i].y = ZnNearestInt(points[i].y);
- }
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, (int) num_points, CoordModeOrigin);
- }
- if (ISSET(cv->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
- cv->first_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xp[i].x = (short) end_points[i].x;
- xp[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
- cv->cap_style, cv->last_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xp[i].x = (short) end_points[i].x;
- xp[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- }
- }
-
- /*
- * Draw the marks at each point. If arrows are specified or
- * if last point join first point suppress markers at end points.
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- unsigned int h_width, h_height, width, height;
- int tmp_x, tmp_y;
-
- ZnSizeOfImage(cv->marker, &width, &height);
- h_width = (width+1)/2;
- h_height = (height+1)/2;
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(cv->marker, wi->win);
- values.foreground = ZnGetGradientPixel(cv->marker_color, 0.0);
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCStipple|GCForeground, &values);
- for (j = 0; j < cv->outlines.num_contours; j++) {
- num_points = cv->outlines.contours[j].num_points;
- points = cv->outlines.contours[j].points;
- ZnListAssertSize(ZnWorkXPoints, num_points);
- xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = (short) ZnNearestInt(points[i].x);
- xpoints[i].y = (short) ZnNearestInt(points[i].y);
- }
- if (ISSET(cv->flags, FIRST_END_OK)) {
- num_points--;
- points++;
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- num_points--;
- }
- for (; num_points > 0; num_points--, points++) {
- tmp_x = ((int) points->x) - h_width;
- tmp_y = ((int) points->y) - h_height;
- values.ts_x_origin = tmp_x;
- values.ts_y_origin = tmp_y;
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCForeground, &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- tmp_x, tmp_y, width, height);
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-CurveRenderCB(void *closure)
-{
- CurveItem cv = (CurveItem) closure;
- unsigned int i, j, num_points;
- ZnPoint *points;
-
- for (i = 0; i < cv->tristrip.num_strips; i++) {
- num_points = cv->tristrip.strips[i].num_points;
- points = cv->tristrip.strips[i].points;
- if (cv->tristrip.strips[i].fan) {
- glBegin(GL_TRIANGLE_FAN);
- }
- else {
- glBegin(GL_TRIANGLE_STRIP);
- }
- for (j = 0; j < num_points; j++, points++) {
- glVertex2d(points->x, points->y);
- }
- glEnd();
- }
-}
-#endif
-
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- unsigned int j, num_points;
- ZnPoint *points;
-
- if ((cv->outlines.num_contours == 0) ||
- (ISCLEAR(cv->flags, FILLED_OK) &&
- !cv->line_width &&
- ISCLEAR(cv->flags, MARKER_OK))) {
- return;
- }
-
-#ifdef GL_LIST
- if (!item->gl_list) {
- item->gl_list = glGenLists(1);
- glNewList(item->gl_list, GL_COMPILE);
-#endif
- /*
- * Fill if requested.
- */
- if (ISSET(cv->flags, FILLED_OK)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (!ZnGradientFlat(cv->fill_color)) {
- ZnRenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo,
- &cv->outlines);
- }
- else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
- ZnRenderTile(wi, cv->tile, cv->fill_color, CurveRenderCB, cv,
- (ZnPoint *) &item->item_bounding_box);
- }
- else {
- unsigned short alpha;
- XColor *color = ZnGetGradientColor(cv->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- CurveRenderCB(cv);
- }
- }
-
- /*
- * Draw the lines between points
- */
- if (cv->line_width) {
- /*
- * Drawing with relief disables: ends, line style and line pattern.
- */
- if (ISSET(cv->flags, RELIEF_OK)) {
- for (j = 0; j < cv->outlines.num_contours; j++) {
- num_points = cv->outlines.contours[j].num_points;
- points = cv->outlines.contours[j].points;
- /*printf("Render: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
- item->id,
- num_points, points[0].x, points[0].y,
- points[num_points-1].x, points[num_points-1].y,
- cv->outlines.contours[j].cw);*/
- ZnRenderPolygonRelief(wi, cv->relief, cv->gradient,
- ISSET(cv->flags, SMOOTH_RELIEF_BIT),
- points, num_points, cv->line_width);
- }
- }
- else {
- ZnLineEnd first = ISSET(cv->flags, FIRST_END_OK) ? cv->first_end : NULL;
- ZnLineEnd last = ISSET(cv->flags, LAST_END_OK) ? cv->last_end : NULL;
-
- for (j = 0; j < cv->outlines.num_contours; j++) {
- ZnRenderPolyline(wi,
- cv->outlines.contours[j].points,
- cv->outlines.contours[j].num_points,
- cv->line_width, cv->line_style, cv->cap_style,
- cv->join_style, first, last, cv->line_color);
- }
- }
- }
-
- /*
- * Draw the marks at each point. If arrows are specified or
- * if last point join first point suppress markers at end points.
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- int i_width, i_height;
- ZnReal r_width, r_height;
- ZnPoint ptmp;
-
- ZnSizeOfImage(cv->marker, &i_width, &i_height);
- r_width = (i_width+1.0)/2.0;
- r_height = (i_height+1.0)/2.0;
- for (j = 0; j < cv->outlines.num_contours; j++) {
- num_points = cv->outlines.contours[j].num_points;
- points = cv->outlines.contours[j].points;
- if (ISSET(cv->flags, FIRST_END_OK)) {
- num_points--;
- points++;
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- num_points--;
- }
- for (; num_points > 0; num_points--, points++) {
- ptmp.x = points->x - r_width;
- ptmp.y = points->y - r_height;
- ZnRenderIcon(wi, cv->marker, cv->marker_color, &ptmp, True);
- }
- }
- }
-#ifdef GL_LIST
- glEndList();
- }
-
- glCallList(item->gl_list);
-#endif
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- CurveItem cv = (CurveItem) item;
- ZnBBox bbox;
- double dist=1.0e40, new_dist;
- ZnPoint *points, *p = ps->point;
- ZnPoint end_points[ZN_LINE_END_POINTS];
- ZnPoint triangle[3];
- unsigned int num_points, i, j, stop;
- int width, height;
-
- if (cv->outlines.num_contours == 0) {
- return dist;
- }
-
-/*printf("Pick in curve\n");*/
- if (ISSET(cv->flags, FILLED_OK)) {
- for (i = 0; i < cv->tristrip.num_strips; i++) {
- num_points = cv->tristrip.strips[i].num_points;
- points = cv->tristrip.strips[i].points;
- j = 0;
- stop = num_points-2;
- if (cv->tristrip.strips[i].fan) {
- triangle[0] = points[0];
- j++;
- points++;
- stop++;
- }
- for (; j < stop; j++, points++) {
- if (cv->tristrip.strips[i].fan) {
- triangle[1] = points[0];
- triangle[2] = points[1];
- }
- else {
- triangle[0] = points[0];
- triangle[1] = points[1];
- triangle[2] = points[2];
- }
- new_dist = ZnPolygonToPointDist(triangle, 3, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- }
- }
-
- if (cv->line_width > 0) {
- /*
- * Check all contours.
- */
- for (i = 0; i < cv->outlines.num_contours; i++) {
- points = cv->outlines.contours[i].points;
- num_points = cv->outlines.contours[i].num_points;
- if (ISCLEAR(cv->flags, RELIEF_OK)) {
- new_dist = ZnPolylineToPointDist(points, num_points,
- cv->line_width, cv->cap_style, cv->join_style, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- /*printf("dist %g\n", dist);*/
- return 0.0;
- }
- }
- else {
- new_dist = ZnPolygonReliefToPointDist(points, num_points, cv->line_width, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- /*printf("dist %g\n", dist);*/
- return 0.0;
- }
- }
- }
- }
-
- /*
- * Line ends are checked only on the first contour.
- */
- points = cv->outlines.contours[0].points;
- num_points = cv->outlines.contours[0].num_points;
- /*
- * Check line ends.
- */
- if (ISSET(cv->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
- cv->first_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- /*printf("dist %g\n", dist);*/
- return 0.0;
- }
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
- cv->cap_style, cv->last_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- /*printf("dist %g\n", dist);*/
- return 0.0;
- }
- }
-
- /*
- * Last, check markers on all contours.
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- for (i = 0; i < cv->outlines.num_contours; i++) {
- points = cv->outlines.contours[i].points;
- num_points = cv->outlines.contours[i].num_points;
-
- if (ISSET(cv->flags, FIRST_END_OK)) {
- num_points--;
- points++;
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- num_points--;
- }
-
- ZnSizeOfImage(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 = ZnRectangleToPointDist(&bbox, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- /*printf("dist %g\n", dist);*/
- return 0.0;
- }
- }
- }
- }
-
- /*printf("dist %g\n", dist);*/
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- CurveItem cv = (CurveItem) item;
- char path[500];
- ZnContour *contours;
- ZnPoint *points;
- int num_contours, num_points;
- int i, j;
-
- num_contours = cv->outlines.num_contours;
- contours = cv->outlines.contours;
-
- /*
- * Put all contours in an array on the stack
- */
- if (ISSET(cv->flags, FILLED_BIT) || cv->line_width) {
- Tcl_AppendResult(wi->interp, "newpath ", NULL);
- for (i = 0; i < num_contours; i++, contours++) {
- num_points = contours->num_points;
- points = contours->points;
- sprintf(path, "%.15g %.15g moveto\n", points[0].x, points[0].y);
- Tcl_AppendResult(wi->interp, path, NULL);
- for (j = 1; j < num_points; j++) {
- sprintf(path, "%.15g %.15g lineto ", points[j].x, points[j].y);
- Tcl_AppendResult(wi->interp, path, NULL);
- if (((j+1) % 5) == 0) {
- Tcl_AppendResult(wi->interp, "\n", NULL);
- }
- }
- }
- }
-
- /*
- * Emit code to draw the filled area.
- */
- if (ISSET(cv->flags, FILLED_BIT)) {
- if (cv->line_width) {
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- }
- if (!ZnGradientFlat(cv->fill_color)) {
- if (ZnPostscriptGradient(wi->interp, wi->ps_info, cv->fill_color,
- cv->grad_geo, NULL) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- else if (cv->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(cv->tile)) { /* Fill tiled */
- /* TODO No support yet */
- }
- else { /* Fill stippled */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "clip ", NULL);
- if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
- ZnImagePixmap(cv->tile, wi->win)) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- }
- else { /* Fill solid */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "fill\n", NULL);
- }
- if (cv->line_width) {
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
-
- /*
- * Then emit code code to stroke the outline.
- */
- if (cv->line_width) {
- if (cv->relief != ZN_RELIEF_FLAT) {
- /* TODO No support yet */
- }
- else {
- Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
- if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
- cv->line_width, cv->line_style,
- cv->line_color, cv->line_pattern) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- CurveItem cv = (CurveItem) item;
-
- tristrip->num_strips = 0;
-
- if (cv->tristrip.num_strips == 1) {
- ZnTriStrip1(tristrip,
- cv->tristrip.strips[0].points,
- cv->tristrip.strips[0].num_points,
- cv->tristrip.strips[0].fan);
- }
- else if (cv->tristrip.num_strips > 1) {
- tristrip->num_strips = cv->tristrip.num_strips;
- tristrip->strips = cv->tristrip.strips;
- }
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetContours --
- * Get the external contour(s).
- * Never ever call ZnPolyFree on the poly returned by GetContours.
- *
- **********************************************************************************
- */
-static ZnBool
-GetContours(ZnItem item,
- ZnPoly *poly)
-{
- CurveItem cv = (CurveItem) item;
-
- if (cv->outlines.num_contours == 1) {
- ZnPolyContour1(poly, cv->outlines.contours[0].points,
- cv->outlines.contours[0].num_points,
- cv->outlines.contours[0].cw);
- }
- else if (cv->outlines.num_contours > 1) {
- poly->num_contours = cv->outlines.num_contours;
- poly->contours = cv->outlines.contours;
- }
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item vertices.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- CurveItem cv = (CurveItem) item;
- unsigned int j, num_controls;
- int i;
- ZnContour *c=NULL;
-
- /*printf("contour %d, num_pts %d, index %d, cmd %d\n",
- contour, *num_pts, index, cmd);*/
- /*printf("nb contours: %d\n", cv->shape.num_contours);*/
- /*
- * Special case for reading an empty curve.
- */
- if (((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) &&
- (cv->shape.num_contours == 0)) {
- *num_pts = 0;
- return TCL_OK;
- }
-
- if (contour < 0) {
- contour += cv->shape.num_contours;
- }
- if ((contour < 0) || ((unsigned int) contour >= cv->shape.num_contours)) {
- Tcl_AppendResult(item->wi->interp,
- " curve contour index out of range", NULL);
- return TCL_ERROR;
- }
- if (cv->shape.num_contours != 0) {
- c = &cv->shape.contours[contour];
- }
-
- /* REPLACE */
-
- if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (cmd == ZN_COORDS_REPLACE_ALL) {
- /*
- * Replacing all the coordinates of a contour by no coordinates
- * is also legal, resulting in the contour being removed.
- */
- if (*num_pts) {
- if (c->points) {
- ZnFree(c->points);
- }
- c->points = ZnMalloc(*num_pts*sizeof(ZnPoint));
- c->num_points = *num_pts;
- memcpy(c->points, *pts, *num_pts*sizeof(ZnPoint));
- if (c->controls) {
- ZnFree(c->controls);
- c->controls = NULL;
- }
- if (*controls) {
- c->controls = ZnMalloc(*num_pts*sizeof(char));
- memcpy(c->controls, *controls, *num_pts*sizeof(char));
- }
- }
- }
- else {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords replace command need at least 1 point on curves", NULL);
- return TCL_ERROR;
- }
- if (index < 0) {
- index += c->num_points;
- }
- if ((index < 0) || ((unsigned int) index >= c->num_points)) {
- range_err:
- Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
- return TCL_ERROR;
- }
- /*printf("--->%g@%g\n", (*pts)[0].x, (*pts)[0].y);*/
- c->points[index] = (*pts)[0];
- if (!c->controls && *controls && (*controls)[0]) {
- c->controls = ZnMalloc(c->num_points*sizeof(char));
- memset(c->controls, 0, c->num_points*sizeof(char));
- }
- if (c->controls) {
- if (!*controls) {
- c->controls[index] = 0;
- }
- else {
- if ((*controls)[0]) {
- /* Check if the edit is allowable, there should be
- * no more than 2 consecutive control points. The first
- * point must not be a control and the last one can
- * be one only if the curve is closed.
- */
- num_controls = 0;
- if (!index) {
- control_first:
- Tcl_AppendResult(item->wi->interp, " the first point must not be a control", NULL);
- return TCL_ERROR;
- }
- else if ((unsigned int) index == c->num_points-1) {
- if (ISCLEAR(cv->flags, CLOSED_BIT) &&
- (cv->shape.num_contours == 1)) {
- control_last:
- Tcl_AppendResult(item->wi->interp, " the last point must not be a control", NULL);
- return TCL_ERROR;
- }
- }
- else {
- for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
- }
- for (j = index+1; c->controls[j] && (j < c->num_points); j++, num_controls++);
- if (num_controls > 1) {
- control_err:
- Tcl_AppendResult(item->wi->interp, " too many consecutive control points in a curve", NULL);
- return TCL_ERROR;
- }
- }
- c->controls[index] = (*controls)[0];
- }
- }
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-
- /* READ */
-
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- if (cmd == ZN_COORDS_READ_ALL) {
- *num_pts = c->num_points;
- *pts = c->points;
- if (c->controls) {
- *controls = c->controls;
- }
- }
- else {
- /* Special case for an empty contour. */
- if (c->num_points == 0) {
- *num_pts = 0;
- return TCL_OK;
- }
- if (index < 0) {
- index += c->num_points;
- }
- if ((index < 0) || ((unsigned int) index >= c->num_points)) {
- goto range_err;
- }
- *num_pts = 1;
- *pts = &c->points[index];
- if (c->controls) {
- *controls = &c->controls[index];
- }
- }
- }
-
- /* ADD */
-
- else if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST)) {
- if (*num_pts == 0) {
- return TCL_OK;
- }
- if (cmd == ZN_COORDS_ADD_LAST) {
- index = c->num_points;
- }
- if (index < 0) {
- index += c->num_points;
- }
- if ((index < 0) || ((unsigned int) index > c->num_points)) {
- goto range_err;
- }
- if (*controls) {
- /* Check if the edit is allowable, there should be
- * no more than 2 consecutive control points. The first
- * point must not be a control and the last one can
- * be one only if the curve is closed.
- */
- if ((index == 0) && (*controls)[0]) {
- goto control_first;
- }
- else if (((unsigned int) index == (c->num_points-1)) &&
- (*controls)[*num_pts-1] &&
- ISCLEAR(cv->flags, CLOSED_BIT) &&
- (cv->shape.num_contours == 1)) {
- goto control_last;
- }
-
- num_controls = 0;
- if (c->controls) {
- if (index) {
- for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
- }
- }
- /*printf("******* num controls: %d\n", num_controls);*/
- for (j = 0; j < *num_pts; j++) {
- if (!(*controls)[j]) {
- num_controls = 0;
- }
- else {
- num_controls++;
- if (num_controls > 2) {
- goto control_err;
- }
- }
- }
- /*printf("******* num controls(2): %d\n", num_controls);*/
- if (c->controls) {
- for (j = index; c->controls[j] && (j < c->num_points); j++, num_controls++);
- }
- /*printf("******* num controls(3): %d\n", num_controls);*/
- if (num_controls > 2) {
- goto control_err;
- }
- }
- c->points = ZnRealloc(c->points, (c->num_points+*num_pts)*sizeof(ZnPoint));
- if (*controls || c->controls) {
- if (c->controls) {
- c->controls = ZnRealloc(c->controls, (c->num_points+*num_pts)*sizeof(char));
- }
- else {
- c->controls = ZnMalloc((c->num_points+*num_pts)*sizeof(char));
- memset(c->controls, 0, (c->num_points+*num_pts)*sizeof(char));
- }
- }
- /*
- * Make a hole if needed.
- */
- for (i = c->num_points-1; i >= index; i--) {
- c->points[i+*num_pts] = c->points[i];
- if (c->controls) {
- c->controls[i+*num_pts] = c->controls[i];
- }
- }
- for (j = 0; j < *num_pts; j++, index++) {
- c->points[index] = (*pts)[j];
- if (c->controls) {
- c->controls[index] = (*controls)?(*controls)[j]:0;
- }
- }
- c->num_points += *num_pts;
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-
- /* REMOVE */
-
- else if (cmd == ZN_COORDS_REMOVE) {
- if (index < 0) {
- index += c->num_points;
- }
- if ((index < 0) || ((unsigned int) index >= c->num_points)) {
- goto range_err;
- }
-
- if (c->controls) {
- /* Check if the edit is allowable, there should be
- * no more than 2 consecutive control points .
- */
- for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
- for (i = index+1; !c->controls[i]; i++, num_controls++);
- if (num_controls > 2) {
- goto control_err;
- }
- }
-
- c->num_points--;
- if ((c->num_points != 0) && ((unsigned int) index != c->num_points)) {
- for (j = index; j < c->num_points; j++) {
- c->points[j] = c->points[j+1];
- if (c->controls) {
- c->controls[j] = c->controls[j+1];
- }
- }
- }
- c->points = ZnRealloc(c->points, (c->num_points)*sizeof(ZnPoint));
- if (c->controls) {
- c->controls = ZnRealloc(c->controls, (c->num_points)*sizeof(char));
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Contour --
- * Perform geometric operations on curve contours.
- *
- **********************************************************************************
- */
-static int
-Contour(ZnItem item,
- int cmd,
- int index,
- ZnPoly *poly)
-{
- CurveItem cv = (CurveItem) item;
- unsigned int j, num_contours;
- int i;
-
- switch (cmd) {
- case ZN_CONTOUR_ADD:
- if (index < 0) {
- index += cv->shape.num_contours;
- }
- if ((unsigned int) index > cv->shape.num_contours) {
- index = cv->shape.num_contours;
- }
- if (index < 0) {
- contour_err:
- Tcl_AppendResult(item->wi->interp, " contour index out of range", NULL);
- return TCL_ERROR;
- }
- num_contours = cv->shape.num_contours + poly->num_contours;
- if (cv->shape.contours == &cv->shape.contour1) {
- cv->shape.contours = ZnMalloc(num_contours*sizeof(ZnContour));
- cv->shape.contours[0].num_points = cv->shape.contour1.num_points;
- cv->shape.contours[0].cw = cv->shape.contour1.cw;
- cv->shape.contours[0].points = cv->shape.contour1.points;
- cv->shape.contours[0].controls = cv->shape.contour1.controls;
- }
- else {
- cv->shape.contours = ZnRealloc(cv->shape.contours, num_contours*sizeof(ZnContour));
- /*printf("Reallocating shape contours (%d) 0x%X\n", num_contours, cv->shape.contours);*/
- }
- /*
- * Make a hole if needed.
- */
- /*printf("index : %d, i : %d\n", index, cv->shape.num_contours-1);*/
- for (i = cv->shape.num_contours-1; i >= index; i--) {
- cv->shape.contours[i+poly->num_contours] = cv->shape.contours[i];
- }
- for (j = 0; j < poly->num_contours; j++, index++) {
- cv->shape.contours[index].num_points = poly->contours[j].num_points;
- cv->shape.contours[index].cw = poly->contours[j].cw;
- cv->shape.contours[index].points = poly->contours[j].points;
- cv->shape.contours[index].controls = NULL;
- if (poly->contours[j].controls) {
- /*
- * The controls array in poly is shared, duplicate it
- * to keep a locally owned copy.
- */
- cv->shape.contours[index].controls = poly->contours[j].controls;
- }
- }
- cv->shape.num_contours = num_contours;
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- break;
- case ZN_CONTOUR_REMOVE:
- if (index < 0) {
- index += cv->shape.num_contours;
- }
- if ((unsigned int) index >= cv->shape.num_contours) {
- index = cv->shape.num_contours - 1;
- }
- if (index < 0) {
- goto contour_err;
- }
- cv->shape.num_contours--;
- if (cv->shape.num_contours == 0) {
- ZnPolyFree(&cv->shape);
- }
- else {
- ZnFree(cv->shape.contours[index].points);
- if (cv->shape.contours[index].controls) {
- ZnFree(cv->shape.contours[index].controls);
- }
- for (j = index; j < cv->shape.num_contours; j++) {
- cv->shape.contours[j] = cv->shape.contours[j+1];
- }
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- break;
- }
-
- return cv->shape.num_contours;
-}
-
-
-/*
- **********************************************************************************
- *
- * 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(ZnItem item,
- ZnPoint *p,
- int *contour,
- int *vertex,
- int *o_vertex)
-{
- CurveItem cv = (CurveItem) item;
- unsigned int i, j, k, num_points;
- ZnPoint *points, po;
- ZnReal dist=1.0e40, new_dist, dist2;
- ZnTransfo t, inv;
-
- *contour = *vertex = *o_vertex = -1;
-
- if ((cv->line_width > 0) ||
- ISSET(cv->flags, FILLED_OK) ||
- ISSET(cv->flags, MARKER_OK)) {
-
- /*
- * Get the point in the item coordinate space.
- */
- ZnITEM.GetItemTransform(item, &t);
- ZnTransfoInvert(&t, &inv);
- ZnTransformPoint(&inv, p, &po);
-
- /*
- * Check all contours.
- */
- for (i = 0; i < cv->shape.num_contours; i++) {
- points = cv->shape.contours[i].points;
- num_points = cv->shape.contours[i].num_points;
- for (j = 0; j < num_points; j++) {
- new_dist = hypot(points[j].x - po.x, points[j].y - po.y);
- if (new_dist < dist) {
- dist = new_dist;
- *contour = i;
- *vertex = j;
- }
- }
- /*
- * If the closest vertex is in the current contour update
- * the opposite vertex.
- */
- if (i == (unsigned int) *contour) {
- j = (*vertex+1) % num_points;
- new_dist = ZnLineToPointDist(&points[*vertex], &points[j], &po, NULL);
- k = ((unsigned int)(*vertex-1)) % num_points;
- dist2 = ZnLineToPointDist(&points[*vertex], &points[k], &po, NULL);
- if (dist2 < new_dist) {
- *o_vertex = k;
- }
- else {
- *o_vertex = j;
- }
- }
- }
- }
-}
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnBBox *bbox = &item->item_bounding_box;
-
- ZnOrigin2Anchor(&bbox->orig,
- bbox->corner.x - bbox->orig.x,
- bbox->corner.y - bbox->orig.y,
- anchor, p);
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct CURVE_ITEM_CLASS = {
- "curve",
- sizeof(CurveItemStruct),
- cv_attrs,
- 0, /* num_parts */
- 0, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- GetContours,
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- Contour,
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- PickVertex, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnCurve = (ZnItemClassId) &CURVE_ITEM_CLASS;
diff --git a/generic/Draw.c b/generic/Draw.c
deleted file mode 100644
index 3c0a37c..0000000
--- a/generic/Draw.c
+++ /dev/null
@@ -1,2245 +0,0 @@
-/*
- * Draw.c -- Implementation of common drawing routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Sat Dec 10 12:51:30 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-/*
- **********************************************************************************
- *
- * The algorihms used to draw the arrows, to do the 3d effects and to
- * smooth the polygons are adapted from Tk.
- *
- **********************************************************************************
- */
-
-#include "Types.h"
-#include "Draw.h"
-#include "Geo.h"
-#include "List.h"
-#include "WidgetInfo.h"
-#include "Image.h"
-#include "tkZinc.h"
-
-#include <math.h>
-#include <stdarg.h>
-
-
-#define POLYGON_RELIEF_DRAW 0
-#define POLYGON_RELIEF_RENDER 1
-#define POLYGON_RELIEF_DIST 2
-#define POLYGON_RELIEF_BBOX 3
-#define POLYGON_RELIEF_IN_BBOX 4
-
-#define TOP_CONTRAST 13
-#define BOTTOM_CONTRAST 6
-#define MAX_INTENSITY 65535
-
-#define ARROW_SHAPE_B 10.0
-#define ARROW_SHAPE_C 5.0
-#define OPEN_ARROW_SHAPE_A 4.0
-#define CLOSED_ARROW_SHAPE_A ARROW_SHAPE_B
-
-#define LIGHTNING_SHAPE_A_RATIO 10.0
-#define LIGHTNING_SHAPE_B_RATIO 8.0
-
-#define LIGHTNING_POINTS 4
-#define CORNER_POINTS 3
-#define DOUBLE_CORNER_POINTS 4
-#define STRAIGHT_POINTS 2
-
-
-/*
- **********************************************************************************
- *
- * ZnSetLineStyle --
- *
- **********************************************************************************
- */
-void
-ZnSetLineStyle(ZnWInfo *wi,
- ZnLineStyle line_style)
-{
- if (wi->render) {
-#ifdef GL
- switch (line_style) {
- case ZN_LINE_DASHED :
- glLineStipple(1, 0xF0F0);
- glEnable(GL_LINE_STIPPLE);
- break;
- case ZN_LINE_MIXED :
- glLineStipple(1, 0x27FF);
- glEnable(GL_LINE_STIPPLE);
- break;
- case ZN_LINE_DOTTED :
- glLineStipple(1, 0x18C3);
- glEnable(GL_LINE_STIPPLE);
- break;
- default:
- glDisable(GL_LINE_STIPPLE);
- }
-#endif
- }
- else {
- XGCValues values;
- static const char dashed[] = { 8 };
- static const char dotted[] = { 2, 5 };
- static const char mixed[] = { 8, 5, 2, 5 };
-
- values.line_style = LineOnOffDash;
- switch (line_style) {
- case ZN_LINE_DASHED :
- XSetDashes(wi->dpy, wi->gc, 0, dashed, 1);
- break;
- case ZN_LINE_MIXED :
- XSetDashes(wi->dpy, wi->gc, 0, mixed, 4);
- break;
- case ZN_LINE_DOTTED :
- XSetDashes(wi->dpy, wi->gc, 0, dotted, 2);
- break;
- default:
- values.line_style = LineSolid;
- break;
- }
- XChangeGC(wi->dpy, wi->gc, GCLineStyle, &values);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnLineShapePoints --
- * Compute the points describing the given line shape between point p1 and p2.
- * If bbox is non null, it is filled with the bounding box of the shape.
- *
- * For the time being this procedure handles straight lines, right and left
- * lightnings, right and left corners, right and left double corners..
- *
- *
- * Here are the parameters for lightnings:
- *
- * *******
- * ******* *
- * ****** *
- * ****** ******+ *
- * ****** ****** * *|
- * ****** ****** * * | LIGHTNING_SHAPE_A
- * ****** ****** * * |
- * ****** * * |
- * ..******.........................+.+.*........................******..
- * | * * ******
- * | * * ****** ******
- * | * * ****** ******
- * | * * ****** ******
- * | * ******* ******
- * | * ******
- * | * ******
- * | ********
- * | | | |
- * | |----| | LIGHTNING_SHAPE_B
- * | |
- * |--------------------------------| LENGTH / 2
- *
- **********************************************************************************
- */
-void
-ZnLineShapePoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim line_width,
- ZnLineShape shape,
- ZnBBox *bbox,
- ZnList to_points)
-{
- ZnPoint *points;
- unsigned int num_points, i;
-
- /*
- * Compute all line points according to shape.
- */
- if ((shape == ZN_LINE_LEFT_LIGHTNING) ||
- (shape == ZN_LINE_RIGHT_LIGHTNING)) {
- double alpha, theta;
- double length, length2;
- double shape_a, shape_b;
- double dx, dy;
- double temp;
-
- num_points = LIGHTNING_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[3] = *p2;
-
- dx = p2->x - p1->x;
- dy = p2->y - p1->y;
- length = hypot(dx, dy);
- shape_a = length/LIGHTNING_SHAPE_A_RATIO + line_width/2.0;
- shape_b = length/LIGHTNING_SHAPE_B_RATIO + line_width/2.0;
-
- if (shape == ZN_LINE_LEFT_LIGHTNING)
- alpha = atan2(shape_a, shape_b);
- else
- alpha = -atan2(shape_a, shape_b);
- length2 = hypot(shape_a, shape_b);
- theta = atan2(-dy, dx);
-
- dx = p1->x + dx/2;
- dy = p1->y + dy/2;
- temp = cos(theta + alpha) * length2;
- points[1].x = dx + temp;
- points[2].x = dx - temp;
- temp = sin(theta + alpha) * length2;
- points[1].y = dy - temp;
- points[2].y = dy + temp;
- }
- else if (shape == ZN_LINE_LEFT_CORNER ||
- shape == ZN_LINE_RIGHT_CORNER) {
- num_points = CORNER_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[2] = *p2;
-
- if (shape == ZN_LINE_LEFT_CORNER) {
- points[1].x = p1->x;
- points[1].y = p2->y;
- }
- else {
- points[1].x = p2->x;
- points[1].y = p1->y;
- }
- }
- else if (shape == ZN_LINE_DOUBLE_LEFT_CORNER ||
- shape == ZN_LINE_DOUBLE_RIGHT_CORNER) {
- int dx, dy;
-
- num_points = DOUBLE_CORNER_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[3] = *p2;
-
- if (shape == ZN_LINE_DOUBLE_LEFT_CORNER) {
- dy = (int) (p2->y - p1->y);
- points[1].x = p1->x;
- points[2].x = p2->x;
- points[1].y = points[2].y = p1->y + dy/2;
- }
- else {
- dx = (int) (p2->x - p1->x);
- points[1].x = points[2].x = p1->x + dx/2;
- points[1].y = p1->y;
- points[2].y = p2->y;
- }
- }
- else /* if (shape) == ZN_LINE_STRAIGHT) */ {
- num_points = STRAIGHT_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[1] = *p2;
- }
-
- /*
- * Fill in the bbox, if requested.
- */
- if (bbox) {
- ZnResetBBox(bbox);
- for (i = 0; i < num_points; i++) {
- ZnAddPointToBBox(bbox, points[i].x, points[i].y);
- }
-
- /* Enlarge to take line_width into account. */
- if (line_width > 1) {
- ZnDim lw_2 = (line_width+1)/2;
-
- bbox->orig.x -= lw_2;
- bbox->orig.y -= lw_2;
- bbox->corner.x += lw_2;
- bbox->corner.y += lw_2;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawLineShape --
- * Draw a line given the points describing its path. It is designed to work
- * with GetLineShape albeit it does fairly trivial things. In the future some
- * shapes might need cooperation between the two and the clients will be ready
- * for that.
- *
- *
- **********************************************************************************
- */
-void
-ZnDrawLineShape(ZnWInfo *wi,
- ZnPoint *p,
- unsigned int num_p,
- ZnLineStyle line_style,
- int foreground_pixel,
- ZnDim line_width,
- ZnLineShape shape)
-{
- XPoint *xpoints;
- unsigned int i;
- XGCValues values;
-
- /*
- * Setup GC.
- */
- ZnSetLineStyle(wi, line_style);
- values.foreground = foreground_pixel;
- values.line_width = (line_width == 1) ? 0 : (int) line_width;
- values.fill_style = FillSolid;
- values.join_style = JoinRound;
- values.cap_style = CapRound;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
- ZnListAssertSize(ZnWorkXPoints, num_p);
- xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_p; i++) {
- xpoints[i].x = (short) p[i].x;
- xpoints[i].y = (short) p[i].y;
- }
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xpoints, (int) num_p, CoordModeOrigin);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetLineEnd --
- * Compute the points describing the given line end style at point p1 for
- * the line p1,p2. Point p1 is adjusted to fit the line end.
- * If bbox is non null, it is filled with the bounding box of the end.
- *
- * For the time being this procedure handles open/filled arrows.
- *
- * Here are the parameters describing arrows.
- *
- * * | ARROW_SHAPE_C
- * ** |
- * * ***************************
- * * *
- * * * +p1 +p2
- * | * |*
- * | * ***************************
- * | | **
- * | | *
- * | | |
- * |---| | ARROW_SHAPE_A
- * | |
- * |-------| ARROW_SHAPE_B
- *
- **********************************************************************************
- */
-void
-ZnGetLineEnd(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim line_width,
- int cap_style,
- ZnLineEnd end_style,
- ZnPoint *points)
-{
- ZnReal dx, dy, length, temp, backup;
- ZnReal frac_height, sin_theta, cos_theta;
- ZnReal vert_x, vert_y;
- ZnReal shape_a, shape_b, shape_c;
-
- if (end_style != NULL) {
- shape_a = end_style->shape_a + 0.001;
- shape_b = end_style->shape_b + 0.001;
- shape_c = end_style->shape_c + line_width/2.0 + 0.001;
-
- frac_height = (line_width/2.0) / shape_c;
- dx = p1->x - p2->x;
- dy = p1->y - p2->y;
- length = hypot(dx, dy);
- if (length == 0) {
- sin_theta = cos_theta = 0.0;
- }
- else {
- sin_theta = dy/length;
- cos_theta = dx/length;
- }
-
- if (cap_style != CapProjecting) {
- temp = frac_height;
- }
- else {
- temp = line_width / shape_c;
- }
- backup = temp * shape_b + shape_a * (1.0 - temp) / 2.0;
- points[0].x = points[5].x = p1->x + backup * cos_theta;
- points[0].y = points[5].y = p1->y + backup * sin_theta;
-
- vert_x = points[0].x - shape_a*cos_theta;
- vert_y = points[0].y - shape_a*sin_theta;
- temp = shape_c*sin_theta;
- points[1].x = ZnNearestInt(points[0].x - shape_b*cos_theta + temp);
- points[4].x = ZnNearestInt(points[1].x - 2*temp);
- temp = shape_c*cos_theta;
- points[1].y = ZnNearestInt(points[0].y - shape_b*sin_theta - temp);
- points[4].y = ZnNearestInt(points[1].y + 2*temp);
- points[2].x = ZnNearestInt(points[1].x*frac_height + vert_x*(1.0-frac_height));
- points[2].y = ZnNearestInt(points[1].y*frac_height + vert_y*(1.0-frac_height));
- points[3].x = ZnNearestInt(points[4].x*frac_height + vert_x*(1.0-frac_height));
- points[3].y = ZnNearestInt(points[4].y*frac_height + vert_y*(1.0-frac_height));
- }
-}
-
-static ZnReal
-SegmentPosInRelief(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- int light_angle)
-{
- ZnReal angle, angle_step, origin, position;
- int num_colors, color_index;
-
- num_colors = ZN_RELIEF_STEPS*2+1;
- angle_step = M_PI / (num_colors-1);
- origin = -(ZnDegRad(light_angle))-(angle_step/2.0);
- if (relief == ZN_RELIEF_SUNKEN) {
- origin += M_PI;
- }
-
- angle = ZnProjectionToAngle(y1 - y2, x2 - x1) + M_PI - origin;
- while (angle < 0.0) {
- angle += 2*M_PI;
- }
- while (angle > 2*M_PI) {
- angle -= 2*M_PI;
- }
-
- color_index = (int) (angle/angle_step);
- if (color_index > num_colors-1) {
- color_index = 2*(num_colors-1)-color_index;
- }
- if ((color_index < 0) || (color_index >= num_colors)) {
- fprintf(stderr, "Color index out of gradient (should not happen).\n");
- if (color_index < 0) {
- color_index = 0;
- }
- if (color_index >= num_colors) {
- color_index = num_colors-1;
- }
- }
- position = 100*color_index/num_colors;
- /*printf("position %g, angle %g(%g), origin %g\n",
- position,
- RadianToDegrees(angle),
- angle,
- RadianToDegrees(origin));*/
- return position;
-}
-
-/*
- * ReliefColorOfSegment --
- * ReliefPixelOfSegment --
- */
-static XColor *
-ReliefColorOfSegment(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- int light_angle)
-{
- return ZnGetGradientColor(gradient,
- SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle),
- NULL);
-}
-
-static int
-ReliefPixelOfSegment(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- int light_angle)
-{
- return ZnGetGradientPixel(gradient,
- SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle));
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawRectangleRelief --
- * Draw the bevels inside bbox.
- *
- **********************************************************************************
- */
-void
-ZnDrawRectangleRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- XRectangle *bbox,
- ZnDim line_width)
-{
- XPoint bevel[4];
-
- /*
- * If we haven't enough space to draw, exit.
- */
- if ((bbox->width < 2*line_width) || (bbox->height < 2*line_width)) {
- return;
- }
-
- /*
- * Grooves and ridges are drawn with two recursives calls with
- * half the width of the original one.
- */
- if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
- ZnDim new_line_width;
- unsigned int offset;
- XRectangle internal_bbox;
-
- new_line_width = line_width/2.0;
- offset = (unsigned) (line_width - new_line_width);
- ZnDrawRectangleRelief(wi,
- (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED),
- gradient, bbox, new_line_width);
- internal_bbox = *bbox;
- internal_bbox.x += offset;
- internal_bbox.y += offset;
- internal_bbox.width -= offset*2;
- internal_bbox.height -= offset*2;
- ZnDrawRectangleRelief(wi,
- (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN),
- gradient, &internal_bbox, new_line_width);
- return;
- }
-
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
-
- bevel[0].x = bbox->x;
- bevel[0].y = bevel[1].y = bbox->y;
- bevel[1].x = bbox->x + bbox->width;
- bevel[2].y = bevel[3].y = bbox->y + (short) line_width;
- bevel[2].x = bevel[1].x - (short) line_width;
- bevel[3].x = bevel[0].x + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].y += bbox->height;
- bevel[2].y = bevel[1].y - (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].x -= bbox->width;
- bevel[2].x = bevel[1].x + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].x = bbox->x;
- bevel[1].y = bbox->y;
- bevel[2].x = bevel[3].x;
- bevel[2].y = bbox->y + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-}
-
-
-typedef struct {
- ZnWInfo *wi;
- ZnPoint *pp;
- ZnPoint *p0;
- ZnPoint *p1;
- double dist;
- ZnBBox *bbox;
- ZnReliefStyle relief;
- ZnGradient *gradient;
- unsigned short alpha;
- ZnBool smooth;
- int result;
- int count;
- ZnBool toggle;
-} PolygonData;
-
-static void
-DoPolygon(ZnPoint *p,
- unsigned int num_points,
- ZnDim line_width,
- ZnBool (*cb)(ZnPoint *bevels, PolygonData *pd),
- PolygonData *pd)
-{
- int i;
- unsigned int processed_points;
- ZnPoint *p1, *p11=NULL, *p2;
- ZnPoint pp1, pp2, new_pp1, new_pp2;
- ZnPoint perp, c, shift1, shift2;
- ZnPoint bevel_points[4];
- ZnBool folded, closed, colinear;
- ZnReal dx, dy;
-
- if (num_points < 2) {
- return;
- }
-
- /*
- * If the polygon is closed (last point is the same as first) open it by
- * dropping the last point. The algorithm closes the path automatically.
- * We remember this to decide if we draw the last bevel or not and if we
- * need to generate ends perpendicular to the path..
- */
- closed = False;
- if ((p->x == p[num_points-1].x) && (p->y == p[num_points-1].y)) {
- closed = True;
- num_points--;
- }
- /*printf("num_points=%d(%s)\n", num_points, closed?"closed":"");*/
-
- /*
- * We loop on all vertices of the polygon.
- * At each step we try to compute the corresponding border
- * corner `corner'. Then we build a polygon for the bevel.
- * Things look like this:
- *
- * bevel[1] /
- * * /
- * | /
- * | /
- * pp1 * * p[i-1]
- * | | bevel[0]
- * | |
- * | |
- * | | bevel[3]
- * | | p[i]
- * | | p1 p2
- * pp2 * *--------------------*
- * |
- * |
- * corner *----*--------------------*
- * bevel[2] new_pp1 new_pp2
- *
- * pp1 and pp2 are the ends of a segment // to p1 p2 at line_width
- * from it. These points are *NOT* necessarily on the perpendicular
- * going through p1 or p2.
- * This loop needs a bootstrap phase of two iterations (i.e we need to
- * process two points). This is why we start at the point before the last
- * and then wrap to the first point.
- * The algorithm discards any duplicate contiguous points.
- * It makes a special case if two consecutives edges are folded:
- *
- * bevel[1] pp1 pp2 a bevel[2]
- * *-----------*--------------*----------*
- * \
- * \
- * p[i-1] \ bevel[3]
- * *--------*-------------------------*---* corner
- * bevel[0] p2 p1 /
- * /
- * /
- * ----------*-----------*-------------*
- * new_pp1 new_pp2 c
- *
- * In such a case we need to compute a, c, corner from pp1, pp2, new_pp1
- * and new_pp2. We compute the perpendicular to p1,p2 through p1, intersect
- * it with pp1,pp2 to obtain a, intersect it with new_pp1, new_pp2 to
- * obtain c, shift a,c and intersect it with p1,p2 to obtain corner.
- *
- */
-
- processed_points = 0;
- if (!closed) {
- i = 0;
- p1 = p;
- }
- else {
- i = -2;
- p1 = &p[num_points-2];
- }
-
- for (p2 = p1+1; i < (int) num_points; i++, p2++) {
- /*
- * When it is time to wrap, do it
- */
- if ((i == -1) || (i == (int) num_points-1)) {
- p2 = p;
- }
- /*
- * Skip over close vertices.
- */
- dx = p2->x - p1->x;
- dy = p2->y - p1->y;
- if ((ABS(dx) < 1.0) && (ABS(dy) < 1.0)) {
- continue;
- }
-
- ZnShiftLine(p1, p2, line_width, &new_pp1, &new_pp2);
- bevel_points[3] = *p1;
- folded = False;
- colinear = False;
- /*
- * The first two cases are for `open' polygons. We compute
- * a bevel closure that is perpendicular to the path.
- */
- if ((processed_points == 0) && !closed) {
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
- }
- else if ((processed_points == num_points-1) && !closed) {
- perp.x = p1->x + (p11->y - p1->y);
- perp.y = p1->y - (p11->x - p1->x);
- ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);
- }
- else if (processed_points >= 1) {
- ZnReal dotp, dist, odx, ody;
-
- /*
- * The dot product of the two faces tell if the are
- * folded or colinear. The
- */
- odx = p11->x - p1->x;
- ody = p11->y - p1->y;
- dotp = odx*dx + ody*dy;
- dist = ZnLineToPointDist(p11, p2, p1, NULL);
- if ((dist < 4.0) && (dotp <= 0)) {
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
- colinear = True;
- }
- else {
- folded = !ZnIntersectLines(&new_pp1, &new_pp2, &pp1, &pp2, &bevel_points[2]);
- /*printf("new_pp1 %g@%g, new_pp2 %g@%g, pp1 %g@%g, pp2 %g@%g, inter %g@%g\n",
- new_pp1.x, new_pp1.y, new_pp2.x, new_pp2.y,
- pp1.x, pp1.y, pp2.x, pp2.y,
- bevel_points[2].x, bevel_points[2].y);*/
- folded = folded && (dotp < 0);
- if (folded) {
- /*printf("DoPolygonRelief: folded edges detected, %g@%g, %g@%g, %g@%g, %g@%g\n",
- pp1.x, pp1.y, pp2.x, pp2.y, new_pp1.x, new_pp1.y,
- new_pp2.x, new_pp2.y);*/
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &c);
- ZnShiftLine(p1, &perp, line_width, &shift1, &shift2);
- ZnIntersectLines(p1, p2, &shift1, &shift2, &bevel_points[3]);
- }
- }
- }
-
- if ((processed_points >= 2) || (!closed && (processed_points == 1))) {
- if ((processed_points == num_points-1) && !closed) {
- pd->p0 = pd->p1 = NULL;
- }
- else {
- pd->p0 = p1;
- pd->p1 = p2;
- }
- if ((*cb)(bevel_points, pd)) {
- return;
- }
- }
-
- p11 = p1;
- p1 = p2;
- pp1 = new_pp1;
- pp2 = new_pp2;
- bevel_points[0] = bevel_points[3];
- if (folded) {
- bevel_points[1] = c;
- }
- else if ((processed_points >= 1) || !closed) {
- bevel_points[1] = bevel_points[2];
- }
-
- processed_points++;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetPolygonReliefBBox --
- * Returns the bevelled polygon bounding box.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonBBoxCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- int i;
-
- for (i = 0; i < 4; i++) {
- ZnAddPointToBBox(pd->bbox, bevels[i].x, bevels[i].y);
- }
- return 0;
-}
-
-void
-ZnGetPolygonReliefBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnBBox *bbox)
-{
- PolygonData pd;
-
- pd.bbox = bbox;
- ZnResetBBox(bbox);
- DoPolygon(points, num_points, line_width, PolygonBBoxCB, &pd);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPolygonReliefInBBox --
- * Returns (-1) if the relief is entirely outside the bbox, (1) if it is
- * entirely inside or (0) if in between
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonInBBoxCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- if (pd->count == 0) {
- pd->count++;
- pd->result = ZnPolygonInBBox(bevels, 4, pd->bbox, NULL);
- if (pd->result == 0) {
- return 1;
- }
- }
- else {
- if (ZnPolygonInBBox(bevels, 4, pd->bbox, NULL) != pd->result) {
- pd->result = 0;
- return 1;
- }
- }
- return 0;
-}
-
-int
-ZnPolygonReliefInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnBBox *area)
-{
- PolygonData pd;
-
- pd.bbox = area;
- pd.count = 0;
-
- DoPolygon(points, num_points, line_width, PolygonInBBoxCB, &pd);
-
- return pd.result;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPolygonReliefToPointDist --
- * Returns the distance between the given point and
- * the bevelled polygon.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonDistCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- double new_dist;
-
- new_dist = ZnPolygonToPointDist(bevels, 4, pd->pp);
- if (new_dist < 0.0) {
- new_dist = 0.0;
- }
- if (new_dist < pd->dist) {
- pd->dist = new_dist;
- }
- return 0;
-}
-
-double
-ZnPolygonReliefToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnPoint *pp)
-{
- PolygonData pd;
-
- pd.dist = 1.0e40;
- pd.pp = pp;
- DoPolygon(points, num_points, line_width, PolygonDistCB, &pd);
-
- return pd.dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawPolygonRelief --
- * Draw the bevels around path.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonDrawCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- ZnWInfo *wi = pd->wi;
- XPoint bevel_xpoints[5];
- XGCValues values;
- int j;
-
- values.foreground = ReliefPixelOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- pd->relief, pd->gradient,
- pd->wi->light_angle);
-
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
-
- for (j = 0; j < 4; j++) {
- bevel_xpoints[j].x = ZnNearestInt(bevels[j].x);
- bevel_xpoints[j].y = ZnNearestInt(bevels[j].y);
- }
-
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4,
- Convex, CoordModeOrigin);
-
- return 0;
-}
-
-void
-ZnDrawPolygonRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width)
-{
- PolygonData pd;
-
- pd.wi = wi;
- pd.gradient = gradient;
-
- /*
- * Grooves and ridges are drawn with two calls. The first
- * with the original width, the second with half the width.
- */
- if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
- pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN;
- DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
- pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED;
- DoPolygon(points, num_points, line_width/2, PolygonDrawCB, &pd);
- }
- else {
- pd.relief = relief;
- DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
- }
-}
-
-/*
- **********************************************************************************
- *
- * ZnRenderPolygonRelief --
- * Draw the bevels around path using alpha enabled rendering.
- *
- **********************************************************************************
- */
-#ifdef GL
-static ZnBool
-PolygonRenderCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- int i;
- ZnPoint p[6];
- XColor *c[8];
- XColor *color = ZnGetGradientColor(pd->gradient, 51.0, NULL);
- ZnReliefStyle relief, int_relief;
- ZnBool two_faces, round, rule;
-
- rule = pd->relief & ZN_RELIEF_RULE;
- round = pd->relief & ZN_RELIEF_ROUND;
- two_faces = pd->relief & ZN_RELIEF_TWO_FACES;
- relief = pd->relief & ZN_RELIEF_MASK;
- for (i = 0; i < 4; i++) {
- p[i].x = ZnNearestInt(bevels[i].x);
- p[i].y = ZnNearestInt(bevels[i].y);
- }
-
- if (two_faces) {
- p[4].x = (p[0].x+p[1].x)/2;
- p[4].y = (p[0].y+p[1].y)/2;
- p[5].x = (p[2].x+p[3].x)/2;
- p[5].y = (p[2].y+p[3].y)/2;
-
- if (relief == ZN_RELIEF_SUNKEN) {
- int_relief = ZN_RELIEF_RAISED;
- }
- else {
- int_relief = ZN_RELIEF_SUNKEN;
- }
- c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- relief, pd->gradient,
- pd->wi->light_angle);
- c[4]=c[5]=c[6]=c[7] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- int_relief, pd->gradient,
- pd->wi->light_angle);
- if (pd->smooth && pd->p0) {
- c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- relief, pd->gradient,
- pd->wi->light_angle);
- c[6]=c[7] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- int_relief, pd->gradient,
- pd->wi->light_angle);
- }
- if (round) {
- if (!rule) {
- c[0]=c[3]=c[5]=c[6]=color;
- }
- else {
- c[1]=c[2]=c[4]=c[7]=color;
- }
- }
- glBegin(GL_QUADS);
- glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
- glVertex2d(p[0].x, p[0].y);
-
- glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
- glVertex2d(p[4].x, p[4].y);
-
- glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
- glVertex2d(p[5].x, p[5].y);
-
- glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
- glVertex2d(p[3].x, p[3].y);
-
- glColor4us(c[4]->red, c[4]->green, c[4]->blue, pd->alpha);
- glVertex2d(p[4].x, p[4].y);
-
- glColor4us(c[5]->red, c[5]->green, c[5]->blue, pd->alpha);
- glVertex2d(p[1].x, p[1].y);
-
- glColor4us(c[6]->red, c[6]->green, c[6]->blue, pd->alpha);
- glVertex2d(p[2].x, p[2].y);
-
- glColor4us(c[7]->red, c[7]->green, c[7]->blue, pd->alpha);
- glVertex2d(p[5].x, p[5].y);
- glEnd();
- }
- else { /* Single face */
- c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- relief, pd->gradient,
- pd->wi->light_angle);
- if (pd->smooth && pd->p0) {
- c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- relief, pd->gradient,
- pd->wi->light_angle);
- }
- if (round) {
- c[1]=c[2] = color;
- }
- glBegin(GL_QUADS);
- glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
- glVertex2d(p[0].x, p[0].y);
- glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
- glVertex2d(p[1].x, p[1].y);
- glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
- glVertex2d(p[2].x, p[2].y);
- glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
- glVertex2d(p[3].x, p[3].y);
- glEnd();
- }
-
- return 0;
-}
-
-void
-ZnRenderPolygonRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- ZnBool smooth,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width)
-{
- PolygonData pd;
-
- pd.wi = wi;
- pd.gradient = gradient;
- ZnGetGradientColor(gradient, 0.0, &pd.alpha);
- pd.alpha = ZnComposeAlpha(pd.alpha, wi->alpha);
- pd.smooth = smooth;
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- pd.relief = relief;
- pd.count = 0;
-
- DoPolygon(points, num_points, line_width, PolygonRenderCB, &pd);
-}
-
-void
-ZnRenderPolyline(ZnWInfo *wi,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnLineStyle line_style,
- int cap_style,
- int join_style,
- ZnLineEnd first_end,
- ZnLineEnd last_end,
- ZnGradient *gradient)
-{
- int num_clips = ZnListSize(wi->clip_stack);
- ZnPoint end_points[ZN_LINE_END_POINTS];
- ZnBool need_rcaps, thin, closed, transparent;
- int pass, num_passes, i, k, m;
- ZnPoint c1, c2;
- XColor *color;
- unsigned short alpha;
- ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
-
- /*
- * The code below draws curves thiner than the min
- * of GL_SMOOTH_LINE_WIDTH_RANGE and GL_SMOOTH_POINT_SIZE_RANGE
- * with a mix of anti-aliased lines and points. The curves that
- * are thicker are drawn using regular polygons.
- * BUG: The joints are drawn only rounded.
- * The caps can be either round or butt (but not projecting).
- */
- thin = ((line_width <= ce->max_line_width) &&
- (line_width <= ce->max_point_width));
- closed = (points->x == points[num_points-1].x) && (points->y == points[num_points-1].y);
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- ZnSetLineStyle(wi, line_style);
- glLineWidth((GLfloat) line_width);
- /*
- * Do not use joints under this transparency value.
- */
- transparent = alpha < (65535 * 0.8);
- if (thin && transparent) {
- /*
- * This makes a special case for transparent lines.
- * In this case we need to avoid drawing twice a
- * single pixel. To achieve this we use the stencil
- * buffer to protect already drawn pixels, unfortunately
- * using antialiasing write in the stencil even if
- * the pixel area is not fully covered resulting in
- * a crack that can't be covered by points later on.
- * To handle this case we need to disable the stencil
- * which in turn result in erroneous alpha coverage.
- *
- * We have chosen to drawn transparent lines with a
- * correct coverage but NOT antialiased.
- */
- glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
- glDisable(GL_LINE_SMOOTH);
- }
- else {
- glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
- }
-
- num_passes = 1;
- if (transparent) {
- num_passes = 2;
- }
-
- for (pass = 0; pass < num_passes; pass++) {
- if (transparent) {
- if (pass == 0) {
- ZnGlStartClip(num_clips, True);
- }
- else {
- ZnGlRestoreStencil(num_clips, False);
- }
- }
- if (first_end) {
- ZnGetLineEnd(&points[0], &points[1], line_width, cap_style,
- first_end, end_points);
- glBegin(GL_TRIANGLE_FAN);
- for (m = 0; m < ZN_LINE_END_POINTS; m++) {
- glVertex2d(end_points[m].x, end_points[m].y);
- }
- glEnd();
- }
- if (last_end) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2],
- line_width, cap_style, last_end, end_points);
- glBegin(GL_TRIANGLE_FAN);
- for (m = 0; m < ZN_LINE_END_POINTS; m++) {
- glVertex2d(end_points[m].x, end_points[m].y);
- }
- glEnd();
- }
- if (thin) {
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < (int) num_points; i++) {
- glVertex2d(points[i].x, points[i].y);
- }
- glEnd();
- }
- else {
- glBegin(GL_QUADS);
- for (i = 0; i < (int) num_points-1; i++) {
- ZnGetButtPoints(&points[i+1], &points[i], line_width, False, &c1, &c2);
- glVertex2d(c1.x, c1.y);
- glVertex2d(c2.x, c2.y);
- ZnGetButtPoints(&points[i], &points[i+1], line_width, False, &c1, &c2);
- glVertex2d(c1.x, c1.y);
- glVertex2d(c2.x, c2.y);
- }
- glEnd();
- }
-
- /* if (pass == 0) {
- ZnGlRenderClipped();
- }
- else {
- ZnGlEndClip(num_clips);
- break;
- }*/
- need_rcaps = ((line_width > 1) && (cap_style == CapRound));
- i = 0;
- k = num_points;
- if (closed) {
- k--;
- }
- if (!need_rcaps || first_end) {
- i++;
- }
- if ((!need_rcaps && !closed) || last_end) {
- k--;
- }
-
- if (thin) {
- glBegin(GL_POINTS);
- for ( ; i < k; i++) {
- glVertex2d(points[i].x, points[i].y);
- }
- glEnd();
- }
- else {
- int num_cpoints;
- ZnReal lw_2 = line_width / 2.0;
- ZnPoint *cpoints = ZnGetCirclePoints(3, ZN_CIRCLE_COARSE,
- 0.0, 2*M_PI, &num_cpoints, NULL);
-
- for ( ; i < k; i++) {
- glBegin(GL_TRIANGLE_FAN);
- glVertex2d(points[i].x, points[i].y);
- for (m = 0; m < num_cpoints; m++) {
- glVertex2d(points[i].x + cpoints[m].x*lw_2,
- points[i].y + cpoints[m].y*lw_2);
- }
- glEnd();
- }
- }
- }
-
- ZnGlEndClip(num_clips);
- if (thin) {
- glEnable(GL_LINE_SMOOTH);
- }
-}
-
-
-void
-ZnRenderIcon(ZnWInfo *wi,
- ZnImage image,
- ZnGradient *gradient,
- ZnPoint *origin,
- ZnBool modulate)
-{
- ZnPoint p[4];
- int width, height;
-
- ZnSizeOfImage(image, &width, &height);
- p[0] = *origin;
- p[1].x = origin->x;
- p[1].y = origin->y + height;
- p[2].x = origin->x + width;
- p[2].y = p[1].y;
- p[3].x = p[2].x;
- p[3].y = origin->y;
- ZnRenderImage(wi, image, gradient, p, modulate);
-}
-
-
-void
-ZnRenderImage(ZnWInfo *wi,
- ZnImage image,
- ZnGradient *gradient,
- ZnPoint *quad,
- ZnBool modulate)
-{
- XColor *color;
- unsigned short alpha;
- ZnReal t, s;
- GLuint texobj;
-
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- texobj = ZnImageTex(image, &t, &s);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texobj);
- if (modulate) {
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- else {
- glColor4us(65535, 65535, 65535, alpha);
- }
- glBegin(GL_QUADS);
- glTexCoord2d(0.0, 0.0);
- glVertex2d(quad[0].x, quad[0].y);
- glTexCoord2d(0.0, t);
- glVertex2d(quad[1].x, quad[1].y);
- glTexCoord2d(s, t);
- glVertex2d(quad[2].x, quad[2].y);
- glTexCoord2d(s, 0.0);
- glVertex2d(quad[3].x, quad[3].y);
- glEnd();
- glDisable(GL_TEXTURE_2D);
-}
-
-void
-ZnRenderTile(ZnWInfo *wi,
- ZnImage tile,
- ZnGradient *gradient,
- void (*cb)(void *),
- void *closure,
- ZnPoint *quad) /* Right now it's a ZnBBox */
-{
- ZnReal x, y, nx, ny, lx, ly, s, t, tiles, tilet;
- int width, height, num_clips = ZnListSize(wi->clip_stack);
- unsigned short alpha;
- GLuint texobj;
- XColor *color;
-
- if (gradient) {
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- }
- else {
- color = NULL;
- alpha = ZnComposeAlpha(100, wi->alpha);
- }
-
- if (cb) {
- /*
- * Setup the stencil buffer with the shape to be drawn.
- */
- ZnGlStartClip(num_clips, False);
-
- (*cb)(closure);
- ZnGlRestoreStencil(num_clips, True);
- }
-
- /*
- * Then texture map the quad through the shape.
- * The rectangle is drawn using quads, each
- * quad matching the size of the texture tile.
- */
- ZnSizeOfImage(tile, &width, &height);
- texobj = ZnImageTex(tile, &tilet, &tiles);
- glEnable(GL_TEXTURE_2D);
- if (color && ZnImageIsBitmap(tile)) {
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- else {
- glColor4us(65535, 65535, 65535, alpha);
- }
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, texobj);
-
- y = quad[0].y;
- lx = quad[1].x;
- ly = quad[1].y;
- glBegin(GL_QUADS);
- do {
- x = quad[0].x;
- t = 1.0;
- ny = y + height;
- if (ny > ly) {
- ny = ly;
- t = (ly - y) / (ZnReal) height;
- }
- t *= tilet;
- do {
- s = 1.0;
- nx = x + width;
- if (nx > lx) {
- nx = lx;
- s = (lx - x) / (ZnReal) width;
- }
- s *= tiles;
- glTexCoord2d(0.0, 0.0);
- glVertex2d(x, y);
- glTexCoord2d(0.0, t);
- glVertex2d(x, ny);
- glTexCoord2d(s, t);
- glVertex2d(nx, ny);
- glTexCoord2d(s, 0.0);
- glVertex2d(nx, y);
- x = nx;
- }
- while (x != lx);
- y = ny;
- }
- while (y != ly);
- glEnd();
-
- if (cb) {
- ZnGlEndClip(num_clips);
- }
- glDisable(GL_TEXTURE_2D);
-}
-
-
-static void
-ComputeAxialGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnReal angle,
- ZnPoint *grad_geo)
-{
- ZnTransfo *transfo1, *transfo2;
- ZnContour *c;
- ZnBBox bbox;
- ZnPoint *points, p[4];
- unsigned int i;
-
- transfo1 = ZnTransfoNew();
- transfo2 = ZnTransfoNew();
- ZnRotateDeg(transfo1, angle);
- ZnRotateDeg(transfo2, -angle);
- c = shape->contours;
- ZnResetBBox(&bbox);
- for (i = 0; i < shape->num_contours; i++, c++) {
- ZnListAssertSize(ZnWorkPoints, c->num_points);
- points = ZnListArray(ZnWorkPoints);
- ZnTransformPoints(transfo1, c->points, points, c->num_points);
- ZnAddPointsToBBox(&bbox, points, c->num_points);
- }
- bbox.orig.x--;
- bbox.orig.y--;
- bbox.corner.x++;
- bbox.corner.y++;
- p[0] = bbox.orig;
- p[2] = bbox.corner;
- p[1].x = p[2].x;
- p[1].y = p[0].y;
- p[3].x = p[0].x;
- p[3].y = p[2].y;
- ZnTransfoSetIdentity(transfo1);
- ZnTransfoCompose(transfo1, transfo2, wi->current_transfo);
- ZnTransformPoints(transfo1, p, grad_geo, 4);
- ZnTransfoFree(transfo1);
- ZnTransfoFree(transfo2);
-}
-
-static void
-ComputeCircularGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnBool oval,
- ZnPoint *focal_pp, /* in percent of bbox */
- ZnReal angle,
- ZnPoint *grad_geo)
-{
- ZnReal dist, new, x, y, ff;
- ZnBBox bbox;
- ZnContour *c;
- ZnPoint offset, radius, focal_point;
- ZnPoint *points;
- ZnTransfo t1;
- unsigned int i, j;
-
- /*
- * Compute the shape bbox (which should be in the item space).
- */
- ZnResetBBox(&bbox);
- c = shape->contours;
- dist = 0.0;
- for (j = 0; j < shape->num_contours; j++, c++) {
- ZnAddPointsToBBox(&bbox, c->points, c->num_points);
- }
-
- /*
- * Find the gradient focal point in the item space.
- * The excursion of the focal point outside the item
- * bbox is clamped to avoid distorsions that take
- * place due to the rather simple algorithm used to
- * compute the maximum radius of the gradient.
- */
- focal_pp->x = fmod(focal_pp->x, 500.0);
- focal_pp->y = fmod(focal_pp->y, 500.0);
- offset.x = focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
- offset.y = focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
- focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + offset.x;
- focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + offset.y;
-
- /*
- * Find the max distance from the focal point.
- */
- if (oval) {
- /*
- * radius.x and radius.y are the shape radiuses.
- * ff is the distance from the bbox center to
- * the focal point.
- */
- radius.x = (bbox.corner.x-bbox.orig.x)/2;
- radius.y = (bbox.corner.y-bbox.orig.y)/2;
- ff = sqrt(offset.x*offset.x + offset.y*offset.y);
- /*
- * Compute the farthest point from the focal point
- * on a unit circle, then map it to the oval and
- * compute the distance between the two points.
- */
- if (ff > PRECISION_LIMIT) {
- x = offset.x/ff;
- y = offset.y/ff;
- x *= radius.x;
- y *= radius.y;
- x = x + offset.x;
- y = y + offset.y;
- }
- else {
- x = 0;
- y = MAX(radius.x, radius.y);
- }
- dist = x*x + y*y;
- }
- else {
- /*
- * Use the given shape
- */
- c = shape->contours;
- for (j = 0; j < shape->num_contours; j++, c++) {
- for (i = 0, points = c->points; i < c->num_points; i++, points++) {
- x = points->x - focal_point.x;
- y = points->y - focal_point.y;
- new = x*x+y*y;
- if (new > dist) {
- dist = new;
- }
- }
- }
- }
-
- /*
- * Create a transform to map a unit circle to another one that
- * could fill the item when centered at the focal point.
- */
- dist = sqrt(dist); /* Max radius plus a fuzz factor */
- ZnTransfoSetIdentity(&t1);
- ZnScale(&t1, dist, dist);
- ZnRotateDeg(&t1, -angle);
-
- /*
- * Then, center the oval on the focal point.
- */
- ZnTranslate(&t1, focal_point.x, focal_point.y, False);
- /*
- * Last, compose with the current transform.
- */
- ZnTransfoCompose((ZnTransfo *) grad_geo, &t1, wi->current_transfo);
-}
-
-static void
-ComputePathGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnPoint *focal_pp, /* in percent of the bbox */
- ZnPoint *grad_geo)
-{
- ZnBBox bbox;
- ZnContour *c;
- ZnPoint focal_point;
- unsigned int j;
-
- /*
- * Compute the shape bbox (which should be in the item space).
- */
- ZnResetBBox(&bbox);
- c = shape->contours;
- for (j = 0; j < shape->num_contours; j++, c++) {
- ZnAddPointsToBBox(&bbox, c->points, c->num_points);
- }
-
- /*
- * Find the gradient center in the item space.
- */
- focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
- focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
- /*
- * Then convert it to device space.
- */
- ZnTransformPoint(wi->current_transfo, &focal_point, &grad_geo[0]);
-}
-
-void
-ZnComputeGradient(ZnGradient *grad,
- ZnWInfo *wi,
- ZnPoly *shape,
- ZnPoint *grad_geo)
-{
- switch (grad->type) {
- case ZN_AXIAL_GRADIENT:
- ComputeAxialGradient(wi, shape, grad->angle, grad_geo);
- break;
- case ZN_RADIAL_GRADIENT:
- case ZN_CONICAL_GRADIENT:
- ComputeCircularGradient(wi, shape, False, &grad->p, grad->angle, grad_geo);
- break;
- case ZN_PATH_GRADIENT:
- ComputePathGradient(wi, shape, &grad->p, grad_geo);
- break;
- }
-}
-
-void
-ZnRenderGradient(ZnWInfo *wi,
- ZnGradient *gradient, /* The gradient to be drawn (static
- * parameters). */
- void (*cb)(void *), /* A callback called to clip the shape
- * containing the gradient. */
- void *closure, /* The callback parameter. */
- ZnPoint *quad, /* The gradient geometric parameters
- * (dynamic). */
- ZnPoly *poly /* Used only by ZN_PATH_GRADIENT */
- )
-{
- unsigned short alpha, alpha2;
- int angle;
- unsigned int i, j;
- int type = gradient->type;
- XColor *color;
- ZnPoint dposa, dposb, dposc, dposd;
- ZnPoint p, dcontrol;
- ZnReal npos, pos, control;
- unsigned int num_clips = ZnListSize(wi->clip_stack);
- ZnPoint iquad[4];
-
- if (!cb && (type == ZN_AXIAL_GRADIENT)) { /* Render an aligned
- * axial gradient in the quad */
- angle = gradient->angle;
- /*
- * Adjust the quad for 90 180 and 270 degrees axial
- * gradients. Other angles not supported.
- */
- switch (angle) {
- case 90:
- iquad[0] = quad[3];
- iquad[3] = quad[2];
- iquad[2] = quad[1];
- iquad[1] = quad[0];
- quad = iquad;
- break;
- case 180:
- iquad[0] = quad[2];
- iquad[3] = quad[1];
- iquad[2] = quad[0];
- iquad[1] = quad[3];
- quad = iquad;
- break;
- case 270:
- iquad[0] = quad[1];
- iquad[3] = quad[0];
- iquad[2] = quad[3];
- iquad[1] = quad[2];
- quad = iquad;
- break;
- }
- }
-
- if (cb) {
- /*
- * Draw the gradient shape in the stencil using the provided
- * callback (clipping).
- */
- ZnGlStartClip(num_clips, False);
- (*cb)(closure);
- ZnGlRestoreStencil(num_clips, True);
- }
-
- if (type == ZN_AXIAL_GRADIENT) {
- /*
- * Then fill the axial gradient using the provided
- * quad and colors. The stencil will be restored
- * to its previous state in the process.
- */
- glBegin(GL_QUAD_STRIP);
- for (i = 0; i < gradient->num_actual_colors; i++) {
- color = gradient->actual_colors[i].rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[i].alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- pos = gradient->actual_colors[i].position;
- control = gradient->actual_colors[i].control;
- dposa.x = (quad[1].x - quad[0].x)*pos/100.0;
- dposa.y = (quad[1].y - quad[0].y)*pos/100.0;
- p.x = quad[0].x + dposa.x;
- p.y = quad[0].y + dposa.y;
- glVertex2d(p.x, p.y);
-
- dposb.x = (quad[2].x - quad[3].x)*pos/100.0;
- dposb.y = (quad[2].y - quad[3].y)*pos/100.0;
- p.x = quad[3].x + dposb.x;
- p.y = quad[3].y + dposb.y;
- glVertex2d(p.x, p.y);
-
- if ((control != 50.0) && (i != gradient->num_actual_colors-1)) {
- color = gradient->actual_colors[i].mid_rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[i].mid_alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- npos = gradient->actual_colors[i+1].position;
- dposc.x = (quad[1].x - quad[0].x)*npos/100.0;
- dposc.y = (quad[1].y - quad[0].y)*npos/100.0;
- dcontrol.x = (dposc.x - dposa.x)*control/100.0;
- dcontrol.y = (dposc.y - dposa.y)*control/100.0;
- p.x = quad[0].x + dposa.x + dcontrol.x;
- p.y = quad[0].y + dposa.y + dcontrol.y;
- glVertex2d(p.x, p.y);
-
- dposd.x = (quad[2].x - quad[3].x)*npos/100.0;
- dposd.y = (quad[2].y - quad[3].y)*npos/100.0;
- dcontrol.x = (dposd.x - dposb.x)*control/100.0;
- dcontrol.y = (dposd.y - dposb.y)*control/100.0;
- p.x = quad[3].x + dposb.x + dcontrol.x;
- p.y = quad[3].y + dposb.y + dcontrol.y;
- glVertex2d(p.x, p.y);
- }
-
- }
- glEnd();
- }
- else if (type == ZN_RADIAL_GRADIENT) {
- ZnReal x, y, position, position2, position3;
- unsigned int num_p;
- ZnPoint *genarc, *tarc, p, focalp;
- XColor *color2;
-
- genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINE, 0.0, 2*M_PI, &num_p, NULL);
- ZnListAssertSize(ZnWorkPoints, num_p);
- tarc = ZnListArray(ZnWorkPoints);
- ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
- p.x = p.y = 0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
-
- position = 0.0;
- color = gradient->actual_colors[0].rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
- control = gradient->actual_colors[0].control;
- for (j = 1; j < gradient->num_actual_colors; j++) {
- position2 = gradient->actual_colors[j].position/100.0;
- if ((control != 50) && (j != gradient->num_actual_colors-1)) {
- glBegin(GL_QUAD_STRIP);
- color2 = gradient->actual_colors[j-1].mid_rgb;
- alpha2 = ZnComposeAlpha(gradient->actual_colors[j-1].mid_alpha, wi->alpha);
- position3 = position + (position2-position)*control/100.0;
- for (i = 0; i < num_p; i++) {
- x = focalp.x + (tarc[i].x-focalp.x) * position;
- y = focalp.y + (tarc[i].y-focalp.y) * position;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(x, y);
- x = focalp.x + (tarc[i].x-focalp.x) * position3;
- y = focalp.y + (tarc[i].y-focalp.y) * position3;
- glColor4us(color2->red, color2->green, color2->blue, alpha);
- glVertex2d(x, y);
- }
- position = position3;
- color = color2;
- alpha = alpha2;
- glEnd();
- }
- glBegin(GL_QUAD_STRIP);
- color2 = gradient->actual_colors[j].rgb;
- alpha2 = ZnComposeAlpha(gradient->actual_colors[j].alpha, wi->alpha);
- for (i = 0; i < num_p; i++) {
- x = focalp.x + (tarc[i].x-focalp.x) * position;
- y = focalp.y + (tarc[i].y-focalp.y) * position;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(x, y);
- x = focalp.x + (tarc[i].x-focalp.x) * position2;
- y = focalp.y + (tarc[i].y-focalp.y) * position2;
- glColor4us(color2->red, color2->green, color2->blue, alpha2);
- glVertex2d(x, y);
- }
- glEnd();
- position = position2;
- color = color2;
- alpha = alpha2;
- control = gradient->actual_colors[j].control;
- }
- }
- else if (type == ZN_PATH_GRADIENT) {
- ZnPoint p, pp, p2, pp2, p3, pp3;
- unsigned int num_p, k, ii;
- ZnPoint *points;
- ZnReal position;
-
- for (k = 0; k < poly->num_contours; k++) {
- /*if (poly->contours[k].cw) {
- continue;
- }*/
- points = poly->contours[k].points;
- num_p = poly->contours[k].num_points;
-
- for (i = 0; i < num_p; i++) {
- if (i == num_p-1) {
- ii = 0;
- }
- else {
- ii = i+1;
- }
-
- glBegin(GL_QUAD_STRIP);
- p.x = p.y = pp.x = pp.y = 0;
- control = gradient->actual_colors[0].control;
- position = gradient->actual_colors[0].position;
- alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
- color = gradient->actual_colors[0].rgb;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
- glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
- for (j = 0; j < gradient->num_actual_colors-1; j++) {
- position = gradient->actual_colors[j+1].position;
- p2.x = (points[i].x-quad[0].x)*position/100.0;
- p2.y = (points[i].y-quad[0].y)*position/100.0;
- pp2.x = (points[ii].x-quad[0].x)*position/100.0;
- pp2.y = (points[ii].y-quad[0].y)*position/100.0;
- if (control != 50) {
- color = gradient->actual_colors[j].mid_rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[j].mid_alpha, wi->alpha);
- p3.x = p.x+(p2.x-p.x)*control/100.0;
- p3.y = p.y+(p2.y-p.y)*control/100.0;
- pp3.x = pp.x+(pp2.x-pp.x)*control/100.0;
- pp3.y = pp.y+(pp2.y-pp.y)*control/100.0;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p3.x, quad[0].y+p3.y);
- glVertex2d(quad[0].x+pp3.x, quad[0].y+pp3.y);
- }
- control = gradient->actual_colors[j+1].control;
- alpha = ZnComposeAlpha(gradient->actual_colors[j+1].alpha, wi->alpha);
- color = gradient->actual_colors[j+1].rgb;
- p = p2;
- pp = pp2;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
- glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
- }
- glEnd();
- }
- }
- }
- else if (type == ZN_CONICAL_GRADIENT) {
- ZnReal position;
- unsigned int num_p;
- ZnPoint *genarc, *tarc, p, focalp;
- XColor col;
-
- genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINEST, 0.0, 2*M_PI, &num_p, NULL);
- ZnListAssertSize(ZnWorkPoints, num_p);
- tarc = ZnListArray(ZnWorkPoints);
- ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
- p.x = p.y = 0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
-
- glBegin(GL_TRIANGLE_STRIP);
- for (i = 0; i < num_p; i++) {
- position = i*100.0/(num_p-1);
- ZnInterpGradientColor(gradient, position, &col, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
-
- /*printf("position: %g --> color: %d %d %d, alpha: %d\n",
- position, col.red, col.green, col.blue, alpha);*/
-
- glColor4us(col.red, col.green, col.blue, alpha);
- glVertex2d(tarc[i].x, tarc[i].y);
- glVertex2d(focalp.x, focalp.y);
- }
- glEnd();
- }
-
- if (cb) {
- /*
- * Restore the previous GL state.
- */
- ZnGlEndClip(num_clips);
- }
-}
-
-
-void
-ZnRenderHollowDot(ZnWInfo *wi,
- ZnPoint *p,
- ZnReal size)
-{
- int num_clips = ZnListSize(wi->clip_stack);
-
- ZnGlStartClip(num_clips, False);
-
- glPointSize((GLfloat) (size-2));
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlRenderClipped();
-
- glPointSize((GLfloat) size);
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlRestoreStencil(num_clips, False);
-
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlEndClip(num_clips);
-}
-#endif
-
-
-#ifdef GL
-void
-ZnRenderGlyph(ZnTexFontInfo *tfi,
- int c)
-{
- ZnTexGVI *tgvi;
-
- tgvi = ZnTexFontGVI(tfi, c);
- if (!tgvi) {
- return;
- }
- //printf("%c --> x0,y0: %d %d, tx0,ty0: %g %g, x1,y1: %d %d, tx1,ty1: %g %g, advance: %g\n",
- // c, tgvi->v0x, tgvi->v0y, tgvi->t0x, tgvi->t0y,
- // tgvi->v1x, tgvi->v1y, tgvi->t1x, tgvi->t1y,
- // tgvi->advance);
- glBegin(GL_QUADS);
- glTexCoord2f(tgvi->t0x, tgvi->t0y); glVertex2s(tgvi->v0x, tgvi->v0y);
- glTexCoord2f(tgvi->t0x, tgvi->t1y); glVertex2s(tgvi->v0x, tgvi->v1y);
- glTexCoord2f(tgvi->t1x, tgvi->t1y); glVertex2s(tgvi->v1x, tgvi->v1y);
- glTexCoord2f(tgvi->t1x, tgvi->t0y); glVertex2s(tgvi->v1x, tgvi->v0y);
- glEnd();
- glTranslatef(tgvi->advance, 0.0, 0.0);
-}
-
-#ifdef PTK_800
-void
-ZnRenderString(ZnTexFontInfo *tfi,
- unsigned char *string,
- unsigned int len)
-{
- while (len) {
- ZnRenderGlyph(tfi, *string);
- string++;
- len--;
- }
-}
-#else
-void
-ZnRenderString(ZnTexFontInfo *tfi,
- unsigned char *string,
- unsigned int len)
-{
- unsigned int clen;
- Tcl_UniChar c;
-
- while (len) {
- clen = Tcl_UtfToUniChar(string, &c);
-
- ZnRenderGlyph(tfi, c);
-
- string += clen;
- len -= clen;
- }
-}
-#endif
-#endif
-
-/*
- **********************************************************************************
- *
- * RenderTriangle --
- * This routine maps an image onto a triangle.
- * Image coordinates are chosen for each vertex of the triangle.
- * A simple affine tex mapping is used as in Zinc there is no way
- * to specify perspective deformation. No filtering is attempted
- * on the output pixels.
- *
- * In the comments below u and v are image coordinates and x and
- * y are triangle coordinates.
- * RenderAffineScanline is an helper function that draws a whole
- * scan line to the image with linear interpolation.
- *
- **********************************************************************************
- */
-static void
-RenderAffineScanline(XImage *image,
- XImage *mapped_image,
- ZnReal x1,
- ZnReal x2,
- ZnReal u1,
- ZnReal u2,
- ZnReal v1,
- ZnReal v2,
- int y)
-{
- ZnReal du, dv, width;
- int intx1, intx2, intu, intv;
- int i;
-
- /* Revert span ends if needed */
- if (x2 < x1) {
- ZnReal tmp;
- tmp = x1; x1 = x2; x2 = tmp;
- tmp = u1; u1 = u2; u2 = tmp;
- tmp = v1; v1 = v2; v2 = tmp;
- }
-
- /* Compute the interpolation factors */
- width = x2 - x1;
- if (width) {
- du = (u2 - u1) / width;
- dv = (v2 - v1) / width;
- }
- else {
- du = dv = 0;
- }
- intx1 = (int) floor(x1);
- intx2 = (int) floor(x2);
-
- /* Draw the line */
- for (i = intx1; i < intx2; i++) {
- intu = (int) floor(u1);
- intv = (int) floor(v1);
- XPutPixel(mapped_image, i, y, XGetPixel(image, intu, intv));
- u1 += du;
- v1 += dv;
- }
-}
-
-static void
-RenderTriangle(XImage *image,
- XImage *mapped_image,
- ZnPoint *tri,
- ZnPoint *im_coords)
-{
- ZnReal dx_A, dx_B; /* Interpolation factor in x / y */
- ZnReal du_A, du_B; /* in u / y */
- ZnReal dv_A, dv_B; /* in v / y */
- ZnReal x1, x2; /* Span in x */
- ZnReal u1, u2; /* Span in u */
- ZnReal v1, v2; /* Span in v */
- int height_A; /* Scan line # from top top vertex A */
- int height_B; /* Scan line # from top top vertex B */
- int y; /* Current scan line */
- int top, a, b; /* Top triangle vertex and other two */
- int i;
-
- /* Find top vertex and deduce the others. */
- top = 0;
- for (i = 1; i < 3; i++) {
- if (tri[i].y <= tri[top].y)
- top = i;
- }
- a = (top+1)%3;
- b = top-1;
- if (b < 0)
- b = 2;
-
- /* Initialize conversion parameters. */
- y = ZnNearestInt(tri[top].y);
- height_A = ZnNearestInt(tri[a].y - tri[top].y);
- height_B = ZnNearestInt(tri[b].y - tri[top].y);
- x1 = x2 = tri[top].x;
- u1 = u2 = im_coords[top].x;
- v1 = v2 = im_coords[top].y;
- if (height_A) {
- dx_A = (tri[a].x - tri[top].x) / height_A;
- du_A = (im_coords[a].x - im_coords[top].x) / height_A;
- dv_A = (im_coords[a].y - im_coords[top].y) / height_A;
- }
- else {
- dx_A = du_A = dv_A = 0;
- }
- if (height_B) {
- dx_B = (tri[b].x - tri[top].x) / height_B;
- du_B = (im_coords[b].x - im_coords[top].x) / height_B;
- dv_B = (im_coords[b].y - im_coords[top].y) / height_B;
- }
- else {
- dx_B = du_B = dv_B = 0;
- }
-
- /* Convert from top to bottom */
- for (i = 2; i > 0; ) {
- while (height_A && height_B) {
-
- /* Draw a scanline */
- RenderAffineScanline(image, mapped_image, x1, x2, u1, u2, v1, v2, y);
-
- /* Step the parameters*/
- y++;
- height_A--;
- height_B--;
- x1 += dx_A;
- x2 += dx_B;
- u1 += du_A;
- u2 += du_B;
- v1 += dv_A;
- v2 += dv_B;
- }
-
- /* If either height_A or height_B steps to zero, we have
- * encountered a vertex (A or B) and we are starting conversion
- * along a new edge. Update the parameters before proceeding. */
- if (!height_A) {
- int na = (a+1)%3;
-
- height_A = ZnNearestInt(tri[na].y - tri[a].y);
- if (height_A) {
- dx_A = (tri[na].x - tri[a].x) / height_A;
- du_A = (im_coords[na].x - im_coords[a].x) / height_A;
- dv_A = (im_coords[na].y - im_coords[a].y) / height_A;
- }
- else {
- dx_A = du_A = dv_A = 0;
- }
- x1 = tri[a].x;
- u1 = im_coords[a].x;
- v1 = im_coords[a].y;
- a = na;
- /* One less vertex to do */
- i--;
- }
-
- if (!height_B) {
- int nb = b - 1;
-
- if (nb < 0)
- nb = 2;
- height_B = ZnNearestInt(tri[nb].y - tri[b].y);
- if (height_B) {
- dx_B = (tri[nb].x - tri[b].x) / height_B;
- du_B = (im_coords[nb].x - im_coords[b].x) / height_B;
- dv_B = (im_coords[nb].y - im_coords[b].y) / height_B;
- }
- else {
- dx_B = du_B = dv_B = 0;
- }
- x2 = tri[b].x;
- u2 = im_coords[b].x;
- v2 = im_coords[b].y;
- b = nb;
- /* One less vertex to do */
- i--;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * MapImage --
- * This procedure maps an image on a parallelogram given in poly.
- * The given parallelogram should fit in the destination image.
- * The parallelogram vertices must be ordered as for a triangle
- * strip:
- *
- * v0 ------------ v2
- * | |
- * | |
- * v1 ------------ v3
- *
- * The mapping is done by a simple affine mapping of the image on the
- * two triangles obtained by cutting the parallelogram along the diogonal
- * from the second vertex to the third vertex.
- *
- **********************************************************************************
- */
-void
-ZnMapImage(XImage *image,
- XImage *mapped_image,
- ZnPoint *poly)
-{
- ZnPoint triangle[3];
- ZnPoint im_coords[3];
-
- triangle[0] = poly[0];
- triangle[1] = poly[1];
- triangle[2] = poly[2];
- im_coords[0].x = 0.0;
- im_coords[0].y = 0.0;
- im_coords[1].x = 0.0;
- im_coords[1].y = image->height-1;
- im_coords[2].x = image->width-1;
- im_coords[2].y = 0.0;
- RenderTriangle(image, mapped_image, triangle, im_coords);
-
- triangle[0] = poly[1];
- triangle[1] = poly[2];
- triangle[2] = poly[3];
- im_coords[0].x = 0.0;
- im_coords[0].y = image->height-1;
- im_coords[1].x = image->width-1;
- im_coords[1].y = 0.0;
- im_coords[2].x = image->width-1;
- im_coords[2].y = image->height-1;
- RenderTriangle(image, mapped_image, triangle, im_coords);
-}
diff --git a/generic/Draw.h b/generic/Draw.h
deleted file mode 100644
index 955f849..0000000
--- a/generic/Draw.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Draw.h -- Header for common drawing routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Sat Dec 10 12:51:30 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Draw_h
-#define _Draw_h
-
-#include "List.h"
-#include "Types.h"
-#include "Color.h"
-#include "Attrs.h"
-#include "Image.h"
-
-
-#define ZN_LINE_SHAPE_POINTS 4 /* Maximum of all *_SHAPE_POINTS */
-
-struct _ZnWInfo;
-
-#ifdef GL
-#define ZnGlStartClip(num_clips, render) { \
- if (!num_clips) { \
- glEnable(GL_STENCIL_TEST); \
- } \
- glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); \
- glStencilOp(GL_KEEP, GL_INCR, GL_INCR); \
- if (!render) { \
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
- } \
-}
-#define ZnGlRenderClipped() { \
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); \
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
- }
-#define ZnGlRestoreStencil(num_clips, render) { \
- glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF); \
- glStencilOp(GL_KEEP, GL_DECR, GL_DECR); \
- if (render) { \
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
- } \
- else { \
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
- } \
-}
-#define ZnGlEndClip(num_clips) { \
- glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); \
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); \
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
- if (!num_clips) { \
- glDisable(GL_STENCIL_TEST); \
- } \
-}
-#endif
-
-
-void ZnSetLineStyle(struct _ZnWInfo *wi, ZnLineStyle line_style);
-void ZnLineShapePoints(ZnPoint *p1, ZnPoint *p2, ZnDim line_width,
- ZnLineShape shape, ZnBBox *bbox, ZnList to_points);
-void ZnDrawLineShape(struct _ZnWInfo *wi, ZnPoint *points, unsigned int num_points,
- ZnLineStyle line_style, int foreground_pixel,
- ZnDim line_width, ZnLineShape shape);
-void
-ZnGetLineEnd(ZnPoint *p1, ZnPoint *p2, ZnDim line_width,
- int cap_style, ZnLineEnd end_style, ZnPoint *points);
-
-int ZnPolygonReliefInBBox(ZnPoint *points, unsigned int num_points,
- ZnDim line_width, ZnBBox *bbox);
-void ZnGetPolygonReliefBBox(ZnPoint *points, unsigned int num_points,
- ZnDim line_width, ZnBBox *bbox);
-double ZnPolygonReliefToPointDist(ZnPoint *points, unsigned int num_points,
- ZnDim line_width, ZnPoint *pp);
-void ZnDrawRectangleRelief(struct _ZnWInfo *wi,
- ZnReliefStyle relief, ZnGradient *gradient,
- XRectangle *bbox, ZnDim line_width);
-void ZnDrawPolygonRelief(struct _ZnWInfo *wi, ZnReliefStyle relief,
- ZnGradient *gradient, ZnPoint *points,
- unsigned int num_points, ZnDim line_width);
-#ifdef GL
-void ZnRenderPolygonRelief(struct _ZnWInfo *wi, ZnReliefStyle relief,
- ZnGradient *gradient, ZnBool smooth,
- ZnPoint *points, unsigned int num_points, ZnDim line_width);
-void ZnRenderPolyline(struct _ZnWInfo *wi, ZnPoint *points, unsigned int num_points,
- ZnDim line_width, ZnLineStyle line_style, int cap_style,
- int join_style, ZnLineEnd first_end, ZnLineEnd last_end,
- ZnGradient *gradient);
-void ZnComputeGradient(ZnGradient *grad, struct _ZnWInfo *wi, ZnPoly *shape,
- ZnPoint *grad_geo);
-void ZnRenderGradient(struct _ZnWInfo *wi, ZnGradient *gradient,
- void (*cb)(void *), void *closure, ZnPoint *quad,
- ZnPoly *poly);
-void ZnRenderTile(struct _ZnWInfo *wi, ZnImage tile, ZnGradient *gradient,
- void (*cb)(void *), void *closure, ZnPoint *quad);
-void ZnRenderIcon(struct _ZnWInfo *wi, ZnImage image, ZnGradient *gradient,
- ZnPoint *origin, ZnBool modulate);
-void ZnRenderImage(struct _ZnWInfo *wi, ZnImage image, ZnGradient *gradient,
- ZnPoint *quad, ZnBool modulate);
-void RenderHollowDot(struct _ZnWInfo *wi, ZnPoint *p, ZnReal size);
-
-void ZnRenderGlyph(ZnTexFontInfo *tfi, int c);
-void ZnRenderString(ZnTexFontInfo *tfi, unsigned char *str, unsigned int len);
-#endif
-
-void ZnMapImage(XImage *image, XImage *mapped_image, ZnPoint *poly);
-
-
-#endif /* _Draw_h */
diff --git a/generic/Field.c b/generic/Field.c
deleted file mode 100644
index e0a428f..0000000
--- a/generic/Field.c
+++ /dev/null
@@ -1,2584 +0,0 @@
-/*
- * Field.c -- Implementation of fields.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Item.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Draw.h"
-#include "Geo.h"
-#include "tkZinc.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-#define FIELD_SENSITIVE_BIT 1
-#define FIELD_VISIBLE_BIT 2
-#define FILLED_BIT 4
-#define TEXT_ON_TOP_BIT 8
-#define CACHE_OK 16
-
-
-/*
- * Field record.
- */
-typedef struct _FieldStruct {
- /* Public data */
- ZnGradient *color;
- ZnGradient *fill_color;
- ZnGradient *border_color;
- char *text;
- ZnImage image;
- ZnImage tile;
- Tk_Font font;
- unsigned short flags;
- ZnBorder border_edges;
- Tk_Justify alignment;
- ZnReliefStyle relief;
- ZnDim relief_thickness;
- ZnAutoAlign auto_alignment;
-
- /* Private data */
- ZnGradient *gradient;
- ZnPoint *grad_geo;
- short orig_x;
- short orig_y;
- short corner_x;
- short corner_y;
- int insert_index;
-#ifdef GL
- ZnTexFontInfo *tfi;
-#endif
-} FieldStruct, *Field;
-
-
-/*
- * The -text, -image, -border, -relief, -visible and
- * -filled attributes set the ZN_COORDS_FLAG to update
- * the leader that might protude if not clipped by the text.
- */
-ZnAttrConfig field_attrs[] = {
- { ZN_CONFIG_ALIGNMENT, "-alignment", NULL,
- Tk_Offset(FieldStruct, alignment), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_AUTO_ALIGNMENT, "-autoalignment", NULL,
- Tk_Offset(FieldStruct, auto_alignment), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-backcolor", NULL,
- Tk_Offset(FieldStruct, fill_color), 0,
- ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
- { ZN_CONFIG_EDGE_LIST, "-border", NULL,
- Tk_Offset(FieldStruct, border_edges), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-bordercolor", NULL,
- Tk_Offset(FieldStruct, border_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-color", NULL,
- Tk_Offset(FieldStruct, color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(FieldStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(FieldStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_FONT, "-font", NULL,
- Tk_Offset(FieldStruct, font), 0, ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_IMAGE, "-image", NULL,
- Tk_Offset(FieldStruct, image), 0,
- ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_RELIEF, "-relief", NULL,
- Tk_Offset(FieldStruct, relief), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-reliefthickness", NULL,
- Tk_Offset(FieldStruct, relief_thickness), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(FieldStruct, flags),
- FIELD_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
- { ZN_CONFIG_STRING, "-text", NULL,
- Tk_Offset(FieldStruct, text), 0, ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_IMAGE, "-tile", NULL,
- Tk_Offset(FieldStruct, tile), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(FieldStruct, flags), FIELD_VISIBLE_BIT,
- ZN_COORDS_FLAG|ZN_CLFC_FLAG, False }, /* Keep ZN_COORDS_FLAG here */
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-static void GetLabelBBox(ZnFieldSet field_set, ZnDim *w, ZnDim *h);
-
-
-
-/*
- **********************************************************************************
- *
- * ComputeFieldAttachment --
- * Compute the location/size of the field, computing attachments if any.
- *
- **********************************************************************************
- */
-static void
-ComputeFieldAttachment(ZnFieldSet field_set,
- unsigned int field,
- ZnBBox *field_bbox)
-{
-
- ZnBBox ref_bbox;
- ZnDim real_width, real_height;
- unsigned int ref_field, num_fields;
- char x_attach, y_attach, x_dim, y_dim;
- short width_spec, height_spec;
- int x_spec, y_spec, icon_width=0, icon_height=0;
- Field fptr;
- Tk_FontMetrics fm;
-
- /*printf("ComputeFieldAttachment in\n");*/
- fptr = &field_set->fields[field];
- if (ISSET(fptr->flags, CACHE_OK)) {
- field_bbox->orig.x = (ZnPos) fptr->orig_x;
- field_bbox->orig.y = (ZnPos) fptr->orig_y;
- field_bbox->corner.x = fptr->corner_x;
- field_bbox->corner.y = fptr->corner_y;
- /*printf("ComputeFieldAttachment in cache\n");*/
- return;
- }
-
- /*
- * Preset this field to a default position/size and pretend
- * its cache is ok to break any deadlocks.
- */
- fptr->orig_x = fptr->orig_y = 0;
- fptr->corner_x = fptr->corner_y = 0;
- field_bbox->orig.x = field_bbox->orig.y = 0;
- field_bbox->corner.x = field_bbox->corner.y = 0;
- SET(fptr->flags, CACHE_OK);
-
- num_fields = ZnLFNumFields(field_set->label_format);
- ZnLFGetField(field_set->label_format, field,
- &x_attach, &y_attach, &x_dim, &y_dim,
- &x_spec, &y_spec, &width_spec, &height_spec);
-
- /*
- * First try to compute the field size which may be a factor
- * of the field content (but not a factor of other fields).
- */
- if ((fptr->image != ZnUnspecifiedImage) &&
- ((x_dim == ZN_LF_DIM_ICON) || (y_dim == ZN_LF_DIM_ICON) ||
- (x_dim == ZN_LF_DIM_AUTO) || (y_dim == ZN_LF_DIM_AUTO))) {
- ZnSizeOfImage(fptr->image, &icon_width, &icon_height);
- }
-
- switch (x_dim) {
- case ZN_LF_DIM_FONT:
- real_width = (ZnDim) (width_spec*Tk_TextWidth(fptr->font, "N", 1)/100);
- break;
- case ZN_LF_DIM_ICON:
- real_width = (ZnDim) (width_spec*icon_width/100);
- break;
- case ZN_LF_DIM_AUTO:
- {
- int len = 0;
- ZnDim text_width;
-
- if (fptr->text) {
- len = strlen(fptr->text);
- }
- real_width = 0.0;
- if (fptr->image != ZnUnspecifiedImage) {
- real_width = (ZnDim) icon_width;
- }
- if (len) {
- /*
- * The 4 extra pixels are needed for border and padding.
- */
- text_width = (ZnDim) Tk_TextWidth(fptr->font, fptr->text, len) + 4;
- real_width = text_width < real_width ? real_width : text_width;
- }
- real_width += (ZnDim) width_spec;
- break;
- }
- case ZN_LF_DIM_LABEL:
- {
- ZnDim lh;
-
- GetLabelBBox(field_set, &real_width, &lh);
- break;
- }
- case ZN_LF_DIM_PIXEL:
- default:
- real_width = (ZnDim) width_spec;
- break;
- }
- /*printf("field %d, width = %g\n", field, real_width);*/
-
- switch (y_dim) {
- case ZN_LF_DIM_FONT:
- {
- Tk_GetFontMetrics(fptr->font, &fm);
- real_height = (ZnDim) (height_spec*(fm.ascent + fm.descent)/100);
- break;
- }
- case ZN_LF_DIM_ICON:
- real_height = (ZnDim) (height_spec*icon_height/100);
- break;
- case ZN_LF_DIM_AUTO:
- {
- ZnDim text_height;
-
- real_height = 0.0;
- if (fptr->image != ZnUnspecifiedImage) {
- real_height = (ZnDim) icon_height;
- }
- if (fptr->text && strlen(fptr->text)) {
- Tk_GetFontMetrics(fptr->font, &fm);
- text_height = (ZnDim) (fm.ascent + fm.descent);
- real_height = text_height < real_height ? real_height : text_height;
- }
- real_height += (ZnDim) height_spec;
- break;
- }
- case ZN_LF_DIM_LABEL:
- {
- ZnDim lw;
-
- GetLabelBBox(field_set, &lw, &real_height);
- break;
- }
- case ZN_LF_DIM_PIXEL:
- default:
- real_height = (ZnDim) height_spec;
- break;
- }
- /*printf("field %d, height = %g\n", field, real_height);*/
-
- /*
- * Update the cache with the newly computed infos
- * (breaking of deadlocks).
- */
- field_bbox->corner.x = real_width;
- field_bbox->corner.y = real_height;
- fptr->corner_x = (short) real_width;
- fptr->corner_y = (short) real_height;
-
- /*
- * Then try to deduce the position, resolving any attachments
- * if needed.
- */
-
- /*
- * Do the x axis.
- */
- if (x_dim != ZN_LF_DIM_LABEL) {
- if (x_attach == ZN_LF_ATTACH_PIXEL) {
- field_bbox->orig.x = (ZnPos) x_spec;
- field_bbox->corner.x = field_bbox->orig.x + real_width;
- }
- else {
- ref_field = x_spec;
- field_bbox->orig.x = field_bbox->corner.x = 0;
- if (ref_field >= num_fields) {
- ZnWarning ("Attached (x) to an inexistant field geometry\n");
- }
- else {
- ComputeFieldAttachment(field_set, ref_field, &ref_bbox);
- switch (x_attach) {
- case ZN_LF_ATTACH_FWD:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->orig.x = ref_bbox.corner.x;
- }
- else {
- field_bbox->orig.x = ref_bbox.orig.x;
- }
- field_bbox->corner.x = field_bbox->orig.x + real_width;
- break;
- case ZN_LF_ATTACH_BWD:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->corner.x = ref_bbox.orig.x;
- }
- else {
- field_bbox->corner.x = ref_bbox.corner.x;
- }
- field_bbox->orig.x = field_bbox->corner.x - real_width;
- break;
- case ZN_LF_ATTACH_LEFT:
- field_bbox->orig.x = ref_bbox.orig.x;
- field_bbox->corner.x = field_bbox->orig.x + real_width;
- break;
- case ZN_LF_ATTACH_RIGHT:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->corner.x = ref_bbox.corner.x;
- }
- else {
- field_bbox->corner.x = ref_bbox.orig.x;
- }
- field_bbox->orig.x = field_bbox->corner.x - real_width;
- break;
- }
- }
- }
- /*printf("field %d, x = %g\n", field, field_bbox->orig.x);*/
- }
-
- /*
- * Then the y axis.
- */
- if (y_dim != ZN_LF_DIM_LABEL) {
- if (y_attach == ZN_LF_ATTACH_PIXEL) {
- field_bbox->orig.y = (ZnPos) y_spec;
- field_bbox->corner.y = field_bbox->orig.y + real_height;
- }
- else {
- ref_field = y_spec;
- field_bbox->orig.y = field_bbox->corner.y = 0;
- if (ref_field >= num_fields) {
- ZnWarning ("Attached (y) to an inexistant field geometry\n");
- }
- else {
- ComputeFieldAttachment(field_set, ref_field, &ref_bbox);
- switch (y_attach) {
- case ZN_LF_ATTACH_FWD:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->orig.y = ref_bbox.corner.y;
- }
- else {
- field_bbox->orig.y = ref_bbox.orig.y;
- }
- field_bbox->corner.y = field_bbox->orig.y + real_height;
- break;
- case ZN_LF_ATTACH_BWD:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->corner.y = ref_bbox.orig.y;
- }
- else {
- field_bbox->corner.y = ref_bbox.corner.y;
- }
- field_bbox->orig.y = field_bbox->corner.y - real_height;
- break;
- case ZN_LF_ATTACH_LEFT:
- field_bbox->orig.y = ref_bbox.orig.y;
- field_bbox->corner.y = field_bbox->orig.y + real_height;
- break;
- case ZN_LF_ATTACH_RIGHT:
- if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
- field_bbox->corner.y = ref_bbox.corner.y;
- }
- else {
- field_bbox->corner.y = ref_bbox.orig.y;
- }
- field_bbox->orig.y = field_bbox->corner.y - real_height;
- break;
- }
- }
- }
- /*printf("field %d, y = %g\n", field, field_bbox->orig.y);*/
- }
-
- fptr->orig_x = (short) field_bbox->orig.x;
- fptr->orig_y = (short) field_bbox->orig.y;
- fptr->corner_x = (short) field_bbox->corner.x;
- fptr->corner_y = (short) field_bbox->corner.y;
- SET(fptr->flags, CACHE_OK);
-
- /*printf("ComputeFieldAttachment out\n");*/
-}
-
-
-/*
- **********************************************************************************
- *
- * ClearFieldCache --
- * Reset the geometric cache of all fields depending on a given field (or
- * of all fields if the field is < 0). Clear also the label bounding box
- * cache if some action has been taken on a field.
- *
- **********************************************************************************
- */
-static void
-ClearFieldCache(ZnFieldSet field_set,
- int field)
-{
- unsigned int i, num_fields;
- ZnBool clear_bbox;
- int x_spec, y_spec;
- char x_attach, y_attach, x_dim, y_dim;
- short width_spec, height_spec;
-
- if (!field_set->num_fields) {
- return;
- }
- if (field < 0) {
- for (i = 0; i < field_set->num_fields; i++) {
- CLEAR(field_set->fields[i].flags, CACHE_OK);
- }
- field_set->label_width = field_set->label_height = -1.0;
- return;
- }
-
- clear_bbox = False;
- if (!field_set->label_format) {
- return;
- }
- num_fields = ZnLFNumFields(field_set->label_format);
- if ((unsigned int) field >= num_fields) {
- return;
- }
- ZnLFGetField(field_set->label_format, (unsigned int) field,
- &x_attach, &y_attach, &x_dim, &y_dim,
- &x_spec, &y_spec, &width_spec, &height_spec);
- if ((x_dim != ZN_LF_DIM_PIXEL) || (y_dim != ZN_LF_DIM_PIXEL)) {
- CLEAR(field_set->fields[field].flags, CACHE_OK);
- clear_bbox = True;
- }
- for (i = 0; i < num_fields; i++) {
- ZnLFGetField(field_set->label_format, i,
- &x_attach, &y_attach, &x_dim, &y_dim,
- &x_spec, &y_spec, &width_spec, &height_spec);
- if ((x_attach == ZN_LF_ATTACH_PIXEL) && (y_attach == ZN_LF_ATTACH_PIXEL)) {
- continue;
- }
- if (x_attach != ZN_LF_ATTACH_PIXEL) {
- if ((x_spec == field) && ISSET(field_set->fields[i].flags, CACHE_OK)) {
- CLEAR(field_set->fields[i].flags, CACHE_OK);
- ClearFieldCache(field_set, (int) i);
- clear_bbox = True;
- }
- }
- if (y_attach != ZN_LF_ATTACH_PIXEL) {
- if ((y_spec == field) && ISSET(field_set->fields[i].flags, CACHE_OK)) {
- CLEAR(field_set->fields[i].flags, CACHE_OK);
- ClearFieldCache(field_set, (int) i);
- clear_bbox = True;
- }
- }
- }
-
- if (clear_bbox) {
- field_set->label_width = field_set->label_height = -1.0;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetLabelBBox --
- *
- **********************************************************************************
- */
-static void
-GetLabelBBox(ZnFieldSet field_set,
- ZnDim *w,
- ZnDim *h)
-{
- ZnBBox bbox, tmp_bbox;
- ZnLabelFormat lf;
- unsigned int i, num_fields;
- ZnDim clip_w, clip_h;
-
- /*printf("GetLabelBBox in\n");*/
- if ((field_set->label_width >= 0.0) && (field_set->label_height >= 0.0)) {
- *w = field_set->label_width;
- *h = field_set->label_height;
- /*printf("GetLabelBBox in cache\n");*/
- return;
- }
-
- lf = field_set->label_format;
- if (lf == NULL) {
- *w = *h = field_set->label_width = field_set->label_height = 0.0;
- /*printf("GetLabelBBox no labelformat\n");*/
- return;
- }
-
- ZnResetBBox(&bbox);
- num_fields = ZnLFNumFields(lf);
- for (i = 0; i < num_fields; i++) {
- ComputeFieldAttachment(field_set, i, &tmp_bbox);
- /*printf("field %d bbox %g %g %g %g\n", i, tmp_bbox.orig.x, tmp_bbox.orig.y,
- tmp_bbox.corner.x, tmp_bbox.corner.y);*/
- ZnAddBBoxToBBox(&bbox, &tmp_bbox);
- }
- field_set->label_width = bbox.corner.x;
- field_set->label_height = bbox.corner.y;
-
- /*printf("GetLabelBBox size before clipping; w = %g, h = %g\n",
- field_set->label_width, field_set->label_height);*/
- if (ZnLFGetClipBox(lf, &clip_w, &clip_h)) {
- if (clip_w < field_set->label_width) {
- field_set->label_width = clip_w;
- }
- if (clip_h < field_set->label_height) {
- field_set->label_height = clip_h;
- }
- }
-
- *w = field_set->label_width;
- *h = field_set->label_height;
- /*printf("GetLabelBBox returns computed size; w = %g, h = %g\n", *w, *h);*/
-}
-
-
-/*
- **********************************************************************************
- *
- * GetFieldBBox --
- * Compute the location of the field described
- * by the field entry index in the item current LabelFormat.
- *
- **********************************************************************************
- */
-static void
-GetFieldBBox(ZnFieldSet field_set,
- unsigned int index,
- ZnBBox *field_bbox)
-{
- ZnReal ox, oy;
-
- /*printf("GetFieldBBox in\n");*/
- if (field_set->label_format) {
- ox = ZnNearestInt(field_set->label_pos.x);
- oy = ZnNearestInt(field_set->label_pos.y);
- ComputeFieldAttachment(field_set, index, field_bbox);
- field_bbox->orig.x += ox;
- field_bbox->orig.y += oy;
- field_bbox->corner.x += ox;
- field_bbox->corner.y += oy;
- }
- else {
- ZnResetBBox(field_bbox);
- }
- /*printf("GetFieldBBox out\n");*/
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeFieldTextLocation --
- * Compute the position of the text in a field. This is a position
- * that we can give to XDrawText. The position is deduced from the
- * field bounding box passed in bbox.
- * Return also the text bounding box.
- *
- **********************************************************************************
- */
-static void
-ComputeFieldTextLocation(Field fptr,
- ZnBBox *bbox,
- ZnPoint *pos,
- ZnBBox *text_bbox)
-{
- ZnDim w, h;
- Tk_FontMetrics fm;
-
- Tk_GetFontMetrics(fptr->font, &fm);
- w = 0;
- if (fptr->text) {
- int width;
- Tk_MeasureChars(fptr->font, fptr->text, strlen(fptr->text), -1, 0, &width);
- w = width;
- }
- h = fm.ascent + fm.descent;
- text_bbox->orig.y = (bbox->orig.y + bbox->corner.y - h) / 2.0;
- text_bbox->corner.y = text_bbox->orig.y + h;
- pos->y = text_bbox->orig.y + fm.ascent;
-
- switch (fptr->alignment) {
- case TK_JUSTIFY_LEFT:
- text_bbox->orig.x = bbox->orig.x + 2;
- break;
- case TK_JUSTIFY_RIGHT:
- text_bbox->orig.x = bbox->corner.x - w - 2;
- break;
- default:
- text_bbox->orig.x = (bbox->orig.x + bbox->corner.x - w) / 2.0;
- break;
- }
- text_bbox->corner.x = text_bbox->orig.x + w;
- pos->x = text_bbox->orig.x;
-}
-
-
-/*
- **********************************************************************************
- *
- * LeaderToLabel --
- * Compute the segment part of segment <start, end> that lies
- * outside the fields of item.
- *
- **********************************************************************************
- */
-static void
-LeaderToLabel(ZnFieldSet field_set,
- ZnPoint *start,
- ZnPoint *end)
-{
- int b_num;
- ZnPoint delta, inf, sup;
- ZnPos xt=0, yu=0, yw=0, xv=0;
- Field fptr;
- unsigned int i;
- ZnBBox field_bbox;
-
- /* Intersection points : */
- /* T |xt / delta_y U |x1 V |y1 W |yw / delta_x */
- /* |y2 |yu / delta_x |xv / delta_y |x2 */
- /* */
- /* y = ax + b; */
- /* a = delta_y / delta_x */
- /* b = (y * delta_x - x * delta_y) / delta_x */
-
- delta.x = start->x - end->x;
- delta.y = start->y - end->y;
- b_num = (int) (start->y*delta.x - start->x*delta.y);
-
- for (i = 0; i < ZnLFNumFields(field_set->label_format); i++) {
- fptr = &field_set->fields[i];
- /*
- * If the field is made invisible or has no graphics of
- * its own, don't clip.
- */
- if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) ||
- (!fptr->text &&
- ISCLEAR(fptr->flags, FILLED_BIT) &&
- (fptr->border_edges == ZN_NO_BORDER) &&
- (fptr->relief == ZN_RELIEF_FLAT) &&
- (fptr->image == ZnUnspecifiedImage))) {
- continue;
- }
-
- /*
- * field_bbox is in absolute device coordinates.
- */
- GetFieldBBox(field_set, i, &field_bbox);
-
- /*
- * Adjust leader on real text, not on field boundaries. This is
- * important when there are leading and trailing spaces.
- */
- if (fptr->text &&
- ISCLEAR(fptr->flags, FILLED_BIT) &&
- (fptr->border_edges == ZN_NO_BORDER) &&
- (fptr->relief == ZN_RELIEF_FLAT) &&
- (fptr->image == ZnUnspecifiedImage)) {
- ZnBBox text_bbox;
- ZnPoint text_pos; /* dummy */
- int space_width;
- int scan_forw, scan_back;
- space_width = Tk_TextWidth(fptr->font, " ", 1);
-
- ComputeFieldTextLocation(fptr, &field_bbox, &text_pos, &text_bbox);
- /*
- * Correct adjusments made by ComputeFieldTextLocation (Vincent Pomey).
- *
- * PLC: IMHO, this is to compensate for exotic fonts like 'symbolesATC'.
- * I am not planning to port this to Tk for two reasons:
- * 1/ Current positions are no longer implemented as characters
- * and 2/ Tk does not give access (easily) to lbearings and rbearings.
- * This patch has been contributed by Phidias team. I don't know the
- * problem it was meant to solve.
- * text_bbox.x -= fptr->font->per_char[fptr->text[0]].lbearing + 3;
- * text_bbox.width += fptr->font->per_char[fptr->text[0]].lbearing + 3;
- */
- /*
- * Change bbox according to leading and trailing spaces.
- */
- scan_forw = 0;
- while (fptr->text[scan_forw] == ' ') {
- /* leading spaces */
- text_bbox.orig.x += space_width;
- scan_forw++;
- }
-
- /*
- * Empty text.
- */
- if (!fptr->text || (fptr->text[scan_forw] == 0)) {
- continue;
- }
-
- scan_back = strlen(fptr->text)-1;
- while ((fptr->text[scan_back] == ' ') && (scan_back > scan_forw)) {
- /* trailing spaces */
- text_bbox.corner.x -= space_width;
- scan_back--;
- }
-
- field_bbox = text_bbox;
- }
-
- if (field_bbox.corner.x <= field_bbox.orig.x) {
- continue;
- }
-
- if ((start->x >= field_bbox.orig.x) && (start->x < field_bbox.corner.x) &&
- (start->y >= field_bbox.orig.y) && (start->y < field_bbox.corner.y)) {
- end->x = start->x;
- end->y = start->y;
- }
- if (delta.x) {
- yu = (field_bbox.orig.x*delta.y + b_num) / delta.x;
- yw = (field_bbox.corner.x*delta.y + b_num) / delta.x;
- }
- if (delta.y) {
- xt = (field_bbox.corner.y*delta.x - b_num) / delta.y;
- xv = (field_bbox.orig.y*delta.x - b_num) / delta.y;
- }
-
- inf.x = MIN(start->x, end->x);
- sup.x = MAX(start->x, end->x);
- inf.y = MIN(start->y, end->y);
- sup.y = MAX(start->y, end->y);
-
- if (delta.x) {
- if ((yu >= field_bbox.orig.y) && (yu <= field_bbox.corner.y) &&
- (field_bbox.orig.x >= inf.x) && (field_bbox.orig.x <= sup.x) &&
- (yu >= inf.y) && (yu <= sup.y)) {
- end->x = field_bbox.orig.x;
- end->y = yu;
- inf.x = MIN(start->x, end->x);
- sup.x = MAX(start->x, end->x);
- inf.y = MIN(start->y, end->y);
- sup.y = MAX(start->y, end->y);
- }
- if ((yw >= field_bbox.orig.y) && (yw <= field_bbox.corner.y) &&
- (field_bbox.corner.x >= inf.x) && (field_bbox.corner.x <= sup.x) &&
- (yw >= inf.y) && (yw <= sup.y)) {
- end->x = field_bbox.corner.x;
- end->y = yw;
- inf.x = MIN(start->x, end->x);
- sup.x = MAX(start->x, end->x);
- inf.y = MIN(start->y, end->y);
- sup.y = MAX(start->y, end->y);
- }
- }
- if (delta.y) {
- if ((xt >= field_bbox.orig.x) && (xt <= field_bbox.corner.x) &&
- (xt >= inf.x) && (xt <= sup.x) &&
- (field_bbox.corner.y >= inf.y) && (field_bbox.corner.y <= sup.y)) {
- end->x = xt;
- end->y = field_bbox.corner.y;
- inf.x = MIN(start->x, end->x);
- sup.x = MAX(start->x, end->x);
- inf.y = MIN(start->y, end->y);
- sup.y = MAX(start->y, end->y);
- }
- if ((xv >= field_bbox.orig.x) && (xv <= field_bbox.corner.x) &&
- (xv >= inf.x) && (xv <= sup.x) &&
- (field_bbox.orig.y >= inf.y) && (field_bbox.orig.y <= sup.y)) {
- end->x = xv;
- end->y = field_bbox.orig.y;
- inf.x = MIN(start->x, end->x);
- sup.x = MAX(start->x, end->x);
- inf.y = MIN(start->y, end->y);
- sup.y = MAX(start->y, end->y);
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * InitFields --
- *
- * Perform the init of each field in a ZnFieldSet. The number of such
- * fields must have been inited before calling this fun.
- *
- **********************************************************************************
- */
-static void
-InitFields(ZnFieldSet field_set)
-{
- ZnWInfo *wi = field_set->item->wi;
- Field field;
- unsigned int i, num_fields;
-
- /*printf("size of a field = %d\n", sizeof(FieldStruct));*/
-
- if (!field_set->num_fields) {
- return;
- }
- num_fields = field_set->num_fields;
- field_set->fields = (Field) ZnMalloc(num_fields*sizeof(FieldStruct));
-
- for (i = 0; i < num_fields; i++){
- field = &field_set->fields[i];
-
- field->color = ZnGetGradientByValue(wi->fore_color);
- field->fill_color = ZnGetGradientByValue(wi->back_color);
- field->border_color = ZnGetGradientByValue(wi->fore_color);
- SET(field->flags, FIELD_VISIBLE_BIT);
- SET(field->flags, FIELD_SENSITIVE_BIT);
- CLEAR(field->flags, FILLED_BIT);
- CLEAR(field->flags, CACHE_OK);
- field->text = NULL;
- field->image = ZnUnspecifiedImage;
- field->tile = ZnUnspecifiedImage;
- field->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(wi->font));
-#ifdef GL
- field->tfi = ZnGetTexFont(wi, field->font);
-#endif
- field->border_edges = ZN_NO_BORDER;
- field->alignment = TK_JUSTIFY_LEFT;
- field->auto_alignment.automatic = False;
-
- field->relief = ZN_RELIEF_FLAT;
- field->relief_thickness = 2;
- SET(field->flags, TEXT_ON_TOP_BIT);
-
- field->gradient = NULL;
- field->grad_geo = NULL;
- }
- field_set->label_pos.x = field_set->label_pos.y = 0.0;
- field_set->label_width = field_set->label_height = -1.0;
-}
-
-
-/*
- **********************************************************************************
- *
- * CloneFields --
- *
- **********************************************************************************
- */
-static void
-CloneFields(ZnFieldSet field_set)
-{
- ZnWInfo *wi = field_set->item->wi;
- Field field, fields_ret;
- unsigned int i, num_fields;
- char *text;
-
- num_fields = field_set->num_fields;
- if (!num_fields) {
- return;
- }
- if (field_set->label_format) {
- field_set->label_format = ZnLFDuplicate(field_set->label_format);
- }
- fields_ret = (Field) ZnMalloc(num_fields*sizeof(FieldStruct));
- memcpy(fields_ret, field_set->fields, num_fields*sizeof(FieldStruct));
- field_set->fields = fields_ret;
-
- for (i = 0; i < num_fields; i++) {
- field = &fields_ret[i];
- if (field->gradient) {
- field->gradient = ZnGetGradientByValue(field->gradient);
- }
- if (field->grad_geo) {
- ZnPoint *grad_geo = ZnMalloc(4*sizeof(ZnPoint));
- memcpy(grad_geo, field->grad_geo, 4*sizeof(ZnPoint));
- field->grad_geo = grad_geo;
- }
- if (field->image != ZnUnspecifiedImage) {
- field->image = ZnGetImageByValue(field->image, ZnUpdateItemImage, field_set->item);
- }
- if (field->tile != ZnUnspecifiedImage) {
- field->tile = ZnGetImageByValue(field->tile, ZnUpdateItemImage, field_set->item);
- }
- field->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(field->font));
-#ifdef GL
- field->tfi = ZnGetTexFont(wi, field->font);
-#endif
- field->color = ZnGetGradientByValue(field->color);
- field->fill_color = ZnGetGradientByValue(field->fill_color);
- field->border_color = ZnGetGradientByValue(field->border_color);
-
- if (field->text) {
- text = (char *) ZnMalloc((strlen(field->text) + 1) * sizeof(char));
- strcpy(text, field->text);
- field->text = text;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ConfigureField --
- *
- **********************************************************************************
- */
-static int
-ConfigureField(ZnFieldSet fs,
- int field,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- unsigned int i;
- Field fptr;
- ZnBBox bbox;
- ZnWInfo *wi = fs->item->wi;
- XColor *color;
- unsigned short alpha;
- int old_num_chars, num_chars;
-#ifdef GL
- Tk_Font old_font;
-#endif
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- Tcl_AppendResult(wi->interp, "invalid field index", NULL);
- return TCL_ERROR;
- }
-
- fptr = &fs->fields[field];
-#ifdef GL
- old_font = fptr->font;
-#endif
- old_num_chars = 0;
- if (fptr->text) {
- old_num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
- }
-
- if (ZnConfigureAttributes(wi, fs->item, fptr, field_attrs,
- argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- num_chars = 0;
- if (fptr->text) {
- num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
- }
- if (old_num_chars != num_chars) {
- ZnTextInfo *ti = &wi->text_info;
- /*
- * The text has changed, update the selection and
- * insertion pos to keep them valid.
- */
- if ((fs->item == ti->sel_item) && (field == ti->sel_field)) {
- if (ti->sel_last > num_chars) {
- ti->sel_last = num_chars;
- }
- if (ti->sel_first >= ti->sel_last) {
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
- }
- if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
- (ti->sel_anchor > num_chars)) {
- ti->sel_anchor = num_chars;
- }
- }
- if (fptr->insert_index > num_chars) {
- fptr->insert_index = num_chars;
- }
- }
-
-#ifdef GL
- if (old_font != fptr->font) {
- if (fptr->tfi) {
- ZnFreeTexFont(fptr->tfi);
- fptr->tfi = ZnGetTexFont(wi, fptr->font);
- }
- }
-#endif
-
- if (ISSET(*flags, ZN_REPICK_FLAG)) {
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- }
- if (ISSET(*flags, ZN_CLFC_FLAG)) {
- ClearFieldCache(fs, field);
- }
-
- if (fptr->gradient &&
- (ISSET(*flags, ZN_BORDER_FLAG) || (fptr->relief == ZN_RELIEF_FLAT))) {
- ZnFreeGradient(fptr->gradient);
- fptr->gradient = NULL;
- }
- if ((fptr->relief != ZN_RELIEF_FLAT) && !fptr->gradient) {
- color = ZnGetGradientColor(fptr->border_color, 51.0, &alpha);
- fptr->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- Tk_NameOfColor(color), alpha);
- if (fptr->gradient == NULL) {
- return TCL_ERROR;
- }
- }
-
- /*
- * This is done here to limit the redraw to the area of the
- * modified fields.
- */
- if (ISCLEAR(*flags, ZN_COORDS_FLAG) &&
- fs->label_format && ISSET(*flags, ZN_DRAW_FLAG)) {
- for (i = 0; i < ZnLFNumFields(fs->label_format); i++) {
- if (i == (unsigned int) field) {
- GetFieldBBox(fs, i, &bbox);
- ZnDamage(wi, &bbox);
- break;
- }
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * QueryField --
- *
- **********************************************************************************
- */
-static int
-QueryField(ZnFieldSet fs,
- int field,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- Tcl_AppendResult(fs->item->wi->interp, "invalid field index \"", NULL);
- return TCL_ERROR;
- }
-
- if (ZnQueryAttribute(fs->item->wi->interp, &fs->fields[field], field_attrs,
- argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * FreeFields --
- *
- **********************************************************************************
- */
-static void
-FreeFields(ZnFieldSet field_set)
-{
- unsigned int i, num_fields;
- Field field;
-
- if (field_set->label_format) {
- ZnLFDelete(field_set->label_format);
- }
-
- num_fields = field_set->num_fields;
- for (i = 0; i < num_fields; i++) {
- field = &field_set->fields[i];
-
- if (field->text) {
- ZnFree(field->text);
- }
- if (field->gradient) {
- ZnFreeGradient(field->gradient);
- }
- if (field->grad_geo) {
- ZnFree(field->grad_geo);
- }
- if (field->image != ZnUnspecifiedImage) {
- ZnFreeImage(field->image, ZnUpdateItemImage, &field->image);
- field->image = ZnUnspecifiedImage;
- }
- if (field->tile != ZnUnspecifiedImage) {
- ZnFreeImage(field->tile, ZnUpdateItemImage, &field->tile);
- field->tile = ZnUnspecifiedImage;
- }
- Tk_FreeFont(field->font);
-#ifdef GL
- if (field->tfi) {
- ZnFreeTexFont(field->tfi);
- }
-#endif
- ZnFreeGradient(field->color);
- ZnFreeGradient(field->fill_color);
- ZnFreeGradient(field->border_color);
- }
- if (num_fields) {
- ZnFree(field_set->fields);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * FieldIndex,
- * FieldInsertChars,
- * FieldDeleteChars,
- * FieldCursor,
- * FieldSelection --
- * These functions implement text edition in fields. The behavior
- * is the same as for Text items.
- *
- **********************************************************************************
- */
-static int
-FieldPointToChar(ZnFieldSet fs,
- unsigned int field,
- int x,
- int y)
-{
- Field fptr;
- int byte_index;
- ZnBBox f_bbox, t_bbox;
- ZnPoint t_orig;
- unsigned int num_bytes, n, dummy;
-
- fptr = &fs->fields[field];
- num_bytes = 0;
- byte_index = 0;
- if (fptr->text) {
- num_bytes = strlen(fptr->text);
- }
-
- if (num_bytes == 0) {
- return 0;
- }
-
- GetFieldBBox(fs, field, &f_bbox);
- ComputeFieldTextLocation(fptr, &f_bbox, &t_orig, &t_bbox);
-
- /*
- * Point above text, returns index 0.
- */
- if (y < t_bbox.orig.y) {
- return 0;
- }
-
- if (y < t_bbox.corner.y) {
- if (x < t_bbox.orig.x) {
- /*
- * Point to the left of the current line, returns
- * index of first char.
- */
- return 0;
- }
- if (x >= t_bbox.corner.x) {
- /*
- * Point to the right of the current line, returns
- * index past the last char.
- */
- byte_index = num_bytes;
- goto convrt;
- }
- n = Tk_MeasureChars(fptr->font, fptr->text, num_bytes,
- x + 2 - (int) t_bbox.orig.x, TK_PARTIAL_OK, &dummy);
- byte_index = n - 1;
- goto convrt;
- }
- /*
- * Point below all lines, return the index after
- * the last char.
- */
- byte_index = num_bytes;
- convrt:
- return Tcl_NumUtfChars(fptr->text, byte_index);
-}
-
-static int
-WordMoveFromIndex(char *text,
- int index,
- int fwd)
-{
- char const *strp;
-
- if (!text) {
- return index;
- }
-
- strp = Tcl_UtfAtIndex(text, index);
- if (fwd) {
- while ((strp[1] == ' ') || (strp[1] == '\n')) {
- strp++;
- }
- while ((strp[1] != ' ') && (strp[1] != '\n') && strp[1]) {
- strp++;
- }
- return Tcl_NumUtfChars(text, strp + 1 - text);
- }
- else {
- while ((strp != text) && ((strp[-1] == ' ') || (strp[-1] == '\n'))) {
- strp--;
- }
- while ((strp != text) && (strp[-1] != ' ') && (strp[-1] != '\n')) {
- strp--;
- }
- return Tcl_NumUtfChars(text, strp - text);
- }
-}
-
-static int
-FieldIndex(ZnFieldSet fs,
- int field,
- Tcl_Obj *index_spec,
- int *index)
-{
- Field fptr;
- ZnWInfo *wi = fs->item->wi;
- ZnTextInfo *ti = &wi->text_info;
- unsigned int length;
- int c, x, y;
- double tmp;
- char *end, *p;
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- *index = 0;
- return TCL_OK;
- }
-
- fptr = &fs->fields[field];
-
- p = Tcl_GetString(index_spec);
- c = p[0];
- length = strlen(p);
-
- if ((c == 'e') && (strncmp(p, "end", length) == 0)) {
- *index = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
- }
- else if ((c == 'e') && (length > 1) && (strncmp(p, "eol", length) == 0)) {
- *index = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
- }
- else if ((c == 'b') && (length > 1) && (strncmp(p, "bol", length) == 0)) {
- *index = 0;
- }
- else if ((c == 'e') && (length > 1) && (strncmp(p, "eow", length) == 0)) {
- *index = WordMoveFromIndex(fptr->text, fptr->insert_index, 1);
- }
- else if ((c == 'b') && (length > 1) && (strncmp(p, "bow", length) == 0)) {
- *index = WordMoveFromIndex(fptr->text, fptr->insert_index, 0);
- }
- else if ((c == 'u') && (strncmp(p, "up", length) == 0)) {
- *index = fptr->insert_index;
- }
- else if ((c == 'd') && (strncmp(p, "down", length) == 0)) {
- *index = fptr->insert_index;
- }
- else if ((c == 'i') && (strncmp(p, "insert", length) == 0)) {
- *index = fptr->insert_index;
- }
- else if ((c == 's') && (strncmp(p, "sel.first", length) == 0) &&
- (length >= 5)) {
- if ((ti->sel_item != fs->item) || (ti->sel_field != field)) {
- sel_err:
- Tcl_AppendResult(wi->interp, "selection isn't in field", (char *) NULL);
- return TCL_ERROR;
- }
- *index = ti->sel_first;
- }
- else if ((c == 's') && (strncmp(p, "sel.last", length) == 0) &&
- (length >= 5)) {
- if ((ti->sel_item != fs->item) || (ti->sel_field != field)) {
- goto sel_err;
- }
- /*
- * We return a modified selection end so that it reflect
- * the text index of the last character _not_ the insertion
- * point between the last and the next.
- */
- *index = ti->sel_last-1;
- }
- else if (c == '@') {
- p++;
- tmp = strtod(p, &end);
- if ((end == p) || (*end != ',')) {
- goto badIndex;
- }
- x = (int) tmp;
- p = end+1;
- tmp = strtod(p, &end);
- if ((end == p) || (*end != 0)) {
- goto badIndex;
- }
- y = (int) tmp;
-
- *index = FieldPointToChar(fs, (unsigned int) field, x, y);
- }
- else if (Tcl_GetIntFromObj(wi->interp, index_spec, index) == TCL_OK) {
- int num_chars = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
- if (*index < 0){
- *index = 0;
- }
- else if (*index > num_chars) {
- *index = num_chars;
- }
- }
- else {
- badIndex:
- Tcl_AppendResult(wi->interp, "bad index \"", p, "\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-static ZnBool
-FieldInsertChars(ZnFieldSet fs,
- int field,
- int *index,
- char *chars)
-{
- Field fptr;
- ZnTextInfo *ti = &fs->item->wi->text_info;
- int num_chars, num_bytes, chars_added;
- unsigned int byte_index, bytes_added = strlen(chars);
- char *new;
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- return False;
- }
-
- if (bytes_added == 0) {
- return False;
- }
-
- fptr = &fs->fields[field];
- num_chars = 0;
- num_bytes = 0;
- if (fptr->text) {
- num_bytes = strlen(fptr->text);
- num_chars = Tcl_NumUtfChars(fptr->text, num_bytes);
- }
- if (*index < 0) {
- *index = 0;
- }
- if (*index > num_chars) {
- *index = num_chars;
- }
- chars_added = Tcl_NumUtfChars(chars, (int) bytes_added);
-
- if (fptr->text) {
- byte_index = Tcl_UtfAtIndex(fptr->text, *index) - fptr->text;
- new = ZnMalloc(num_bytes + bytes_added + 1);
- /*
- * Copy the part before and the part after the new
- * text (if any).
- */
- memcpy(new, fptr->text, (size_t) byte_index);
- strcpy(new + byte_index + bytes_added, fptr->text + byte_index);
- ZnFree(fptr->text);
- }
- else {
- byte_index = 0;
- new = ZnMalloc(num_bytes + 1);
- new[num_bytes] = 0;
- }
- /*
- * Insert the new text.
- */
- memcpy(new + byte_index, chars, bytes_added);
- fptr->text = new;
-
- if (fptr->insert_index >= *index) {
- fptr->insert_index += chars_added;
- }
- if ((ti->sel_item == fs->item) && (ti->sel_field == field)) {
- if (ti->sel_first >= *index) {
- ti->sel_first += chars_added;
- }
- if (ti->sel_last >= *index) {
- ti->sel_last += chars_added;
- }
- if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
- (ti->sel_anchor >= *index)) {
- ti->sel_anchor += chars_added;
- }
- }
-
- /*
- * Need to redo the fields layout (maybe).
- */
- ClearFieldCache(fs, field);
- return True;
-}
-
-static ZnBool
-FieldDeleteChars(ZnFieldSet fs,
- int field,
- int *first,
- int *last)
-{
- Field fptr;
- ZnTextInfo *ti = &fs->item->wi->text_info;
- unsigned int char_count, byte_count;
- unsigned int num_bytes, num_chars, first_offset;
- char *new;
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- return False;
- }
-
- fptr = &fs->fields[field];
- num_chars = 0;
- num_bytes = 0;
- if (fptr->text) {
- num_bytes = strlen(fptr->text);
- num_chars = Tcl_NumUtfChars(fptr->text, (int) num_bytes);
- }
- if (num_chars == 0) {
- return False;
- }
-
- if (*first < 0) {
- *first = 0;
- }
- if (*last >= (int) num_chars) {
- *last = num_chars-1;
- }
- if (*first > *last) {
- return False;
- }
- char_count = *last + 1 - *first;
- first_offset = Tcl_UtfAtIndex(fptr->text, *first)-fptr->text;
- byte_count = Tcl_UtfAtIndex(fptr->text + first_offset, (int) char_count) -
- (fptr->text+first_offset);
-
- if (num_bytes - byte_count) {
- new = ZnMalloc(num_bytes + 1 - byte_count);
- memcpy(new, fptr->text, (size_t) first_offset);
- strcpy(new + first_offset, fptr->text + first_offset + byte_count);
- ZnFree(fptr->text);
- fptr->text = new;
- }
- else {
- ZnFree(fptr->text);
- fptr->text = NULL;
- }
-
- /*
- * Update the cursor to reflect the new string.
- */
- if (fptr->insert_index > *first) {
- fptr->insert_index -= char_count;
- if (fptr->insert_index < *first) {
- fptr->insert_index = *first;
- }
- }
- if ((ti->sel_item == fs->item) && (ti->sel_field == field)) {
- if (ti->sel_first > *first) {
- ti->sel_first -= char_count;
- if (ti->sel_first < *first) {
- ti->sel_first = *first;
- }
- }
- if (ti->sel_last >= *first) {
- ti->sel_last -= char_count;
- if (ti->sel_last < *first - 1) {
- ti->sel_last = *first - 1;
- }
- }
- if (ti->sel_first > ti->sel_last) {
- ti->sel_item = ZN_NO_ITEM;
- }
- if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
- (ti->sel_anchor > *first)) {
- ti->sel_anchor -= char_count;
- if (ti->sel_anchor < *first) {
- ti->sel_anchor = *first;
- }
- }
- }
-
- /*
- * Need to redo the fields layout (maybe).
- */
- ClearFieldCache(fs, field);
- return True;
-}
-
-static void
-FieldCursor(ZnFieldSet fs,
- int field,
- int index)
-{
- Field fptr;
- int num_chars;
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- return;
- }
-
- fptr = &fs->fields[field];
- num_chars = 0;
- if (fptr->text) {
- num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
- }
-
- if (index < 0) {
- fptr->insert_index = 0;
- }
- else if (index > num_chars) {
- fptr->insert_index = num_chars;
- }
- else {
- fptr->insert_index = index;
- }
-}
-
-static int
-FieldSelection(ZnFieldSet fs,
- int field,
- int offset,
- char *chars,
- int max_bytes)
-{
- Field fptr;
- int count;
- char const *sel_first, *sel_last;
- ZnTextInfo *ti;
-
- if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
- return 0;
- }
- ti = &fs->item->wi->text_info;
- if ((ti->sel_first < 0) ||
- (ti->sel_first > ti->sel_last)) {
- return 0;
- }
-
- fptr = &fs->fields[field];
- if (!fptr->text) {
- return 0;
- }
-
- sel_first = Tcl_UtfAtIndex(fptr->text, ti->sel_first);
- sel_last = Tcl_UtfAtIndex(sel_first, ti->sel_last + 1 - ti->sel_first);
- count = sel_last - sel_first - offset;
- if (count <= 0) {
- return 0;
- }
- if (count > max_bytes) {
- count = max_bytes;
- }
-
- memcpy(chars, sel_first + offset, (size_t) count);
- chars[count] = 0;
-
- return count;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeFieldImageLocation --
- * Compute the bounding box of the pixmap in a field. The position is
- * deduced from the field bounding box passed in bbox.
- *
- **********************************************************************************
- */
-static void
-ComputeFieldImageLocation(Field fptr,
- ZnBBox *bbox,
- ZnBBox *pm_bbox)
-{
- int width, height;
-
- ZnSizeOfImage(fptr->image, &width, &height);
- pm_bbox->orig.y = (bbox->orig.y + bbox->corner.y - height) / 2;
- pm_bbox->corner.y = pm_bbox->orig.y + height;
-
- switch (fptr->alignment) {
- case TK_JUSTIFY_LEFT:
- pm_bbox->orig.x = bbox->orig.x;
- break;
- case TK_JUSTIFY_RIGHT:
- pm_bbox->orig.x = bbox->corner.x - width - 1;
- break;
- default:
- pm_bbox->orig.x = (bbox->orig.x + bbox->corner.x - width) / 2;
- break;
- }
- pm_bbox->corner.x = pm_bbox->orig.x + width;
-}
-
-
-/*
- **********************************************************************************
- *
- * FieldsEngine --
- *
- **********************************************************************************
- */
-static void
-FieldsEngine(ZnFieldSet field_set,
- void (*cb)())
-{
- ZnWInfo *wi = field_set->item->wi;
- /*int i; This one *NEED* to be an int */
- unsigned int i, num_fields, num_chars;
- Field fptr;
- ZnTextInfo *ti = &wi->text_info;
- ZnBBox lclip_bbox, fclip_bbox, bbox, *global_clip_box;
- ZnBBox tmp_bbox, text_bbox, pm_bbox;
- ZnPoint pts[2];
- ZnTriStrip tristrip;
- ZnPoint text_pos;
- ZnBool restore = False;
- ZnDim lwidth, lheight;
- ZnReal val;
- int cursor;
- int sel_start, sel_stop;
-
- if (!field_set->num_fields) {
- return;
- }
-
- if (field_set->label_format && ZnLFNumFields(field_set->label_format)) {
- bbox.orig.x = ZnNearestInt(field_set->label_pos.x);
- bbox.orig.y = ZnNearestInt(field_set->label_pos.y);
- GetLabelBBox(field_set, &lwidth, &lheight);
- bbox.corner.x = bbox.orig.x + lwidth;
- bbox.corner.y = bbox.orig.y + lheight;
- ZnCurrentClip(wi, NULL, &global_clip_box, NULL);
-
- if (!wi->render) {
- ZnIntersectBBox(global_clip_box, &bbox, &lclip_bbox);
- if (ZnIsEmptyBBox(&lclip_bbox)) {
- return;
- }
- }
- else {
- lclip_bbox = bbox;
- }
-
- num_fields = ZnLFNumFields(field_set->label_format);
- for (i = 0; i < num_fields; i++) {
- fptr = &field_set->fields[i];
-
- if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT)) {
- continue;
- }
-
- GetFieldBBox(field_set, i, &bbox);
- ZnIntersectBBox(&lclip_bbox, &bbox, &fclip_bbox);
- if (ZnIsEmptyBBox(&fclip_bbox)) {
- continue;
- }
-
- /* we must call XSetClipRectangles only if it's required */
- val = fclip_bbox.orig.x - bbox.orig.x;
- restore = val > 0;
- val = fclip_bbox.orig.y - bbox.orig.y;
- restore |= val > 0;
- val = fclip_bbox.corner.x - bbox.corner.x;
- restore |= val < 0;
- val = fclip_bbox.corner.y - bbox.corner.y;
- restore |= val < 0;
-
- cursor = ((field_set->item == wi->focus_item) &&
- ((unsigned int) wi->focus_field == i) &&
- ISSET(wi->flags, ZN_GOT_FOCUS) && ti->cursor_on) ? 0 : -1;
- sel_start = -1, sel_stop = -1;
- ComputeFieldTextLocation(fptr, &bbox, &text_pos, &text_bbox);
-
- if (fptr->text) {
- if (cursor != -1) {
- cursor = Tk_TextWidth(fptr->font, fptr->text,
- Tcl_UtfAtIndex(fptr->text,
- fptr->insert_index)-fptr->text);
- }
- num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
- if (num_chars) {
- if ((field_set->item == ti->sel_item) && ((unsigned int) ti->sel_field == i) &&
- (ti->sel_last >= 0) && (ti->sel_first <= (int) num_chars)) {
- sel_start = Tk_TextWidth(fptr->font, fptr->text,
- Tcl_UtfAtIndex(fptr->text,
- ti->sel_first)-fptr->text);
- sel_stop = Tk_TextWidth(fptr->font, fptr->text,
- Tcl_UtfAtIndex(fptr->text,
- ti->sel_last)-fptr->text);
- }
-
- ZnIntersectBBox(&fclip_bbox, &text_bbox, &tmp_bbox);
-
- val = tmp_bbox.orig.x - text_bbox.orig.x;
- restore |= val > 0;
- val = tmp_bbox.orig.y - text_bbox.orig.y;
- restore |= val > 0;
- val = tmp_bbox.corner.x - text_bbox.corner.x;
- restore |= val < 0;
- val = tmp_bbox.corner.y - text_bbox.corner.y;
- restore |= val < 0;
- }
- }
-
- if (fptr->image != ZnUnspecifiedImage) {
- ComputeFieldImageLocation(fptr, &bbox, &pm_bbox);
-
- ZnIntersectBBox(&fclip_bbox, &pm_bbox, &tmp_bbox);
-
- val = tmp_bbox.orig.x - pm_bbox.orig.x;
- restore |= val > 0;
- val = tmp_bbox.orig.y - pm_bbox.orig.y;
- restore |= val > 0;
- val = tmp_bbox.corner.x - pm_bbox.corner.x;
- restore |= val < 0;
- val = tmp_bbox.corner.y - pm_bbox.corner.y;
- restore |= val < 0;
- }
-
- /*restore = True;*/
- if (restore) {
- /* we must clip. */
- /*printf("clip: %d\n", i);*/
- pts[0] = fclip_bbox.orig;
- pts[1] = fclip_bbox.corner;
- ZnTriStrip1(&tristrip, pts, 2, False);
- ZnPushClip(wi, &tristrip, True, True);
- }
-
- (*cb)(wi, fptr, &bbox, &pm_bbox,
- &text_pos, &text_bbox, cursor, sel_start, sel_stop);
-
- if (restore) {
- /* Restore the previous clip. */
- ZnPopClip(wi, True);
- restore = False;
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * DrawFields --
- *
- **********************************************************************************
- */
-static void
-DrawField(ZnWInfo *wi,
- Field fptr,
- ZnBBox *bbox,
- ZnBBox *pm_bbox,
- ZnPoint *text_pos,
- ZnBBox *text_bbox,
- int cursor,
- int sel_start,
- int sel_stop)
-{
- ZnTextInfo *ti = &wi->text_info;
- XGCValues values;
- XRectangle r;
- int j, xs, num_bytes;
- int pw, ph, fw, fh;
- TkRegion clip_region;
- ZnBool simple;
- Pixmap pixmap;
- TkRegion photo_region, clip;
-
- ZnBBox2XRect(bbox, &r);
-
- /*
- * Draw the background.
- */
- if (ISSET(fptr->flags, FILLED_BIT)) {
- values.foreground = ZnGetGradientPixel(fptr->fill_color, 0.0);
-
- if (fptr->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(fptr->tile)) { /* Fill tiled */
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(fptr->tile, wi->win);
- values.ts_x_origin = (int) bbox->orig.x;
- values.ts_y_origin = (int) bbox->orig.y;
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile,
- &values);
- }
- else { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(fptr->tile, wi->win);
- values.ts_x_origin = (int) bbox->orig.x;
- values.ts_y_origin = (int) bbox->orig.y;
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground,
- &values);
- }
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);
- }
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height);
- }
-
- /*
- * Draw the image and the text, which is in back depends on
- * the value of text_on_top.
- */
- for (j = 0; j < 2; j++) {
- if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
- (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
- /*
- * Draw the image.
- */
- if (fptr->image != ZnUnspecifiedImage) {
- pw = ZnNearestInt(pm_bbox->corner.x - pm_bbox->orig.x);
- ph = ZnNearestInt(pm_bbox->corner.y - pm_bbox->orig.y);
- fw = ZnNearestInt(bbox->corner.x - bbox->orig.x);
- fh = ZnNearestInt(bbox->corner.y - bbox->orig.y);
-
- pixmap = ZnImagePixmap(fptr->image, wi->win);
- photo_region = ZnImageRegion(fptr->image);
- ZnCurrentClip(wi, &clip_region, NULL, &simple);
- clip = TkCreateRegion();
- /*
- * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
- * some internal TkPhoto functions.
- * This is a workaround using a rectangular region based
- * on the image size.
- */
- if (photo_region == NULL) {
- XRectangle rect;
- rect.x = rect.y = 0;
- rect.width = pw;
- rect.height = ph;
- TkUnionRectWithRegion(&rect, clip, clip);
- }
- else {
- ZnUnionRegion(clip, photo_region, clip);
- }
- ZnOffsetRegion(clip, (int) pm_bbox->orig.x, (int) pm_bbox->orig.y);
- TkIntersectRegion(clip_region, clip, clip);
- TkSetRegion(wi->dpy, wi->gc, clip);
- XCopyArea(wi->dpy, pixmap, wi->draw_buffer, wi->gc,
- (int) ZnNearestInt(bbox->orig.x-pm_bbox->orig.x),
- (int) ZnNearestInt(bbox->orig.y-pm_bbox->orig.y),
- (unsigned int) MIN(pw, fw),
- (unsigned int) MIN(ph, fh),
- (int) MAX(bbox->orig.x, pm_bbox->orig.x),
- (int) MAX(bbox->orig.y, pm_bbox->orig.y));
-
- TkSetRegion(wi->dpy, wi->gc, clip_region);
- TkDestroyRegion(clip);
- }
- }
- else if (fptr->text) {
- /*
- * Draw the text.
- */
- num_bytes = strlen(fptr->text);
- if (num_bytes) {
- if (sel_start >= 0) {
- values.foreground = ZnGetGradientPixel(ti->sel_color, 0.0);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- (int) (text_bbox->orig.x+sel_start),
- (int) text_bbox->orig.y,
- (unsigned int) (sel_stop-sel_start),
- (unsigned int) (text_bbox->corner.y-text_bbox->orig.y));
- }
- values.foreground = ZnGetGradientPixel(fptr->color, 0.0);
- values.fill_style = FillSolid;
- values.font = Tk_FontId(fptr->font);
- XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle | GCFont, &values);
- Tk_DrawChars(wi->dpy, wi->draw_buffer, wi->gc, fptr->font,
- fptr->text, num_bytes, (int) text_pos->x, (int) text_pos->y);
- }
- }
- }
- if (cursor >= 0) {
- values.line_width = ti->insert_width;
- values.foreground = ZnGetGradientPixel(ti->insert_color, 0.0);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCLineWidth|GCFillStyle, &values);
- xs = (int) text_bbox->orig.x + cursor;
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- xs, (int) text_bbox->orig.y,
- xs, (int) text_bbox->corner.y);
- }
-
- /*
- * Draw the border relief.
- */
- if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
- ZnDrawRectangleRelief(wi, fptr->relief, fptr->gradient,
- &r, fptr->relief_thickness);
- }
-
- /*
- * Draw the border line.
- */
- if (fptr->border_edges != ZN_NO_BORDER) {
- values.foreground = ZnGetGradientPixel(fptr->border_color, 0.0);
- values.line_width = 0;
- values.line_style = LineSolid;
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc,
- GCForeground | GCLineWidth | GCLineStyle | GCFillStyle, &values);
- if (fptr->border_edges & ZN_LEFT_BORDER) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
- r.x, r.y + r.height - 1);
- }
- if (fptr->border_edges & ZN_RIGHT_BORDER) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- r.x + r.width - 1, r.y,
- r.x + r.width - 1, r.y + r.height - 1);
- }
- if (fptr->border_edges & ZN_TOP_BORDER) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- r.x, r.y, r.x + r.width - 1, r.y);
- }
- if (fptr->border_edges & ZN_BOTTOM_BORDER) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- r.x, r.y + r.height - 1,
- r.x + r.width - 1, r.y + r.height - 1);
- }
- if (fptr->border_edges & ZN_OBLIQUE) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- r.x, r.y, r.x + r.width - 1, r.y + r.height - 1);
- }
- if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- r.x, r.y + r.height - 1,
- r.x + r.width - 1, r.y);
- }
- }
-}
-
-static void
-DrawFields(ZnFieldSet field_set)
-{
- FieldsEngine(field_set, DrawField);
-}
-
-
-/*
- **********************************************************************************
- *
- * RenderFields --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-FieldRenderCB(void *closure)
-{
- ZnBBox *bbox = (ZnBBox *) closure;
-
- glBegin(GL_QUADS);
- glVertex2d(bbox->orig.x, bbox->orig.y);
- glVertex2d(bbox->orig.x, bbox->corner.y);
- glVertex2d(bbox->corner.x, bbox->corner.y);
- glVertex2d(bbox->corner.x, bbox->orig.y);
- glEnd();
-}
-
-static void
-RenderField(ZnWInfo *wi,
- Field fptr,
- ZnBBox *bbox,
- ZnBBox *pm_bbox,
- ZnPoint *text_pos,
- ZnBBox *text_bbox,
- int cursor,
- int sel_start,
- int sel_stop)
-{
- unsigned short alpha;
- unsigned int j, num_bytes;
- XColor *color;
- ZnReal xs;
- ZnTextInfo *ti = &wi->text_info;
-
- ZnGLMakeCurrent(wi->dpy, wi);
- /*
- * Draw the background.
- */
- if (ISSET(fptr->flags, FILLED_BIT)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (!ZnGradientFlat(fptr->fill_color)) {
-#if 0 /* TODO_GL Faire le dégradé dans le fond des champs. */
- int type = fptr->fill_color->type;
- ZnBool fast = (type == ZN_AXIAL_GRADIENT) && !fptr->grad_geo;
-
- RenderGradient(wi, fptr->fill_color,
- fast ? NULL : FieldRenderCB,
- bbox, fast ? (ZnPoint *) bbox : fptr->grad_geo);
-#endif
- }
- else {
- if (fptr->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
- ZnRenderTile(wi, fptr->tile, fptr->fill_color, FieldRenderCB, bbox,
- (ZnPoint *) bbox);
- }
- else { /* Fill solid */
- color = ZnGetGradientColor(fptr->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- FieldRenderCB(bbox);
- }
- }
- }
-
- /*
- * Draw the image and the text, which one is back depends on
- * the value of text_on_top.
- */
- for (j = 0; j < 2; j++) {
- if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
- (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
- /*
- * Draw the image.
- */
- if (fptr->image != ZnUnspecifiedImage) {
- ZnRenderIcon(wi, fptr->image, fptr->fill_color,
- &pm_bbox->orig, False);
- }
- }
- else if (fptr->text) {
- /*
- * Draw the text.
- */
- num_bytes = strlen(fptr->text);
- if (num_bytes) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (sel_start >= 0) {
- color = ZnGetGradientColor(ti->sel_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glBegin(GL_QUADS);
- glVertex2d(text_bbox->orig.x+sel_start, text_bbox->orig.y);
- glVertex2d(text_bbox->orig.x+sel_stop, text_bbox->orig.y);
- glVertex2d(text_bbox->orig.x+sel_stop, text_bbox->corner.y);
- glVertex2d(text_bbox->orig.x+sel_start, text_bbox->corner.y);
- glEnd();
- }
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- color = ZnGetGradientColor(fptr->color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(fptr->tfi));
- glPushMatrix();
- glTranslated(text_pos->x, text_pos->y, 0.0);
- ZnRenderString(fptr->tfi, fptr->text, num_bytes);
- glPopMatrix();
- glDisable(GL_TEXTURE_2D);
- }
- }
- if (cursor >= 0) {
- glLineWidth((GLfloat) ti->insert_width);
- color = ZnGetGradientColor(ti->insert_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- xs = text_bbox->orig.x + cursor;
- glBegin(GL_LINES);
- glVertex2d(xs, text_bbox->orig.y);
- glVertex2d(xs, text_bbox->corner.y);
- glEnd();
- }
- }
-
- /*
- * Draw the border relief.
- */
- if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
- ZnPoint p[5];
-
- p[0].x = bbox->orig.x;
- p[0].y = bbox->orig.y;
- p[2].x = bbox->corner.x;
- p[2].y = bbox->corner.y;
- p[1].x = p[0].x;
- p[1].y = p[2].y;
- p[3].x = p[2].x;
- p[3].y = p[0].y;
- p[4] = p[0];
- ZnRenderPolygonRelief(wi, fptr->relief, fptr->gradient,
- False, p, 5, fptr->relief_thickness);
- }
-
- /*
- * Draw the border line.
- */
- if (fptr->border_edges != ZN_NO_BORDER) {
- color = ZnGetGradientColor(fptr->border_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glLineWidth(1.5);
- ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
- glBegin(GL_LINES);
- if (fptr->border_edges & ZN_LEFT_BORDER) {
- glVertex2d(bbox->orig.x, bbox->orig.y);
- glVertex2d(bbox->orig.x, bbox->corner.y);
- }
- if (fptr->border_edges & ZN_RIGHT_BORDER) {
- glVertex2d(bbox->corner.x, bbox->orig.y);
- glVertex2d(bbox->corner.x, bbox->corner.y);
- }
- if (fptr->border_edges & ZN_TOP_BORDER) {
- glVertex2d(bbox->orig.x, bbox->orig.y);
- glVertex2d(bbox->corner.x, bbox->orig.y);
- }
- if (fptr->border_edges & ZN_BOTTOM_BORDER) {
- glVertex2d(bbox->orig.x, bbox->corner.y);
- glVertex2d(bbox->corner.x, bbox->corner.y);
- }
- if (fptr->border_edges & ZN_OBLIQUE) {
- glVertex2d(bbox->orig.x, bbox->orig.y);
- glVertex2d(bbox->corner.x, bbox->corner.y);
- }
- if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
- glVertex2d(bbox->orig.x, bbox->corner.y);
- glVertex2d(bbox->corner.x, bbox->orig.y);
- }
- glEnd();
- }
-}
-#endif
-
-#ifdef GL
-static void
-RenderFields(ZnFieldSet field_set)
-{
- /* glDisable(GL_LINE_SMOOTH);*/
- FieldsEngine(field_set, RenderField);
- /* glEnable(GL_LINE_SMOOTH);*/
-}
-#else
-static void
-RenderFields(ZnFieldSet field_set)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * PostScriptFields --
- *
- **********************************************************************************
- */
-static int
-PsField(ZnWInfo *wi,
- ZnBool prepass,
- Field fptr,
- ZnBBox *bbox,
- ZnBBox *pm_bbox,
- ZnPoint *text_pos,
- ZnBBox *text_bbox)
-{
- int j;
- char path[250];
-
- /*
- * Must set the clip rect for the whole field, not only for stipple fill.
- */
- if (ISSET(fptr->flags, FILLED_BIT)) {
- if (fptr->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(fptr->tile)) { /* Fill tiled */
- /* TODO No support yet */
- }
- else { /* Fill stippled */
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
- ZnImagePixmap(fptr->tile, wi->win)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
- else { /* Fill solid */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "fill\n", NULL);
- }
- }
-
- /*
- * Draw the image and the text, which is in back depends on
- * the value of text_on_top.
- */
- for (j = 0; j < 2; j++) {
- if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
- (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
- /*
- * Draw the image.
- */
- if (fptr->image != ZnUnspecifiedImage) {
- int w, h;
-
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- sprintf(path, "%.15g %.15g translate 1 -1 scale\n",
- pm_bbox->orig.x, pm_bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- w = ZnNearestInt(pm_bbox->corner.x - pm_bbox->orig.x);
- h = ZnNearestInt(pm_bbox->corner.y - pm_bbox->orig.y);
- if (Tk_PostscriptImage(ZnImageTkImage(fptr->image), wi->interp, wi->win,
- wi->ps_info, 0, 0, w, h, prepass) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
- else if (fptr->text) {
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- if (Tk_PostscriptFont(wi->interp, wi->ps_info, fptr->font) != TCL_OK) {
- return TCL_ERROR;
- }
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(fptr->color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- /*
- * TODO pourquoi la text_bbox ne donne pas un texte centré verticalement ?
- * Apparement la fonte PostScript n'est pas centrée comme la fonte X.
- * Il faut donc opérer le calcul dans le code PostScript de DrawText.
- */
- sprintf(path, "%.15g %.15g translate 1 -1 scale 0 0 [\n",
- text_bbox->orig.x, text_bbox->orig.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- /*
- * strlen should do the work of counting _bytes_ in the utf8 string.
- */
- ZnPostscriptString(wi->interp, fptr->text, strlen(fptr->text));
- Tcl_AppendResult(wi->interp, "] 0 0.0 0.0 0.0 false DrawText\n", NULL);
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
-
- /*
- * Draw the border relief.
- */
- if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
- }
-
- /*
- * Draw the border line.
- */
- if (fptr->border_edges != ZN_NO_BORDER) {
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(fptr->border_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "1 setlinewidth 0 setlinejoin 2 setlinecap\n", NULL);
- if (fptr->border_edges & ZN_LEFT_BORDER) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->orig.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- if (fptr->border_edges & ZN_RIGHT_BORDER) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->corner.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- if (fptr->border_edges & ZN_TOP_BORDER) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->orig.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- if (fptr->border_edges & ZN_BOTTOM_BORDER) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->orig.x, bbox->corner.y, bbox->corner.x, bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- if (fptr->border_edges & ZN_OBLIQUE) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
- bbox->corner.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- }
-
- return TCL_OK;
-}
-
-static int
-PostScriptFields(ZnFieldSet field_set,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = field_set->item->wi;
- ZnBBox lclip_bbox, fclip_bbox;
- ZnBBox bbox, text_bbox, pm_bbox;
- ZnPoint text_pos;
- int i, num_fields;
- ZnDim lwidth, lheight;
- Field fptr;
- char path[250];
-
- if (!field_set->num_fields) {
- return TCL_OK;
- }
-
-
- if (field_set->label_format && ZnLFNumFields(field_set->label_format)) {
- /*
- * Fields are drawn with respect to a point already converted
- * to device space, so we need to reinstate the initial transform.
- */
- Tcl_AppendResult(wi->interp, "/InitialTransform load setmatrix\n", NULL);
-
- lclip_bbox.orig.x = ZnNearestInt(field_set->label_pos.x);
- lclip_bbox.orig.y = ZnNearestInt(field_set->label_pos.y);
- GetLabelBBox(field_set, &lwidth, &lheight);
- lclip_bbox.corner.x = lclip_bbox.orig.x + lwidth;
- lclip_bbox.corner.y = lclip_bbox.orig.y + lheight;
-
- num_fields = ZnLFNumFields(field_set->label_format);
- for (i = 0; i < num_fields; i++) {
- fptr = &field_set->fields[i];
-
- if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT)) {
- continue;
- }
-
- GetFieldBBox(field_set, i, &bbox);
- ZnIntersectBBox(&lclip_bbox, &bbox, &fclip_bbox);
- if (ZnIsEmptyBBox(&fclip_bbox)) {
- /* The field is outside the label bbox */
- continue;
- }
-
- /*
- * Setup a clip area around the field
- */
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g",
- fclip_bbox.orig.x, fclip_bbox.orig.y, fclip_bbox.corner.x+1, fclip_bbox.orig.y,
- fclip_bbox.corner.x+1, fclip_bbox.corner.y+1, fclip_bbox.orig.x,
- fclip_bbox.corner.y+1);
- Tcl_AppendResult(wi->interp, path, " lineto closepath clip\n", NULL);
-
- if (fptr->text) {
- ComputeFieldTextLocation(fptr, &bbox, &text_pos, &text_bbox);
- }
- if (fptr->image != ZnUnspecifiedImage) {
- ComputeFieldImageLocation(fptr, &bbox, &pm_bbox);
- }
-
- if (PsField(wi, prepass, fptr, &bbox, &pm_bbox, &text_pos, &text_bbox) != TCL_OK) {
- return TCL_ERROR;
- }
-
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * IsFieldsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsFieldSensitive(ZnFieldSet field_set,
- int part)
-{
- if ((part >= 0) && ((unsigned int) part < field_set->num_fields)) {
- return ISSET(field_set->fields[part].flags, FIELD_SENSITIVE_BIT);
- }
- else {
- return False;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * FieldsPick --
- * Return the first field that contains <x, y>.
- * A field is selected if <x, y> is over a non transparent area.
- * Such areas are : a solid filled background, a text, an icon.
- * This does *NOT* do with *GLOBAL* visible and sensitive.
- * But we need to take into account local field visible and
- * sensitive as they modifiy local transparency. Local means
- * within a single item.
- *
- **********************************************************************************
- */
-static double
-FieldsPick(ZnFieldSet field_set,
- ZnPoint *p,
- int *part)
-{
- Field fptr;
- ZnBBox bbox;
- unsigned int best_field = 0;
- int i;
- ZnReal new_dist, dist = 1e40;
-
- if (!field_set->num_fields) {
- return dist;
- }
-
- if (field_set->label_format) {
- for (i = ZnLFNumFields(field_set->label_format)-1; i >= 0; i--) {
- fptr = &field_set->fields[i];
-
- if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) &&
- ISCLEAR(fptr->flags, FIELD_SENSITIVE_BIT)) {
- continue;
- }
-
- GetFieldBBox(field_set, (unsigned int) i, &bbox);
-
- new_dist = ZnRectangleToPointDist(&bbox, p);
- if (new_dist < dist) {
- dist = new_dist;
- best_field = i;
- }
- if (dist <= 0.0) {
- dist = 0.0;
- break;
- }
- }
- }
-
- *part = best_field;
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * FieldsToArea --
- * Return -1 if no field is in the given area, 1 if they are
- * all in it or 0 if there is some overlap. The function consider
- * only fields that are either sensible or visible.
- *
- **********************************************************************************
- */
-static int
-FieldsToArea(ZnFieldSet field_set,
- ZnBBox *area)
-{
- Field fptr;
- ZnBBox bbox;
- int i, inside = -1;
- ZnBool first_done = False;
-
- if (!field_set->num_fields) {
- return inside;
- }
-
- for (i = ZnLFNumFields(field_set->label_format)-1; i >= 0; i--) {
- fptr = &field_set->fields[i];
-
- if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) &&
- ISCLEAR(fptr->flags, FIELD_SENSITIVE_BIT)) {
- continue;
- }
-
- GetFieldBBox(field_set, (unsigned int) i, &bbox);
- if (!first_done) {
- first_done = True;
- inside = ZnBBoxInBBox(&bbox, area);
- if (inside == 0) {
- return 0;
- }
- }
- else {
- if (ZnBBoxInBBox(&bbox, area) != inside) {
- return 0;
- }
- }
- }
-
- return inside;
-}
-
-
-/*
- **********************************************************************************
- *
- * SetFieldsAutoAlign --
- *
- **********************************************************************************
- */
-static void
-SetFieldsAutoAlign(ZnFieldSet fs,
- int alignment)
-{
- unsigned int i;
- Field field;
-
- if (!fs->num_fields) {
- return;
- }
- if ((alignment >= ZN_AA_LEFT) && (alignment <= ZN_AA_RIGHT)) {
- for (i = 0; i < fs->num_fields; i++) {
- field = &fs->fields[i];
- if (field->auto_alignment.automatic) {
- field->alignment = field->auto_alignment.align[alignment];
- }
- }
- }
-}
-
-static char *
-GetFieldStruct(ZnFieldSet fs,
- int field)
-{
- if ((unsigned int) field >= fs->num_fields) {
- return NULL;
- }
- return (char *) &fs->fields[field];
-}
-
-
-static unsigned int
-NumFields(ZnFieldSet fs)
-{
- return fs->num_fields;
-}
-
-
-struct _ZnFIELD ZnFIELD = {
- field_attrs,
-
- InitFields,
- CloneFields,
- FreeFields,
- ConfigureField,
- QueryField,
- DrawFields,
- RenderFields,
- PostScriptFields,
- FieldsToArea,
- IsFieldSensitive,
- FieldsPick,
- FieldIndex,
- FieldInsertChars,
- FieldDeleteChars,
- FieldCursor,
- FieldSelection,
- LeaderToLabel,
- GetLabelBBox,
- GetFieldBBox,
- SetFieldsAutoAlign,
- ClearFieldCache,
- GetFieldStruct,
- NumFields
-};
diff --git a/generic/Field.h b/generic/Field.h
deleted file mode 100644
index ad13663..0000000
--- a/generic/Field.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Field.h -- Header for field item parts.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 2002 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Field_h
-#define _Field_h
-
-#include "Attrs.h"
-#include "Types.h"
-#include "List.h"
-#include "Color.h"
-#include "Image.h"
-
-
-struct _ZnItemStruct;
-struct _ZnAttrConfig;
-
-
-/*
- * Field array management record.
- *
- * This structure should be used only for internal
- * management by items with fields. The rest of the code
- * should use the methods in FIELD.
- *
- */
-typedef struct _ZnFieldSetStruct {
- struct _ZnItemStruct *item;
- ZnLabelFormat label_format;
- unsigned int num_fields;
- struct _FieldStruct *fields;
- ZnDim label_width; /* Describe the label size. Access these */
- ZnDim label_height; /* 2 only with GetLabelBBox. -1 means
- * not up to date. */
- ZnPoint label_pos; /* Describe the label origin. */
-} ZnFieldSetStruct, *ZnFieldSet;
-
-
-extern struct _ZnFIELD {
- struct _ZnAttrConfig *attr_desc;
-
- void (*InitFields)(ZnFieldSet fs);
- void (*CloneFields)(ZnFieldSet fs);
- void (*FreeFields)(ZnFieldSet fs);
- int (*ConfigureField)(ZnFieldSet fs, int field, int argc, Tcl_Obj *CONST argv[], int *flags);
- int (*QueryField)(ZnFieldSet fs, int field, int argc, Tcl_Obj *CONST argv[]);
- void (*DrawFields)(ZnFieldSet fs);
- void (*RenderFields)(ZnFieldSet fs);
- int (*PostScriptFields)(ZnFieldSet fs, ZnBool prepass, ZnBBox *area);
- int (*FieldsToArea)(ZnFieldSet fs, ZnBBox *area);
- ZnBool (*IsFieldSensitive)(ZnFieldSet fs, int part);
- double (*FieldsPick)(ZnFieldSet fs, ZnPoint *p, int *part);
- int (*FieldIndex)(ZnFieldSet fs, int field, Tcl_Obj *index_spec, int *index);
- ZnBool (*FieldInsertChars)(ZnFieldSet fs, int field, int *index, char *chars);
- ZnBool (*FieldDeleteChars)(ZnFieldSet fs, int field,
- int *first, int *last);
- void (*FieldCursor)(ZnFieldSet fs, int field, int index);
- int (*FieldSelection)(ZnFieldSet fs, int field, int offset,
- char *chars, int max_chars);
- void (*LeaderToLabel)(ZnFieldSet fs, ZnPoint *start, ZnPoint *end);
- void (*GetLabelBBox)(ZnFieldSet fs, ZnDim *w, ZnDim *h);
- void (*GetFieldBBox)(ZnFieldSet fs, unsigned int index,
- ZnBBox *field_bbox);
- void (*SetFieldsAutoAlign)(ZnFieldSet fs, int alignment);
- void (*ClearFieldCache)(ZnFieldSet fs, int field);
- char *(*GetFieldStruct)(ZnFieldSet fs, int field);
- unsigned int (*NumFields)(ZnFieldSet fs);
-} ZnFIELD;
-
-
-#endif /* _Field_h */
diff --git a/generic/Geo.c b/generic/Geo.c
deleted file mode 100644
index 1fde494..0000000
--- a/generic/Geo.c
+++ /dev/null
@@ -1,3276 +0,0 @@
-/*
- * Geo.c -- Implementation of common geometric routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * Much of the code here is inspired by (or copied from) the Tk code.
- */
-
-
-#include "Geo.h"
-#include "WidgetInfo.h"
-
-#include <memory.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-void
-ZnPolyInit(ZnPoly *poly)
-{
- poly->num_contours = 0;
- poly->contours = NULL;
-}
-
-void
-ZnPolyContour1(ZnPoly *poly,
- ZnPoint *pts,
- unsigned int num_pts,
- ZnBool cw)
-{
- poly->num_contours = 1;
- poly->contours = &poly->contour1;
- poly->contour1.num_points = num_pts;
- poly->contour1.points = pts;
- poly->contour1.cw = cw;
- poly->contour1.controls = NULL;
-}
-
-void
-ZnPolySet(ZnPoly *poly1,
- ZnPoly *poly2)
-{
- ZnPolyFree(poly1);
- if (poly2->num_contours == 1) {
- ZnPolyContour1(poly1, poly2->contours[0].points, poly2->contours[0].num_points,
- poly2->contours[0].cw);
- if (poly2->contours != &poly2->contour1) {
- ZnFree(poly2->contours);
- }
- }
- else {
- poly1->num_contours = poly2->num_contours;
- poly1->contours = poly2->contours;
- }
-}
-
-void
-ZnPolyFree(ZnPoly *poly)
-{
- if (poly->num_contours) {
- unsigned int i;
- for (i = 0; i < poly->num_contours; i++) {
- ZnFree(poly->contours[i].points);
-/* if (poly->contours[i].controls) {
- ZnFree(poly->contours[i].controls);
- }*/
- }
- if (poly->contours != &poly->contour1) {
- ZnFree(poly->contours);
- }
- poly->num_contours = 0;
- poly->contours = NULL;
- }
-}
-
-void
-ZnTriStrip1(ZnTriStrip *tristrip,
- ZnPoint *pts,
- unsigned int num_pts,
- ZnBool fan)
-{
- tristrip->num_strips = 1;
- tristrip->strips = &tristrip->strip1;
- tristrip->strip1.points = pts;
- tristrip->strip1.num_points = num_pts;
- tristrip->strip1.fan = fan;
-}
-
-void
-ZnTriFree(ZnTriStrip *tristrip)
-{
- if (tristrip->num_strips) {
- unsigned int i;
- for (i = 0; i < tristrip->num_strips; i++) {
- ZnFree(tristrip->strips[i].points);
- }
- if (tristrip->strips != &tristrip->strip1) {
- ZnFree(tristrip->strips);
- }
- tristrip->num_strips = 0;
- tristrip->strips = NULL;
- }
-}
-
-/*
- * Compute the origin of the rectangle given
- * by position, anchor, width and height.
- */
-void
-ZnAnchor2Origin(ZnPoint *position,
- ZnDim width,
- ZnDim height,
- Tk_Anchor anchor,
- ZnPoint *origin)
-{
- switch (anchor) {
- case TK_ANCHOR_CENTER:
- origin->x = position->x - width/2;
- origin->y = position->y - height/2;
- break;
- case TK_ANCHOR_NW:
- *origin = *position;
- break;
- case TK_ANCHOR_N:
- origin->x = position->x - width/2;
- origin->y = position->y;
- break;
- case TK_ANCHOR_NE:
- origin->x = position->x - width;
- origin->y = position->y;
- break;
- case TK_ANCHOR_E:
- origin->x = position->x - width;
- origin->y = position->y - height/2;
- break;
- case TK_ANCHOR_SE:
- origin->x = position->x - width;
- origin->y = position->y - height;
- break;
- case TK_ANCHOR_S:
- origin->x = position->x - width/2;
- origin->y = position->y - height;
- break;
- case TK_ANCHOR_SW:
- origin->x = position->x;
- origin->y = position->y - height;
- break;
- case TK_ANCHOR_W:
- origin->x = position->x;
- origin->y = position->y - height/2;
- break;
- }
-}
-
-
-/*
- * Compute the anchor position given the bbox origin, width,
- * height and the anchor.
- */
-void
-ZnOrigin2Anchor(ZnPoint *origin,
- ZnDim width,
- ZnDim height,
- Tk_Anchor anchor,
- ZnPoint *position)
-{
- switch (anchor) {
- case TK_ANCHOR_CENTER:
- position->x = origin->x + width/2;
- position->y = origin->y + height/2;
- break;
- case TK_ANCHOR_NW:
- *position = *origin;
- break;
- case TK_ANCHOR_N:
- position->x = origin->x + width/2;
- position->y = origin->y;
- break;
- case TK_ANCHOR_NE:
- position->x = origin->x + width;
- position->y = origin->y;
- break;
- case TK_ANCHOR_E:
- position->x = origin->x + width;
- position->y = origin->y + height/2;
- break;
- case TK_ANCHOR_SE:
- position->x = origin->x + width;
- position->y = origin->y + height;
- break;
- case TK_ANCHOR_S:
- position->x = origin->x + width/2;
- position->y = origin->y + height;
- break;
- case TK_ANCHOR_SW:
- position->x = origin->x;
- position->y = origin->y + height;
- break;
- case TK_ANCHOR_W:
- position->x = origin->x;
- position->y = origin->y + height/2;
- break;
- }
-}
-
-/*
- * Compute the anchor position given a rectangle and
- * the anchor. The rectangle vertices must be ordered
- * as for a triangle strip:
- *
- * v0 ------------ v2
- * | |
- * | |
- * v1 ------------ v3
- */
-void
-ZnRectOrigin2Anchor(ZnPoint *rect,
- Tk_Anchor anchor,
- ZnPoint *position)
-{
- switch (anchor) {
- case TK_ANCHOR_CENTER:
- position->x = (rect[0].x + rect[3].x) / 2.0;
- position->y = (rect[0].y + rect[3].y) / 2.0;
- break;
- case TK_ANCHOR_NW:
- *position = *rect;
- break;
- case TK_ANCHOR_N:
- position->x = (rect[0].x + rect[2].x) / 2.0;
- position->y = (rect[0].y + rect[2].y) / 2.0;
- break;
- case TK_ANCHOR_NE:
- *position = rect[2];
- break;
- case TK_ANCHOR_E:
- position->x = (rect[2].x + rect[3].x) / 2.0;
- position->y = (rect[2].y + rect[3].y) / 2.0;
- break;
- case TK_ANCHOR_SE:
- *position = rect[3];
- break;
- case TK_ANCHOR_S:
- position->x = (rect[1].x + rect[3].x) / 2.0;
- position->y = (rect[1].y + rect[3].y) / 2.0;
- break;
- case TK_ANCHOR_SW:
- *position = rect[1];
- break;
- case TK_ANCHOR_W:
- position->x = (rect[0].x + rect[1].x) / 2.0;
- position->y = (rect[0].y + rect[1].y) / 2.0;
- break;
- }
-}
-
-void
-ZnBBox2XRect(ZnBBox *bbox,
- XRectangle *r)
-{
- r->x = ZnNearestInt(bbox->orig.x);
- r->y = ZnNearestInt(bbox->orig.y);
- r->width = ZnNearestInt(bbox->corner.x) - r->x;
- r->height = ZnNearestInt(bbox->corner.y) - r->y;
-}
-
-
-void
-ZnGetStringBBox(char *str,
- Tk_Font font,
- ZnPos x,
- ZnPos y,
- ZnBBox *str_bbox)
-{
- Tk_FontMetrics fm;
-
- str_bbox->orig.x = x;
- str_bbox->corner.x = x + Tk_TextWidth(font, str, (int) strlen(str));
- Tk_GetFontMetrics(font, &fm);
- str_bbox->orig.y = y - fm.ascent;
- str_bbox->corner.y = str_bbox->orig.y + fm.ascent + fm.descent;
-}
-
-
-void
-ZnResetBBox(ZnBBox *bbox)
-{
- bbox->orig.x = bbox->orig.y = 0;
- bbox->corner = bbox->orig;
-}
-
-
-void
-ZnCopyBBox(ZnBBox *bbox_from,
- ZnBBox *bbox_to)
-{
- bbox_to->orig = bbox_from->orig;
- bbox_to->corner = bbox_from->corner;
-}
-
-
-void
-ZnIntersectBBox(ZnBBox *bbox1,
- ZnBBox *bbox2,
- ZnBBox *bbox_inter)
-{
- if ((bbox1->corner.x < bbox2->orig.x) ||
- (bbox1->corner.y < bbox2->orig.y) ||
- (bbox2->corner.x < bbox1->orig.x) ||
- (bbox2->corner.y < bbox1->orig.y)) {
- ZnResetBBox(bbox_inter);
- }
- else {
- bbox_inter->orig.x = MAX(bbox1->orig.x, bbox2->orig.x);
- bbox_inter->orig.y = MAX(bbox1->orig.y, bbox2->orig.y);
- bbox_inter->corner.x = MIN(bbox1->corner.x, bbox2->corner.x);
- bbox_inter->corner.y = MIN(bbox1->corner.y, bbox2->corner.y);
- }
-}
-
-
-ZnBool
-ZnIsEmptyBBox(ZnBBox *bbox)
-{
- return (bbox->orig.x >= bbox->corner.x) || (bbox->orig.y >= bbox->corner.y);
-}
-
-
-void
-ZnAddBBoxToBBox(ZnBBox *bbox,
- ZnBBox *bbox2)
-{
- if (ZnIsEmptyBBox(bbox2)) {
- return;
- }
- if (ZnIsEmptyBBox(bbox)) {
- ZnCopyBBox(bbox2, bbox);
- }
- else {
- bbox->orig.x = MIN(bbox->orig.x, bbox2->orig.x);
- bbox->orig.y = MIN(bbox->orig.y, bbox2->orig.y);
- bbox->corner.x = MAX(bbox->corner.x, bbox2->corner.x);
- bbox->corner.y = MAX(bbox->corner.y, bbox2->corner.y);
- }
-}
-
-
-void
-ZnAddPointToBBox(ZnBBox *bbox,
- ZnPos px,
- ZnPos py)
-{
- if (ZnIsEmptyBBox(bbox)) {
- bbox->orig.x = px;
- bbox->orig.y = py;
- bbox->corner.x = bbox->orig.x + 1;
- bbox->corner.y = bbox->orig.y + 1;
- }
- else {
- bbox->orig.x = MIN(bbox->orig.x, px);
- bbox->orig.y = MIN(bbox->orig.y, py);
- bbox->corner.x = MAX(bbox->corner.x, px + 1);
- bbox->corner.y = MAX(bbox->corner.y, py + 1);
- }
-}
-
-
-void
-ZnAddPointsToBBox(ZnBBox *bbox,
- ZnPoint *points,
- unsigned int num_points)
-{
- ZnReal x1, y1, x2, y2, cur;
-
- if (points == NULL) {
- return;
- }
-
- if (num_points == 0) {
- return;
- }
-
- if (ZnIsEmptyBBox(bbox)) {
- x1 = points->x;
- y1 = points->y;
- x2 = x1 + 1;
- y2 = y1 + 1;
- num_points--;
- points++;
- }
- else {
- x1 = bbox->orig.x;
- y1 = bbox->orig.y;
- x2 = bbox->corner.x;
- y2 = bbox->corner.y;
- }
-
- for ( ; num_points > 0; num_points--, points++) {
- cur = points->x;
- if (cur < x1) {
- x1 = cur;
- }
- if (cur > x2) {
- x2 = cur;
- }
- cur = points->y;
- if (cur < y1) {
- y1 = cur;
- }
- if (cur > y2) {
- y2 = cur;
- }
- }
- bbox->orig.x = x1;
- bbox->orig.y = y1;
- if (x1 == x2) {
- x2++;
- }
- if (y1 == y2) {
- y2++;
- }
- bbox->corner.x = x2;
- bbox->corner.y = y2;
-}
-
-
-void
-ZnAddStringToBBox(ZnBBox *bbox,
- char *str,
- Tk_Font font,
- ZnPos cx,
- ZnPos cy)
-{
- ZnBBox str_bbox;
-
- ZnGetStringBBox(str, font, cx, cy, &str_bbox);
- ZnAddBBoxToBBox(bbox, &str_bbox);
-}
-
-ZnBool
-ZnPointInBBox(ZnBBox *bbox,
- ZnPos x,
- ZnPos y)
-{
- return ((x >= bbox->orig.x) && (x < bbox->corner.x) &&
- (y >= bbox->orig.y) && (y < bbox->corner.y));
-}
-
-
-/*
- * Tell where aa area is with respect to another area.
- * Return -1 if the first is entirely outside the second,
- * 1 if it is entirely inside and 0 otherwise.
- */
-int
-ZnBBoxInBBox(ZnBBox *bbox1,
- ZnBBox *bbox2)
-{
- if ((bbox1->corner.x <= bbox2->orig.x) ||
- (bbox1->orig.x >= bbox2->corner.x) ||
- (bbox1->corner.y <= bbox2->orig.y) ||
- (bbox1->orig.y >= bbox2->corner.y)) {
- return -1;
- }
- if ((bbox2->orig.x <= bbox1->orig.x) &&
- (bbox1->corner.x <= bbox2->corner.x) &&
- (bbox2->orig.y <= bbox1->orig.y) &&
- (bbox1->corner.y <= bbox2->corner.y)) {
- return 1;
- }
- return 0;
-}
-
-/*
- * Tell where a line is with respect to an area.
- * Return -1 if the line is entirely outside the bbox, 1
- * if it is entirely inside and 0 otherwise.
- */
-int
-ZnLineInBBox(ZnPoint *p1,
- ZnPoint *p2,
- ZnBBox *bbox)
-{
- ZnBool p1_inside = ZnPointInBBox(bbox, p1->x, p1->y);
- ZnBool p2_inside = ZnPointInBBox(bbox, p2->x, p2->y);
-
- if (p1_inside != p2_inside) {
- return 0;
- }
-
- if (p1_inside && p2_inside) {
- return 1;
- }
-
- /*
- * Segment may intersect area, check it more thoroughly.
- */
- /* Vertical line */
- if (p1->x == p2->x) {
- if (((p1->y >= bbox->orig.y) ^ (p2->y >= bbox->orig.y)) &&
- (p1->x >= bbox->orig.x) &&
- (p1->x <= bbox->corner.x)) {
- return 0;
- }
- }
- /* Horizontal line */
- else if (p1->y == p2->y) {
- if (((p1->x >= bbox->orig.x) ^ (p2->x >= bbox->orig.x)) &&
- (p1->y >= bbox->orig.y) &&
- (p1->y <= bbox->corner.y)) {
- return 0;
- }
- }
- /* Diagonal, do it the hard way. */
- else {
- ZnReal slope = (p2->y - p1->y) / (p2->x - p1->x);
- ZnDim low, high, x, y;
- ZnDim bbox_width = bbox->corner.x - bbox->orig.x;
- ZnDim bbox_height = bbox->corner.y - bbox->orig.y;
-
- /* Check against left edge */
- if (p1->x < p2->x) {
- low = p1->x;
- high = p2->x;
- }
- else {
- low = p2->x;
- high = p1->x;
- }
-
- y = p1->y + (bbox->orig.x - p1->x) * slope;
- if ((bbox->orig.x >= low) && (bbox->orig.x <= high) &&
- (y >= bbox->orig.y) && (y <= bbox->corner.y))
- return 0;
-
- /* Check against right edge */
- y += bbox_width * slope;
- if ((y >= bbox->orig.y) && (y <= bbox->corner.y) &&
- (bbox->corner.x >= low) && (bbox->corner.x <= high))
- return 0;
-
- /* Check against bottom edge */
- if (p1->y < p2->y) {
- low = p1->y;
- high = p2->y;
- }
- else {
- low = p2->y;
- high = p1->y;
- }
-
- x = p1->x + (bbox->orig.y - p1->y) / slope;
- if ((x >= bbox->orig.x) && (x <= bbox->corner.x) &&
- (bbox->orig.y >= low) && (bbox->orig.y <= high))
- return 0;
-
- /* Check against top edge */
- x += bbox_height / slope;
- if ((x >= bbox->orig.x) && (x <= bbox->corner.x) &&
- (bbox->corner.y >= low) && (bbox->corner.y <= high))
- return 0;
- }
-
- return -1;
-}
-
-
-ZnBool
-ZnTestCCW(ZnPoint *points,
- unsigned int num_points)
-{
- ZnPoint *p, *p_p=NULL, *p_n=NULL, min;
- ZnReal xprod;
- unsigned 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];
- /*printf("min index %d, prev %d, next %d\n", min_index,
- (min_index+(num_points-1))%num_points, (min_index+1)%num_points);*/
- /*printf("lower point index %d %d %d\n",
- (min_index+(num_points-1))%num_points, min_index, (min_index+1)%num_points);*/
- /*
- * Try to find preceding and following points that are not
- * the same as the base point.
- */
- for (i = 1; i < num_points; i++) {
- p_p = &points[(min_index+(num_points-i))%num_points]; /* min_index-1 */
- if ((p_p->x != p->x) || (p_p->y != p->y)) {
- break;
- }
- }
- for (i = 1; i < num_points; i++) {
- p_n = &points[(min_index+i)%num_points];
- if ((p_p->x != p->x) || (p_p->y != p->y)) {
- break;
- }
- }
- xprod = ((p->x - p_p->x) * (p_n->y - p->y)) - ((p->y - p_p->y) * (p_n->x - p->x));
- return (xprod < 0.0); /* Should be > 0 but X11 has Y axis reverted. */
-}
-
-
-/*
- * ZnShiftLine --
- * Given two points describing a line and a distance, return
- * to points describing a line parallel to it at the given distance.
- * When looking the line from p1 to p2 the new line will be dist away
- * on its left. Negative values are allowed for dist, resulting in a line
- * on the right.
- */
-void
-ZnShiftLine(ZnPoint *p1,
- ZnPoint *p2,
- ZnReal dist,
- ZnPoint *p3,
- ZnPoint *p4)
-{
- static int shift_table[129];
- ZnBool dx_neg, dy_neg;
- int dx, dy;
-
- /*
- * Initialize the conversion table.
- */
- if (shift_table[0] == 0) {
- int i;
- ZnReal tangent, cosine;
-
- for (i = 0; i <= 128; i++) {
- tangent = i/128.0;
- cosine = 128/cos(atan(tangent)) + 0.5;
- shift_table[i] = (int) cosine;
- }
- }
-
- *p3 = *p1;
- dx = (int) (p2->x - p1->x);
- dy = (int) (p2->y - p1->y);
- if (dx < 0) {
- dx = -dx;
- dx_neg = True;
- }
- else {
- dx_neg = False;
- }
- if (dy < 0) {
- dy = -dy;
- dy_neg = True;
- }
- else {
- dy_neg = False;
- }
- if ((dy < PRECISION_LIMIT) && (dx < PRECISION_LIMIT)) {
- fprintf(stderr, "ShiftLine: segment is a point\n");
- return;
- }
-
- if (dy <= dx) {
- dy = (((int) dist * shift_table[(dy*128)/dx]) + 64) / 128;
- if (!dx_neg) {
- dy = -dy;
- }
- p3->y += dy;
- }
- else {
- dx = (((int) dist * shift_table[(dx*128)/dy]) + 64) / 128;
- if (dy_neg) {
- dx = -dx;
- }
- p3->x += dx;
- }
-
- p4->x = p3->x + (p2->x - p1->x);
- p4->y = p3->y + (p2->y - p1->y);
-}
-
-
-/*
- * IntersectLines --
- * Given two lines described by two points, compute their intersection.
- * The function returns True if the lines are not parallel and False
- * otherwise.
- */
-ZnBool
-ZnIntersectLines(ZnPoint *a1,
- ZnPoint *a2,
- ZnPoint *b1,
- ZnPoint *b2,
- ZnPoint *pi)
-{
- ZnReal dxadyb, dxbdya, dxadxb, dyadyb, p, q;
-
- dxadyb = (a2->x - a1->x)*(b2->y - b1->y);
- dxbdya = (b2->x - b1->x)*(a2->y - a1->y);
- dxadxb = (a2->x - a1->x)*(b2->x - b1->x);
- dyadyb = (a2->y - a1->y)*(b2->y - b1->y);
-
- if (dxadyb == dxbdya) {
- return False;
- }
-
- p = a1->x*dxbdya - b1->x*dxadyb + (b1->y - a1->y)*dxadxb;
- q = dxbdya - dxadyb;
- if (q < 0) {
- p = -p;
- q = -q;
- }
- if (p < 0) {
- pi->x = - ((-p + q/2)/q);
- }
- else {
- pi->x = (p + q/2)/q;
- }
-
- p = a1->y*dxadyb - b1->y*dxbdya + (b1->x - a1->x)*dyadyb;
- q = dxadyb - dxbdya;
- if (q < 0) {
- p = -p;
- q = -q;
- }
- if (p < 0) {
- pi->y = - ((-p + q/2)/q);
- }
- else {
- pi->y = (p + q/2)/q;
- }
-
- return True;
-}
-
-
-/*
- * InsetPolygon --
- * Inset the given polygon by the given amount. The
- * value can be negative, in this case the polygon will
- * be outset.
- */
-/**** A FINIR ****/
-void
-ZnInsetPolygon(ZnPoint *p,
- unsigned int num_points,
- ZnDim inset)
-{
- ZnPoint *p1, *p2;
- ZnPoint new_p1, new_p2;
- /* ZnPoint shift1, shift2;*/
- unsigned int i, processed_points;
-
- processed_points = 0;
-
- if ((p->x == p[num_points-1].x) && (p->y == p[num_points-1].y)) {
- num_points--;
- }
- for (p1 = p, p2 = p1+1, i = 0; i < num_points; i++, p1 = p2, p2++) {
- /*
- * Wrap to the first point.
- */
- if (i == num_points-1) {
- p2 = p;
- }
- /*
- * Skip duplicate vertices.
- */
- if ((p2->x == p1->x) && (p2->y == p1->y)) {
- continue;
- }
-
- ZnShiftLine(p1, p2, inset, &new_p1, &new_p2);
-
- if (processed_points >= 1) {
- }
- }
-}
-
-
-/*
- * Compute the two corner points of a thick line end.
- * Two points describing the line segment and the width
- * are given as input. If projecting is true this function
- * mimics the X11 line projecting behaviour. The computed
- * end is located around p2.
- */
-void
-ZnGetButtPoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim width,
- ZnBool projecting,
- ZnPoint *c1,
- ZnPoint *c2)
-{
- ZnReal w_2 = width/2.0;
- ZnDim length = hypot(p2->x - p1->x, p2->y - p1->y);
- ZnReal delta_x, delta_y;
-
- if (length == 0.0) {
- c1->x = c2->x = p2->x;
- c1->y = c2->y = p2->y;
- }
- else {
- delta_x = -w_2 * (p2->y - p1->y) / length;
- delta_y = w_2 * (p2->x - p1->x) / length;
- c1->x = p2->x + delta_x;
- c2->x = p2->x - delta_x;
- c1->y = p2->y + delta_y;
- c2->y = p2->y - delta_y;
- if (projecting) {
- c1->x += delta_y;
- c2->x += delta_y;
- c1->y -= delta_x;
- c2->y -= delta_x;
- }
- }
-}
-
-/*
- * Compute the inside and outside points of the mitered
- * corner formed by a thick line going through 3 points.
- * If the angle formed by the three points is less than
- * 11 degrees, False is returned an no points are computed.
- * Else True is returned and the points are in c1, c2.
- *
- * If someday the code is switched to REAL coordinates, we
- * must round each coordinate to the nearer integer to mimic
- * the way pixels are drawn. Sample code: floor(p->x+0.5);
- *
- * Hmmm, the switch has been done but not the rounding ;-)
- */
-ZnBool
-ZnGetMiterPoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnPoint *p3,
- ZnDim width,
- ZnPoint *c1,
- ZnPoint *c2)
-{
- static ZnReal deg11 = (11.0*2.0*M_PI)/360.0;
- ZnReal theta1; /* angle of p2-p1 segment. */
- ZnReal theta2; /* angle of p2-p3 segment. */
- ZnReal theta; /* angle of the joint */
- ZnReal theta3; /* angle of bisector of the joint toward
- * the external point of the joint. */
- ZnReal dist; /* distance of the external points
- * of the corner from the mid point
- * p2. */
- ZnReal delta_x, delta_y; /* projection of (dist,theta3) on x
- * and y. */
-
- if (p2->y == p1->y) {
- theta1 = (p2->x < p1->x) ? 0.0 : M_PI;
- }
- else if (p2->x == p1->x) {
- theta1 = (p2->y < p1->y) ? M_PI/2.0 : -M_PI/2.0;
- }
- else {
- theta1 = atan2(p1->y - p2->y, p1->x - p2->x);
- }
- if (p3->y == p2->y) {
- theta2 = (p3->x > p2->x) ? 0.0 : M_PI;
- }
- else if (p3->x == p2->x) {
- theta2 = (p3->y > p2->y) ? M_PI/2.0 : -M_PI/2.0;
- }
- else {
- theta2 = atan2(p3->y - p2->y, p3->x - p2->x);
- }
- theta = theta1 - theta2;
- if (theta > M_PI) {
- theta -= 2.0*M_PI;
- }
- else if (theta < -M_PI) {
- theta += 2*M_PI;
- }
- if ((theta < deg11) && (theta > -deg11)) {
- return False;
- }
- /*
- * Compute the distance of the internal and external
- * corner points from the intersection p2 (considered
- * at 0,0).
- */
- dist = 0.5*width / sin(0.5*theta);
- dist = ABS(dist);
-
- /*
- * Compute the angle of the bisector of the joint that
- * goes toward the outside of the joint (the left hand
- * when looking from p1-p2).
- */
- theta3 = (theta1 + theta2)/2.0;
- if (sin(theta3 - (theta1 + M_PI)) < 0.0) {
- theta3 += M_PI;
- }
-
- delta_x = dist * cos(theta3);
- c1->x = p2->x + delta_x;
- c2->x = p2->x - delta_x;
- delta_y = dist * sin(theta3);
- c1->y = p2->y + delta_y;
- c2->y = p2->y - delta_y;
-
- return True;
-}
-
-/*
- * Tell where a thick polyline is with respect to an area.
- * Return -1 if the polyline is entirely outside the bbox, 1
- * if it is entirely inside and 0 otherwise. The joints can
- * be specified as JoinMiter, JoinRound, JoinBevel. The ends
- * can be: CapRound, CapButt, CapProjecting.
- */
-int
-ZnPolylineInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim width,
- int cap_style,
- int join_style,
- ZnBBox *bbox)
-{
- unsigned int count;
- int inside = -1;
- ZnBool do_miter_as_bevel;
- ZnPoint poly[4];
-
- /*
- * If the first point is inside the area, change inside
- * accordingly.
- */
- if ((points[0].x >= bbox->orig.x) && (points[0].x <= bbox->corner.x) &&
- (points[0].y >= bbox->orig.y) && (points[0].y <= bbox->corner.y)) {
- inside = 1;
- }
-
- /*
- * Now iterate through all the edges. Compute a polygon for
- * each and test it against the area. At each vertex an oval
- * of radius width/2 is also tested to account for round ends
- * and joints.
- */
- do_miter_as_bevel = False;
- for (count = num_points; count >= 2; count--, points++) {
-
- /*
- * Test a circle around the first point if CapRound or
- * around every joint if JoinRound.
- */
- if (((cap_style == CapRound) && (count == num_points)) ||
- ((join_style == JoinRound) && (count != num_points))) {
- if (ZnOvalInBBox(points, width, width, bbox) != inside) {
- return 0;
- }
- }
- /*
- * Build a polygon to represent an edge from the current
- * point to the next. Special cases for the first and
- * last edges to implement the line ends.
- */
- /*
- * First vertex of the edge
- */
- if (count == num_points) {
- ZnGetButtPoints(&points[1], points, width,
- cap_style == CapProjecting, poly, &poly[1]);
- }
- /*
- * Here we are at a joint starting a new edge. If the
- * joint is mitered, start by carrying over the points
- * from the previous edge. Otherwise compute new points
- * for a butt end.
- */
- else if ((join_style == JoinMiter) && !do_miter_as_bevel) {
- poly[0] = poly[3];
- poly[1] = poly[2];
- }
- else {
- ZnGetButtPoints(&points[1], points, width, 0, poly, &poly[1]);
- /*
- * If the previous joint was beveled (or considered so),
- * check the polygon that fill the bevel. It has more or
- * less an X shape, i.e, it's self intersecting. If this
- * is not ok, it may be necessary to permutte poly[1] &
- * poly[2].
- */
- if ((join_style == JoinBevel) || do_miter_as_bevel) {
- if (ZnPolygonInBBox(poly, 4, bbox, NULL) != inside) {
- return 0;
- }
- do_miter_as_bevel = False;
- }
- }
-
- /*
- * Opposite vertex of the edge.
- */
- if (count == 2) {
- ZnGetButtPoints(points, &points[1], width, cap_style == CapProjecting,
- &poly[2], &poly[3]);
- }
- else if (join_style == JoinMiter) {
- if (ZnGetMiterPoints(points, &points[1], &points[2], width,
- &poly[2], &poly[3]) == False) {
- do_miter_as_bevel = True;
- ZnGetButtPoints(points, &points[1], width, 0, &poly[2], &poly[3]);
- }
- }
- else {
- ZnGetButtPoints(points, &points[1], width, 0, &poly[2], &poly[3]);
- }
-
- if (ZnPolygonInBBox(poly, 4, bbox, NULL) != inside) {
- return 0;
- }
- }
-
- /*
- * Test a circle around the last point if CapRound.
- */
- if (cap_style == CapRound) {
- if (ZnOvalInBBox(points, width, width, bbox) != inside) {
- return 0;
- }
- }
-
- return inside;
-}
-
-
-/*
- * Tell where a polygon is with respect to an area.
- * Return -1 if the polygon is entirely outside the bbox, 1
- * if it is entirely inside and 0 otherwise. If area_enclosed
- * is not NULL it tells whether the area is enclosed by the
- * polygon or not.
- */
-int
-ZnPolygonInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnBBox *bbox,
- ZnBool *area_enclosed)
-{
- int inside, count;
- ZnPoint *p, *head, *first, *second;
- ZnBool closed;
-
- if (area_enclosed) {
- *area_enclosed = False;
- }
- p = head = points;
- closed = True;
- count = num_points-2;
- /*
- * Check to see if closed. If not adjust num_points and
- * record this.
- */
- if ((points[0].x != points[num_points-1].x) ||
- (points[0].y != points[num_points-1].y)) {
- closed = False;
- count = num_points-1;
- }
-
- /*
- * Get the status of the first edge.
- */
- inside = ZnLineInBBox(&p[0], &p[1], bbox);
- p++;
- if (inside == 0) {
- return 0;
- }
- for (; count > 0; p++, count--) {
- first = &p[0];
- /*
- * Pretend the polygon is closed if this is not the case.
- */
- if (!closed && (count == 1)) {
- second = head;
- }
- else {
- second = &p[1];
- }
-
- if (ZnLineInBBox(first, second, bbox) != inside) {
- return 0;
- }
- }
-
- /*
- * If all the edges are inside the area, the polygon is
- * inside the area. If all the edges are outside, the polygon
- * may completely enclose the area. Test if the origin of
- * the area is inside the polygon to decide this.
- */
- if (inside == 1) {
- return 1;
- }
-
- /*printf("PolygonInBBox, np = %d, x = %g, y = %g, dist = %g\n",
- num_points, bbox->orig.x, bbox->orig.y,
- PolygonToPointDist(points, num_points, &bbox->orig));*/
- if (ZnPolygonToPointDist(points, num_points, &bbox->orig) <= 0.0) {
- if (area_enclosed) {
- *area_enclosed = True;
- }
- return 0;
- }
-
- return -1;
-}
-
-
-/*
- * Tell where an oval is with respect to an area.
- * Return -1 if the oval is entirely outside the bbox, 1
- * if it is entirely inside and 0 otherwise.
- */
-int
-ZnOvalInBBox(ZnPoint *center,
- ZnDim width,
- ZnDim height,
- ZnBBox *bbox)
-{
- ZnPoint origin, corner;
- ZnDim w_2, h_2;
- ZnReal delta_x, delta_y;
-
- w_2 = (width+1)/2;
- h_2 = (height+1)/2;
-
- origin.x = center->x - w_2;
- origin.y = center->y - h_2;
- corner.x = center->x + w_2;
- corner.y = center->y + h_2;
-
- /*
- * This if the oval bbox is completely inside or outside
- * of the area. Trivial case first.
- */
- if ((bbox->orig.x <= origin.x) && (bbox->corner.x >= corner.x) &&
- (bbox->orig.y <= origin.y) && (bbox->corner.y >= corner.y)) {
- return 1;
- }
- if ((bbox->corner.x < origin.x) || (bbox->orig.x > corner.x) ||
- (bbox->corner.y < origin.y) || (bbox->orig.y > corner.y)) {
- return -1;
- }
-
- /*
- * Then test all sides of the area against the oval center.
- * If the point of a side closest to the center is inside
- * the oval, then the oval intersects the area.
- */
-
- /*
- * Compute the square of the Y axis distance, reducing
- * the oval to a unit circle to take into account the
- * shape factor.
- */
- delta_y = bbox->orig.y - center->y;
- if (delta_y < 0.0) {
- delta_y = center->y - bbox->corner.y;
- if (delta_y < 0.0) {
- delta_y = 0.0;
- }
- }
- delta_y /= h_2;
- delta_y *= delta_y;
-
- /*
- * Test left and then right edges.
- */
- delta_x = (bbox->orig.x - center->x) / w_2;
- delta_x *= delta_x;
- if ((delta_x + delta_y) <= 1.0) {
- return 0;
- }
- delta_x = (bbox->corner.x - center->x) / w_2;
- delta_x *= delta_x;
- if ((delta_x + delta_y) <= 1.0) {
- return 0;
- }
-
- /*
- * Compute the square of the X axis distance, reducing
- * the oval to a unit circle to take into account the
- * shape factor.
- */
- delta_x = bbox->orig.x - center->x;
- if (delta_x < 0.0) {
- delta_x = center->x - bbox->corner.x;
- if (delta_x < 0.0) {
- delta_x = 0.0;
- }
- }
- delta_x /= w_2;
- delta_x *= delta_x;
-
- /*
- * Test top and then bottom edges.
- */
- delta_y = (bbox->orig.y - center->y) / h_2;
- delta_y *= delta_y;
- if ((delta_x + delta_y) <= 1.0) {
- return 0;
- }
- delta_y = (bbox->corner.y - center->y) / h_2;
- delta_y *= delta_y;
- if ((delta_x + delta_y) <= 1.0) {
- return 0;
- }
-
- return -1;
-}
-
-
-/*
- * Tell if a point is in an angular range whose center is 0,0.
- * The range is specified by a starting angle and an angle extent.
- * The use of a double here is important, don't change it. In some
- * case we need to normalize a figure to take care of its shape and
- * the result needs precision.
- */
-ZnBool
-ZnPointInAngle(int start_angle,
- int angle_extent,
- ZnPoint *p)
-{
- ZnReal point_angle;
- int angle_diff;
-
- if ((p->x == 0) && (p->y == 0)) {
- point_angle = 0.0;
- }
- else {
- point_angle = atan2(p->y, p->x) * 180.0 / M_PI;
- }
- angle_diff = (ZnNearestInt(point_angle) - start_angle) % 360;
- if (angle_diff < 0) {
- angle_diff += 360;
- }
- return ((angle_diff <= angle_extent) ||
- ((angle_extent < 0) && ((angle_diff - 360) >= angle_extent)));
-}
-
-/*
- * PointPolarToCartesian --
- * Convert a point in polar coordinates (rho, theta)
- * in a reference system described by angle heading
- * (angles running clockwise) to a point in cartesian
- * coordinates (delta_x, delta_y).
- *
- */
-void
-ZnPointPolarToCartesian(ZnReal heading,
- ZnReal rho,
- ZnReal theta,
- ZnReal *delta_x,
- ZnReal *delta_y)
-{
- ZnReal to_angle;
-
- /* Compute angle in trigonometric system */
- /* to_angle = ZnDegRad(theta) + heading - M_PI_2;*/
- to_angle = heading - ZnDegRad(theta) - M_PI_2;
- /* Compute cartesian coordinates */
- *delta_x = rho * cos(to_angle);
- *delta_y = rho * sin(to_angle);
-}
-
-/*
- * Return a vector angle given its projections
- */
-ZnReal
-ZnProjectionToAngle(ZnReal dx,
- ZnReal dy)
-{
- if (dx == 0) {
- if (dy < 0) {
- return -M_PI_2;
- }
- else if (dy > 0) {
- return M_PI_2;
- }
- else {
- return 0.0;
- }
- }
- else if (dx < 0) {
- return atan(dy / dx) - M_PI;
- }
- else {
- return atan(dy / dx);
- }
- return 0.0;
-}
-
-
-/*
- * Tell if an horizontal line intersect an axis aligned
- * elliptical arc.
- *
- * Returns True if the line described by (x1, x2, y) intersects
- * the arc described by (r1, r2, start_angle and angle_extent).
- * This arc is origin centered.
- */
-ZnBool
-ZnHorizLineToArc(ZnReal x1,
- ZnReal x2,
- ZnReal y,
- ZnReal rx,
- ZnReal ry,
- int start_angle,
- int angle_extent)
-{
- ZnReal tmp, x;
- ZnPoint t;
-
- /*
- * Compute the x-coordinate of one possible intersection point
- * between the arc and the line. Use a transformed coordinate
- * system where the oval is a unit circle centered at the origin.
- * Then scale back to get actual x-coordinate.
- */
- t.y = y/ry;
- tmp = 1 - t.y*t.y;
- if (tmp < 0.0) {
- return False;
- }
- t.x = sqrt(tmp);
- x = t.x*rx;
-
- /*
- * Test both intersection points.
- */
- if ((x >= x1) && (x <= x2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
- return True;
- }
- t.x = -t.x;
- if ((-x >= x1) && (-x <= x2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
- return True;
- }
- return False;
-}
-
-
-/*
- * Tell if an vertical line intersect an axis aligned
- * elliptical arc.
- *
- * Returns True if the line described by (x1, x2, y) intersects
- * the arc described by (r1, r2, start_angle and angle_extent).
- * This arc is origin centered.
- */
-ZnBool
-ZnVertLineToArc(ZnReal x,
- ZnReal y1,
- ZnReal y2,
- ZnReal rx,
- ZnReal ry,
- int start_angle,
- int angle_extent)
-{
- ZnReal tmp, y;
- ZnPoint t;
-
- /*
- * Compute the y-coordinate of one possible intersection point
- * between the arc and the line. Use a transformed coordinate
- * system where the oval is a unit circle centered at the origin.
- * Then scale back to get actual y-coordinate.
- */
- t.x = x/rx;
- tmp = 1 - t.x*t.x;
- if (tmp < 0.0) {
- return False;
- }
- t.y = sqrt(tmp);
- y = t.y*ry;
-
- /*
- * Test both intersection points.
- */
- if ((y > y1) && (y < y2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
- return True;
- }
- t.y = -t.y;
- if ((-y > y1) && (-y < y2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
- return True;
- }
- return False;
-}
-
-
-/*
- * Return the distance of the given point to the rectangle
- * described by rect. Return negative values for points in
- * the rectangle.
- */
-ZnDim
-ZnRectangleToPointDist(ZnBBox *bbox,
- ZnPoint *p)
-{
- ZnDim new_dist, dist;
- ZnPoint p1, p2;
-
- p1.x = bbox->orig.x;
- p1.y = p2.y = bbox->orig.y;
- p2.x = bbox->corner.x;
- dist = ZnLineToPointDist(&p1, &p2, p, NULL);
- if (dist == 0.0) {
- return 0.0;
- }
-
- p1 = p2;
- p2.y = bbox->corner.y;
- new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
- dist = MIN(dist, new_dist);
- if (dist == 0.0) {
- return 0.0;
- }
-
- p1 = p2;
- p2.x = bbox->orig.x;
- new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
- dist = MIN(dist, new_dist);
- if (dist == 0.0) {
- return 0.0;
- }
-
- p1 = p2;
- p2.y = bbox->orig.y;
- new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
- dist = MIN(dist, new_dist);
-
- if (ZnPointInBBox(bbox, p->x, p->y)) {
- return -dist;
- }
- else {
- return dist;
- }
-}
-
-
-/*
- * Return the distance of the given point to the line
- * described by <xl1,yl1>, <xl2,yl2>..
- */
-ZnDim
-ZnLineToPointDist(ZnPoint *p1,
- ZnPoint *p2,
- ZnPoint *p,
- ZnPoint *closest)
-{
- ZnReal x, y;
- ZnReal x_int, y_int;
-
- /*
- * First compute the closest point on the line. This is done
- * separately for vertical, horizontal, other lines.
- */
-
- /* Vertical */
- if (p1->x == p2->x) {
- x = p1->x;
- if (p1->y >= p2->y) {
- y_int = MIN(p1->y, p->y);
- y_int = MAX(y_int, p2->y);
- }
- else {
- y_int = MIN(p2->y, p->y);
- y_int = MAX(y_int, p1->y);
- }
- y = y_int;
- }
-
- /* Horizontal */
- else if (p1->y == p2->y) {
- y = p1->y;
- if (p1->x >= p2->x) {
- x_int = MIN(p1->x, p->x);
- x_int = MAX(x_int, p2->x);
- }
- else {
- x_int = MIN(p2->x, p->x);
- x_int = MAX(x_int, p1->x);
- }
- x = x_int;
- }
-
- /*
- * Other. Compute its parameters of form y = a1*x + b1 and
- * then compute the parameters of the perpendicular passing
- * through the point y = a2*x + b2, last find the closest point
- * on the segment.
- */
- else {
- ZnReal a1, a2, b1, b2;
-
- a1 = (p2->y - p1->y) / (p2->x - p1->x);
- b1 = p1->y - a1*p1->x;
-
- a2 = -1.0/a1;
- b2 = p->y - a2*p->x;
-
- x = (b2 - b1) / (a1 - a2);
- y = a1*x + b1;
-
- if (p1->x > p2->x) {
- if (x > p1->x) {
- x = p1->x;
- y = p1->y;
- }
- else if (x < p2->x) {
- x = p2->x;
- y = p2->y;
- }
- }
- else {
- if (x > p2->x) {
- x = p2->x;
- y = p2->y;
- }
- else if (x < p1->x) {
- x = p1->x;
- y = p1->y;
- }
- }
- }
-
- if (closest) {
- closest->x = x;
- closest->y = y;
- }
-
- /* Return the distance */
- return hypot(p->x - x, p->y - y);
-}
-
-
-/*
- * Return the distance of the polygon described by
- * points, to the given point. If the point is
- * inside return values are negative.
- */
-ZnDim
-ZnPolygonToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnPoint *p)
-{
- ZnDim best_distance, dist;
- int intersections;
- int x_int, y_int;
- ZnPoint *first_point;
- ZnReal x, y;
- ZnPoint p1, p2;
-
- /*
- * The algorithm iterates through all the edges of the polygon
- * computing for each the distance to the point and whether a vertical
- * ray starting at the point, intersects the edge. The smallest
- * distance of all edges is stored in best_distance while intersections
- * hold the count of edges to rays intersections. For more informations
- * on how the distance is computed see LineToPointDist.
- */
- best_distance = 1.0e40;
- intersections = 0;
-
- first_point = points;
-
- /*
- * Check to see if closed. Adjust num_points to open it (the
- * algorithm always consider a set of points as a closed polygon).
- */
- if ((points[0].x == points[num_points-1].x) &&
- (points[0].y == points[num_points-1].y)) {
- num_points--;
- }
-
- for ( ; num_points >= 1; num_points--, points++) {
- p1 = points[0];
- /*
- * Wrap over to the first point.
- */
- if (num_points == 1) {
- p2 = *first_point;
- }
- else {
- p2 = points[1];
- }
-
- /*
- * First try to find the closest point on this edge.
- */
-
- /* Vertical edge */
- if (p1.x == p2.x) {
- x = p1.x;
- if (p1.y >= p2.y) {
- y_int = (int) MIN(p1.y, p->y);
- y_int = (int) MAX(y_int, p2.y);
- }
- else {
- y_int = (int) MIN(p2.y, p->y);
- y_int = (int) MAX(y_int, p1.y);
- }
- y = y_int;
- }
-
- /* Horizontal edge */
- else if (p1.y == p2.y) {
- y = p1.y;
- if (p1.x >= p2.x) {
- x_int = (int) MIN(p1.x, p->x);
- x_int = (int) MAX(x_int, p2.x);
- if ((p->y < y) && (p->x < p1.x) && (p->x >= p2.x)) {
- intersections++;
- }
- }
- else {
- x_int = (int) MIN(p2.x, p->x);
- x_int = (int) MAX(x_int, p1.x);
- if ((p->y < y) && (p->x < p2.x) && (p->x >= p1.x)) {
- intersections++;
- }
- }
- x = x_int;
- }
-
- /* Other */
- else {
- ZnReal a1, b1, a2, b2;
-
- a1 = (p2.y - p1.y) / (p2.x - p1.x);
- b1 = p1.y - a1 * p1.x;
-
- a2 = -1.0/a1;
- b2 = p->y - a2 * p->x;
-
- x = (b2 - b1)/(a1 - a2);
- y = a1 * x + b1;
-
- if (p1.x > p2.x) {
- if (x > p1.x) {
- x = p1.x;
- y = p1.y;
- }
- else if (x < p2.x) {
- x = p2.x;
- y = p2.y;
- }
- }
- else {
- if (x > p2.x) {
- x = p2.x;
- y = p2.y;
- }
- else if (x < p1.x) {
- x = p1.x;
- y = p1.y;
- }
- }
-
- if (((a1 * p->x + b1) > p->y) && /* True if point is lower */
- (p->x >= MIN(p1.x, p2.x)) &&
- (p->x < MAX(p1.x, p2.x))) {
- intersections++;
- }
- }
-
- /*
- * Now compute the distance to the closest point and
- * keep it if it is the shortest.
- */
- dist = hypot(p->x - x, p->y - y);
- best_distance = MIN(best_distance, dist);
- /*
- * We can safely escape here if distance is zero.
- */
- if (best_distance == 0.0) {
- return 0.0;
- }
- }
-
- /*
- * Well, all the edges are processed, if the
- * intersection count is odd the point is inside.
- */
- if (intersections & 0x1) {
- return -best_distance;
- }
- else {
- return best_distance;
- }
-}
-
-
-/*
- * Return the distance of a thick polyline to the
- * given point. Cap and Join parameters are considered
- * in the process.
- */
-ZnDim
-ZnPolylineToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnDim width,
- int cap_style,
- int join_style,
- ZnPoint *p)
-{
- ZnBool miter2bevel = False;
- unsigned int count;
- ZnPoint *ptr;
- ZnPoint outline[5];
- ZnDim dist, best_dist, h_width;
-
- best_dist = 1.0e36;
- h_width = width/2.0;
-
- for (count = num_points, ptr = points; count >= 2; count--, ptr++) {
- if (((cap_style == CapRound) && (count == num_points)) ||
- ((join_style == JoinRound) && (count != num_points))) {
- dist = hypot(ptr->x - p->x, ptr->y - p->y) - h_width;
- if (dist <= 0.0) {
- best_dist = 0.0;
- goto done;
- }
- else if (dist < best_dist) {
- best_dist = dist;
- }
- }
- /*
- * Build the polygonal outline of the current edge.
- */
- if (count == num_points) {
- ZnGetButtPoints(&ptr[1], ptr, width, cap_style==CapProjecting, outline, &outline[1]);
- }
- else if ((join_style == JoinMiter) && !miter2bevel) {
- outline[0] = outline[3];
- outline[1] = outline[2];
- }
- else {
- ZnGetButtPoints(&ptr[1], ptr, width, 0, outline, &outline[1]);
- /*
- * If joints are beveled, check the distance to the polygon
- * that fills the joint.
- */
- if ((join_style == JoinBevel) || miter2bevel) {
- outline[4] = outline[0];
- dist = ZnPolygonToPointDist(outline, 5, p);
- if (dist <= 0.0) {
- best_dist = 0.0;
- goto done;
- }
- else if (dist < best_dist) {
- best_dist = dist;
- }
- miter2bevel = False;
- }
- }
- if (count == 2) {
- ZnGetButtPoints(ptr, &ptr[1], width, cap_style==CapProjecting,
- &outline[2], &outline[3]);
- }
- else if (join_style == JoinMiter) {
- if (ZnGetMiterPoints(ptr, &ptr[1], &ptr[2], width,
- &outline[2], &outline[3]) == False) {
- miter2bevel = True;
- ZnGetButtPoints(ptr, &ptr[1], width, 0, &outline[2], &outline[3]);
- }
- /*printf("2=%g+%g, 3=%g+%g\n",
- outline[2].x, outline[2].y, outline[3].x, outline[3].y);*/
- }
- else {
- ZnGetButtPoints(ptr, &ptr[1], width, 0, &outline[2], &outline[3]);
- }
- outline[4] = outline[0];
- /*printf("0=%g+%g, 1=%g+%g, 2=%g+%g, 3=%g+%g, 4=%g+%g\n",
- outline[0].x, outline[0].y, outline[1].x, outline[1].y,
- outline[2].x, outline[2].y, outline[3].x, outline[3].y,
- outline[4].x, outline[4].y);*/
- dist = ZnPolygonToPointDist(outline, 5, p);
- if (dist <= 0.0) {
- best_dist = 0.0;
- goto done;
- }
- else if (dist < best_dist) {
- best_dist = dist;
- }
- }
-
- /*
- * Test the final point if cap style is round. The code so far
- * has only handled the butt and projecting cases.
- */
- if (cap_style == CapRound) {
- dist = hypot(ptr->x - p->x, ptr->y - p->y) - h_width;
- if (dist <= 0.0) {
- best_dist = 0.0;
- goto done;
- }
- else if (dist < best_dist) {
- best_dist = dist;
- }
- }
-
- done:
- return best_dist;
-}
-
-
-/*
- * Return the distance of the given oval to the point given.
- * The oval is described by its bounding box <xbb,ybb,wbb,hbb>,
- * the thickness of its outline <width>. Return values are negative
- * if the point is inside.
- */
-ZnDim
-ZnOvalToPointDist(ZnPoint *center,
- ZnDim width,
- ZnDim height,
- ZnDim line_width,
- ZnPoint *p)
-{
- ZnReal x_delta, y_delta;
- /* ZnReal x_diameter, y_diameter;*/
- ZnDim scaled_distance;
- ZnDim distance_to_outline;
- ZnDim distance_to_center;
-
- /*
- * Compute the distance from the point given to the center
- * of the oval. Then compute the same distance in a coordinate
- * system where the oval is a circle with unit radius.
- */
-
- x_delta = p->x - center->x;
- y_delta = p->y - center->y;
- distance_to_center = hypot(x_delta, y_delta);
- scaled_distance = hypot(x_delta / ((width + line_width) / 2.0),
- y_delta / ((height + line_width) / 2.0));
-
- /*
- * If the scaled distance is greater than 1.0 the point is outside
- * the oval. Compute the distance to the edge and convert it back
- * to the original coordinate system. This distance is not much
- * accurate and can overestimate the real distance if the oval is
- * very eccentric.
- */
- if (scaled_distance > 1.0) {
- distance_to_outline = (distance_to_center / scaled_distance) * (scaled_distance - 1.0);
- return distance_to_outline;
- }
-
- /*
- * The point is inside the oval. Compute the distance as above and check
- * if the point is within the outline.
- */
- if (scaled_distance > 1.0e-10) {
- distance_to_outline = (distance_to_center / scaled_distance) * (1.0 - scaled_distance) - line_width;
- }
- else {
- /*
- * If the point is very close to the center avoid dividing by a
- * very small number, take another method.
- */
- if (width < height)
- distance_to_outline = (width - line_width) / 2;
- else
- distance_to_outline = (height - line_width) / 2;
- }
-
- if (distance_to_outline < 0.0)
- return 0.0;
- else
- return -distance_to_outline;
-}
-
-
-static int bezier_basis[][4] =
-{
- { -1, 3, -3, 1},
- { 3, -6, 3, 0},
- { -3, 3, 0, 0},
- { 1, 0, 0, 0}
-};
-
-/*
- **********************************************************************************
- *
- * Arc2Param --
- *
- * Given a Bezier curve describing an arc and an angle return the parameter
- * value for the intersection point between the arc and the ray at angle.
- *
- **********************************************************************************
- */
-#define EVAL(coeff, t) (((coeff[0]*t + coeff[1])*t + coeff[2]) * t + coeff[3])
-static ZnReal
-Arc2Param(ZnPoint *controls,
- ZnReal angle)
-{
- ZnReal coeff_x[4], coeff_y[4];
- ZnReal min_angle, min_t, max_angle, max_t, cur_angle, cur_t;
- int i, j, depth = 0;
-
- /* assume angle >= 0 */
- while (angle > M_PI) {
- angle -= 2 * M_PI;
- }
-
- for (i = 0; i < 4; i++) {
- coeff_x[i] = coeff_y[i] = 0.0;
- for (j = 0; j < 4; j++) {
- coeff_x[i] += bezier_basis[i][j] * controls[j].x;
- coeff_y[i] += bezier_basis[i][j] * controls[j].y;
- }
- }
-
- min_angle = atan2(controls[0].y, controls[0].x);
- max_angle = atan2(controls[3].y, controls[3].x);
- if (max_angle < min_angle) {
- min_angle -= M_PI+M_PI;
- }
- if (angle > max_angle) {
- angle -= M_PI+M_PI;
- }
-
- min_t = 0.0; max_t = 1.0;
-
- while (depth < 15) {
- cur_t = (max_t + min_t) / 2.0;
- cur_angle = atan2(EVAL(coeff_y, cur_t), EVAL(coeff_x, cur_t));
- if (angle > cur_angle) {
- min_t = cur_t;
- min_angle = cur_angle;
- }
- else {
- max_t = cur_t;
- max_angle = cur_angle;
- }
- depth += 1;
- }
-
- if ((max_angle-angle) < (angle-min_angle)) {
- return max_t;
- }
-
- return min_t;
-}
-#undef EVAL
-
-
-/*
- **********************************************************************************
- *
- * BezierSubdivide --
- *
- * Subdivide a Bezier curve given by controls at parameter t. Return
- * in controls, the first or the last part depending on boolean first.
- *
- **********************************************************************************
- */
-static void
-BezierSubdivide(ZnPoint *controls,
- ZnReal t,
- ZnBool first)
-{
- ZnReal s = 1.0 - t;
- ZnPoint r[7];
- ZnPoint a;
-
- r[0] = controls[0];
- r[6] = controls[3];
- a.x = s*controls[1].x + t*controls[2].x;
- a.y = s*controls[1].y + t*controls[2].y;
- r[1].x = s*r[0].x + t*controls[1].x;
- r[1].y = s*r[0].y + t*controls[1].y;
- r[2].x = s*r[1].x + t*a.x;
- r[2].y = s*r[1].y + t*a.y;
- r[5].x = s*controls[2].x + t*r[6].x;
- r[5].y = s*controls[2].y + t*r[6].y;
- r[4].x = s*a.x + t*r[5].x;
- r[4].y = s*a.y + t*r[5].y;
- r[3].x = s*r[2].x + t*r[4].x;
- r[3].y = s*r[2].y + t*r[4].y;
-
- if (first) {
- memcpy(controls, r, 4*sizeof(ZnPoint));
- }
- else {
- memcpy(controls, &r[3], 4*sizeof(ZnPoint));
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetBezierPoints --
- * Use recursive subdivision to approximate the curve. The subdivision stops
- * when the error is under eps.
- * This algorithm is adaptive, meaning that it computes the minimum number
- * of segments needed to render each curve part.
- *
- **********************************************************************************
- */
-void
-ZnGetBezierPoints(ZnPoint *p1,
- ZnPoint *c1,
- ZnPoint *c2,
- ZnPoint *p2,
- ZnList to_points,
- ZnReal eps)
-{
- ZnReal dist;
-
- dist = ZnLineToPointDist(p1, p2, c1, NULL);
- if ((dist < eps) && ((c1->x != c2->x) || (c1->y != c2->y))) {
- dist = ZnLineToPointDist(p1, p2, c2, NULL);
- }
-
- if (dist > eps) {
- ZnPoint mid_segm, new_c1, new_c2;
- /*
- * Subdivide the curve at t = 0.5
- * and compute each new curve.
- */
- mid_segm.x = (p1->x + 3*c1->x + 3*c2->x + p2->x) / 8.0;
- mid_segm.y = (p1->y + 3*c1->y + 3*c2->y + p2->y) / 8.0;
- new_c1.x = (p1->x + c1->x) / 2.0;
- new_c1.y = (p1->y + c1->y) / 2.0;
- new_c2.x = (p1->x + 2*c1->x + c2->x) / 4.0;
- new_c2.y = (p1->y + 2*c1->y + c2->y) / 4.0;
- ZnGetBezierPoints(p1, &new_c1, &new_c2, &mid_segm, to_points, eps);
-
- new_c1.x = (c1->x + 2*c2->x + p2->x) / 4.0;
- new_c1.y = (c1->y + 2*c2->y + p2->y) / 4.0;
- new_c2.x = (c2->x + (p2->x)) / 2.0;
- new_c2.y = (c2->y + (p2->y)) / 2.0;
- ZnGetBezierPoints(&mid_segm, &new_c1, &new_c2, p2, to_points, eps);
- }
- else {
- /*
- * Flat enough add the end to the current path.
- * The start should already be there.
- */
- ZnListAdd(to_points, p2, ZnListTail);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetBezierPath --
- * Compute in to_points a new set of points describing a Bezier path based
- * on the control points given in from_points.
- * If more than four points are given, the algorithm iterate over the
- * set using the last point of a segment as the first point of the next.
- * If 3 points are left, they are interpreted as a Bezier segment with
- * coincident internal control points. If 2 points are left a straight
- * is emitted.
- *
- **********************************************************************************
- */
-void
-ZnGetBezierPath(ZnList from_points,
- ZnList to_points)
-{
- ZnPoint *fp;
- int num_fp, i;
-
- fp = ZnListArray(from_points);
- num_fp = ZnListSize(from_points);
-
- /*
- * make sure the output vector is empty, then add the first point.
- */
- ZnListEmpty(to_points);
- ZnListAdd(to_points, fp, ZnListTail);
-
- for (i = 0; i < num_fp; ) {
- if (i < (num_fp-3)) {
- ZnGetBezierPoints(fp, fp+1, fp+2, fp+3, to_points, 1.0);
- if (i < (num_fp-4)) {
- fp += 3;
- i += 3;
- }
- else {
- break;
- }
- }
- else if (i == (num_fp-3)) {
- ZnGetBezierPoints(fp, fp+1, fp+1, fp+2, to_points, 1.0);
- break;
- }
- else if (i == (num_fp-2)) {
- ZnListAdd(to_points, fp+1, ZnListTail);
- break;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetCirclePoints --
- * Return a pointer to an array of points describing a
- * circle arc of radius 1.0. The arc is described by start_angle,
- * end_angle and the type: 0 for arc, 1 for chord, 2 for pie slice,
- * 3 for a full circle (in which case start_angle and end_angle are
- * not used.
- * The number of points is returned in num_points. If type is not 3,
- * point_list must not be NULL. If not NULL, it is filled with the
- * computed points.
- *
- **********************************************************************************
- */
-ZnPoint *
-ZnGetCirclePoints(int type,
- int quality,
- ZnReal start_angle,
- ZnReal angle_extent,
- unsigned int *num_points,
- ZnList point_list)
-{
- static ZnPoint genarc_finest[] = { /* 128 */
- {1.0, 0.0},
- {0.99879545617, 0.0490676750517},
- {0.99518472653, 0.0980171417729},
- {0.989176509646, 0.146730476607},
- {0.980785279837, 0.195090324861},
- {0.970031252314, 0.24298018342},
- {0.956940334469, 0.290284681418},
- {0.941544063473, 0.336889858172},
- {0.923879530291, 0.382683437725},
- {0.903989290333, 0.42755509933},
- {0.88192126093, 0.471396743221},
- {0.857728605899, 0.514102751035},
- {0.831469607468, 0.555570240255},
- {0.803207525865, 0.595699312064},
- {0.773010446922, 0.634393292011},
- {0.74095111805, 0.671558962907},
- {0.707106772982, 0.707106789391},
- {0.671558945713, 0.740951133634},
- {0.634393274074, 0.773010461643},
- {0.595699293426, 0.803207539688},
- {0.555570220961, 0.83146962036},
- {0.514102731131, 0.857728617829},
- {0.471396722756, 0.881921271869},
- {0.427555078353, 0.903989300254},
- {0.382683416286, 0.923879539171},
- {0.336889836323, 0.94154407129},
- {0.290284659212, 0.956940341205},
- {0.242980160911, 0.970031257952},
- {0.195090302102, 0.980785284364},
- {0.146730453653, 0.98917651305},
- {0.0980171186795, 0.995184728805},
- {0.0490676518746, 0.998795457308},
- {-2.32051033331e-08, 1.0},
- {-0.0490676982289, 0.998795455031},
- {-0.0980171648663, 0.995184724256},
- {-0.146730499561, 0.989176506241},
- {-0.19509034762, 0.98078527531},
- {-0.24298020593, 0.970031246675},
- {-0.290284703624, 0.956940327733},
- {-0.33688988002, 0.941544055655},
- {-0.382683459163, 0.923879521411},
- {-0.427555120307, 0.903989280412},
- {-0.471396763686, 0.881921249991},
- {-0.514102770939, 0.85772859397},
- {-0.555570259549, 0.831469594576},
- {-0.595699330703, 0.803207512042},
- {-0.634393309949, 0.773010432201},
- {-0.6715589801, 0.740951102467},
- {-0.707106805799, 0.707106756574},
- {-0.740951149217, 0.671558928519},
- {-0.773010476365, 0.634393256136},
- {-0.803207553511, 0.595699274787},
- {-0.831469633252, 0.555570201666},
- {-0.857728629759, 0.514102711228},
- {-0.881921282808, 0.471396702291},
- {-0.903989310176, 0.427555057376},
- {-0.923879548052, 0.382683394847},
- {-0.941544079108, 0.336889814474},
- {-0.956940347941, 0.290284637006},
- {-0.97003126359, 0.242980138401},
- {-0.980785288892, 0.195090279343},
- {-0.989176516455, 0.146730430699},
- {-0.995184731079, 0.0980170955862},
- {-0.998795458447, 0.0490676286974},
- {-1.0, -4.64102066663e-08},
- {-0.998795453892, -0.049067721406},
- {-0.995184721981, -0.0980171879596},
- {-0.989176502836, -0.146730522515},
- {-0.980785270783, -0.195090370379},
- {-0.970031241037, -0.24298022844},
- {-0.956940320997, -0.29028472583},
- {-0.941544047838, -0.336889901869},
- {-0.923879512531, -0.382683480602},
- {-0.90398927049, -0.427555141284},
- {-0.881921239052, -0.471396784151},
- {-0.85772858204, -0.514102790842},
- {-0.831469581684, -0.555570278844},
- {-0.803207498218, -0.595699349341},
- {-0.77301041748, -0.634393327887},
- {-0.740951086883, -0.671558997294},
- {-0.707106740165, -0.707106822208},
- {-0.671558911325, -0.740951164801},
- {-0.634393238198, -0.773010491086},
- {-0.595699256149, -0.803207567335},
- {-0.555570182372, -0.831469646144},
- {-0.514102691324, -0.857728641689},
- {-0.471396681826, -0.881921293746},
- {-0.427555036399, -0.903989320097},
- {-0.382683373409, -0.923879556932},
- {-0.336889792626, -0.941544086926},
- {-0.2902846148, -0.956940354677},
- {-0.242980115891, -0.970031269229},
- {-0.195090256583, -0.980785293419},
- {-0.146730407745, -0.98917651986},
- {-0.0980170724928, -0.995184733354},
- {-0.0490676055202, -0.998795459585},
- {6.96153097774e-08, -1.0},
- {0.0490677445832, -0.998795452754},
- {0.098017211053, -0.995184719707},
- {0.146730545469, -0.989176499431},
- {0.195090393139, -0.980785266256},
- {0.242980250949, -0.970031235398},
- {0.290284748036, -0.956940314261},
- {0.336889923717, -0.94154404002},
- {0.382683502041, -0.923879503651},
- {0.427555162262, -0.903989260569},
- {0.471396804617, -0.881921228114},
- {0.514102810746, -0.85772857011},
- {0.555570298138, -0.831469568792},
- {0.59569936798, -0.803207484395},
- {0.634393345825, -0.773010402759},
- {0.671559014488, -0.740951071299},
- {0.707106838616, -0.707106723757},
- {0.740951180385, -0.671558894131},
- {0.773010505807, -0.63439322026},
- {0.803207581158, -0.59569923751},
- {0.831469659036, -0.555570163078},
- {0.857728653619, -0.51410267142},
- {0.881921304685, -0.471396661361},
- {0.903989330019, -0.427555015421},
- {0.923879565812, -0.38268335197},
- {0.941544094743, -0.336889770777},
- {0.956940361414, -0.290284592594},
- {0.970031274867, -0.242980093382},
- {0.980785297946, -0.195090233824},
- {0.989176523265, -0.146730384792},
- {0.995184735628, -0.0980170493994},
- {0.998795460724, -0.0490675823431},
- {1.0, 0.0}
- };
- static ZnPoint genarc_finer[] = { /* 64 */
- {1.0, 0.0},
- {0.99518472653, 0.0980171417729},
- {0.980785279837, 0.195090324861},
- {0.956940334469, 0.290284681418},
- {0.923879530291, 0.382683437725},
- {0.88192126093, 0.471396743221},
- {0.831469607468, 0.555570240255},
- {0.773010446922, 0.634393292011},
- {0.707106772982, 0.707106789391},
- {0.634393274074, 0.773010461643},
- {0.555570220961, 0.83146962036},
- {0.471396722756, 0.881921271869},
- {0.382683416286, 0.923879539171},
- {0.290284659212, 0.956940341205},
- {0.195090302102, 0.980785284364},
- {0.0980171186795, 0.995184728805},
- {-2.32051033331e-08, 1.0},
- {-0.0980171648663, 0.995184724256},
- {-0.19509034762, 0.98078527531},
- {-0.290284703624, 0.956940327733},
- {-0.382683459163, 0.923879521411},
- {-0.471396763686, 0.881921249991},
- {-0.555570259549, 0.831469594576},
- {-0.634393309949, 0.773010432201},
- {-0.707106805799, 0.707106756574},
- {-0.773010476365, 0.634393256136},
- {-0.831469633252, 0.555570201666},
- {-0.881921282808, 0.471396702291},
- {-0.923879548052, 0.382683394847},
- {-0.956940347941, 0.290284637006},
- {-0.980785288892, 0.195090279343},
- {-0.995184731079, 0.0980170955862},
- {-1.0, -4.64102066663e-08},
- {-0.995184721981, -0.0980171879596},
- {-0.980785270783, -0.195090370379},
- {-0.956940320997, -0.29028472583},
- {-0.923879512531, -0.382683480602},
- {-0.881921239052, -0.471396784151},
- {-0.831469581684, -0.555570278844},
- {-0.77301041748, -0.634393327887},
- {-0.707106740165, -0.707106822208},
- {-0.634393238198, -0.773010491086},
- {-0.555570182372, -0.831469646144},
- {-0.471396681826, -0.881921293746},
- {-0.382683373409, -0.923879556932},
- {-0.2902846148, -0.956940354677},
- {-0.195090256583, -0.980785293419},
- {-0.0980170724928, -0.995184733354},
- {6.96153097774e-08, -1.0},
- {0.098017211053, -0.995184719707},
- {0.195090393139, -0.980785266256},
- {0.290284748036, -0.956940314261},
- {0.382683502041, -0.923879503651},
- {0.471396804617, -0.881921228114},
- {0.555570298138, -0.831469568792},
- {0.634393345825, -0.773010402759},
- {0.707106838616, -0.707106723757},
- {0.773010505807, -0.63439322026},
- {0.831469659036, -0.555570163078},
- {0.881921304685, -0.471396661361},
- {0.923879565812, -0.38268335197},
- {0.956940361414, -0.290284592594},
- {0.980785297946, -0.195090233824},
- {0.995184735628, -0.0980170493994},
- {1.0, 0.0}
- };
- static ZnPoint genarc_fine[] = { /* 40 */
- {1.0, 0.0},
- {0.987688340232, 0.156434467332},
- {0.951056514861, 0.309016998789},
- {0.891006521028, 0.453990505942},
- {0.809016988919, 0.587785259802},
- {0.707106772982, 0.707106789391},
- {0.587785241028, 0.809017002559},
- {0.453990485266, 0.891006531563},
- {0.309016976719, 0.951056522032},
- {0.156434444413, 0.987688343862},
- {-2.32051033331e-08, 1.0},
- {-0.156434490252, 0.987688336602},
- {-0.309017020858, 0.95105650769},
- {-0.453990526618, 0.891006510493},
- {-0.587785278575, 0.809016975279},
- {-0.707106805799, 0.707106756574},
- {-0.809017016198, 0.587785222255},
- {-0.891006542098, 0.453990464591},
- {-0.951056529203, 0.30901695465},
- {-0.987688347492, 0.156434421493},
- {-1.0, -4.64102066663e-08},
- {-0.987688332972, -0.156434513171},
- {-0.951056500519, -0.309017042928},
- {-0.891006499958, -0.453990547294},
- {-0.80901696164, -0.587785297348},
- {-0.707106740165, -0.707106822208},
- {-0.587785203482, -0.809017029838},
- {-0.453990443915, -0.891006552633},
- {-0.309016932581, -0.951056536373},
- {-0.156434398574, -0.987688351122},
- {6.96153097774e-08, -1.0},
- {0.15643453609, -0.987688329342},
- {0.309017064997, -0.951056493349},
- {0.45399056797, -0.891006489423},
- {0.587785316122, -0.809016948},
- {0.707106838616, -0.707106723757},
- {0.809017043478, -0.587785184709},
- {0.891006563167, -0.453990423239},
- {0.951056543544, -0.309016910511},
- {0.987688354752, -0.156434375655},
- {1.0, 0.0}
- };
- static ZnPoint genarc_medium[] = { /* 20 */
- {1.0, 0.0},
- {0.951056514861, 0.309016998789},
- {0.809016988919, 0.587785259802},
- {0.587785241028, 0.809017002559},
- {0.309016976719, 0.951056522032},
- {-2.32051033331e-08, 1.0},
- {-0.309017020858, 0.95105650769},
- {-0.587785278575, 0.809016975279},
- {-0.809017016198, 0.587785222255},
- {-0.951056529203, 0.30901695465},
- {-1.0, -4.64102066663e-08},
- {-0.951056500519, -0.309017042928},
- {-0.80901696164, -0.587785297348},
- {-0.587785203482, -0.809017029838},
- {-0.309016932581, -0.951056536373},
- {6.96153097774e-08, -1.0},
- {0.309017064997, -0.951056493349},
- {0.587785316122, -0.809016948},
- {0.809017043478, -0.587785184709},
- {0.951056543544, -0.309016910511},
- {1.0, 0.0}
- };
- static ZnPoint genarc_coarse[] = { /* 10 */
- {1.0, 0.0},
- {0.809016988919, 0.587785259802},
- {0.309016976719, 0.951056522032},
- {-0.309017020858, 0.95105650769},
- {-0.809017016198, 0.587785222255},
- {-1.0, -4.64102066663e-08},
- {-0.80901696164, -0.587785297348},
- {-0.309016932581, -0.951056536373},
- {0.309017064997, -0.951056493349},
- {0.809017043478, -0.587785184709},
- {1.0, 0.0}
- };
- unsigned int num_p, i;
- ZnPoint *p, *p_from;
- ZnPoint center_p = { 0.0, 0.0 };
- ZnPoint start_p, wp;
- ZnReal iangle, end_angle=0;
-
- switch (quality) {
- case ZN_CIRCLE_COARSE:
- num_p = sizeof(genarc_coarse)/sizeof(ZnPoint);
- p = p_from = genarc_coarse;
- break;
- case ZN_CIRCLE_MEDIUM:
- num_p = sizeof(genarc_medium)/sizeof(ZnPoint);
- p = p_from = genarc_medium;
- break;
- case ZN_CIRCLE_FINER:
- num_p = sizeof(genarc_finer)/sizeof(ZnPoint);
- p = p_from = genarc_finer;
- break;
- case ZN_CIRCLE_FINEST:
- num_p = sizeof(genarc_finest)/sizeof(ZnPoint);
- p = p_from = genarc_finest;
- break;
- default:
- case ZN_CIRCLE_FINE:
- num_p = sizeof(genarc_fine)/sizeof(ZnPoint);
- p = p_from = genarc_fine;
- }
-
- /*printf("start: %g, extent: %g\n", start_angle, angle_extent);*/
- if (angle_extent == 2*M_PI) {
- type = 3;
- }
- if (type != 3) {
- end_angle = start_angle+angle_extent;
- if (angle_extent < 0) {
- iangle = start_angle;
- start_angle = end_angle;
- end_angle = iangle;
- }
- /*
- * normalize start_angle and end_angle.
- */
- if (start_angle < 0.0) {
- start_angle += 2.0*M_PI;
- }
- if (end_angle < 0.0) {
- end_angle += 2.0*M_PI;
- }
- if (end_angle < start_angle) {
- end_angle += 2.0*M_PI;
- }
- /*printf("---start: %g, end: %g\n", start_angle, end_angle);*/
- }
-
- /*
- * Now 0 <= start_angle < 2 * M_PI and start_angle <= end_angle.
- */
- if ((type != 3) || (point_list != NULL)) {
- if (type == 3) {
- ZnListAssertSize(point_list, num_p);
- p = ZnListArray(point_list);
- for (i = 0; i < num_p; i++, p++, p_from++) {
- *p = *p_from;
- }
- }
- else {
- ZnListEmpty(point_list);
- iangle = 2*M_PI / (num_p-1);
- start_p.x = cos(start_angle);
- start_p.y = sin(start_angle);
- ZnListAdd(point_list, &start_p, ZnListTail);
- i = (unsigned int) (start_angle / iangle);
- if ((i * iangle) < start_angle) {
- i++;
- }
- while (1) {
- if (start_angle + iangle <= end_angle) {
- if (i == num_p-1) {
- i = 0;
- }
- ZnListAdd(point_list, &p_from[i], ZnListTail);
- start_angle += iangle;
- i++;
- }
- else {
- wp.x = cos(end_angle);
- wp.y = sin(end_angle);
- ZnListAdd(point_list, &wp, ZnListTail);
- break;
- }
- }
- if (type == 1) {
- ZnListAdd(point_list, &start_p, ZnListTail);
- }
- else if (type == 2) {
- ZnListAdd(point_list, &center_p, ZnListTail);
- ZnListAdd(point_list, &start_p, ZnListTail);
- }
- }
- p = ZnListArray(point_list);
- num_p = ZnListSize(point_list);
- }
-
- *num_points = num_p;
- return p;
-}
-
-/*
- **********************************************************************************
- *
- * ZnGetArcPath --
- * Compute in to_points a set of Bezier control points describing an arc
- * path given the start angle, the stop angle and the type: 0 for arc,
- * 1 for chord, 2 for pie slice.
- * To obtain the actual polygonal shape, the client should use GetBezierPath
- * on the returned controls (after applying transform). The returned arc
- * is circular and centered on 0,0.
- *
- **********************************************************************************
- */
-static ZnReal arc_nodes_x[4] = { 1.0, 0.0, -1.0, 0.0 };
-static ZnReal arc_nodes_y[4] = { 0.0, 1.0, 0.0, -1.0 };
-static ZnReal arc_controls_x[8] = { 1.0, 0.55197, -0.55197, -1.0, -1.0, -0.55197, 0.55197, 1.0 };
-static ZnReal arc_controls_y[8] = { 0.55197, 1.0, 1.0, 0.55197, -0.55197, -1.0, -1.0, -0.55197 };
-void
-ZnGetArcPath(ZnReal start_angle,
- ZnReal end_angle,
- int type,
- ZnList to_points)
-{
- int start_quad, end_quad, quadrant;
- ZnPoint center_p = { 0.0, 0.0 };
- ZnPoint start_p = center_p;
-
- /*
- * make sure the output vector is empty.
- */
- ZnListEmpty(to_points);
-
- /*
- * normalize start_angle and end_angle.
- */
- start_angle = fmod(start_angle, 2.0*M_PI);
- if (start_angle < 0.0) {
- start_angle += 2.0*M_PI;
- }
- end_angle = fmod(end_angle, 2.0*M_PI);
- if (end_angle < 0.0) {
- end_angle += 2.0*M_PI;
- }
- if (start_angle >= end_angle) {
- if (start_angle == end_angle) {
- type = 3;
- }
- end_angle += 2.0*M_PI;
- }
-
- /*
- * Now 0 <= start_angle < 2 * M_PI and start_angle <= end_angle.
- */
-
- start_quad = (int) (start_angle / (M_PI / 2.0));
- end_quad = (int) (end_angle / (M_PI / 2.0));
-
- for (quadrant = start_quad; quadrant <= end_quad; quadrant++) {
- ZnPoint controls[4];
- ZnReal t;
-
- controls[0].x = arc_nodes_x[quadrant % 4];
- controls[0].y = arc_nodes_y[quadrant % 4];
- controls[1].x = arc_controls_x[2 * (quadrant % 4)];
- controls[1].y = arc_controls_y[2 * (quadrant % 4)];
- controls[2].x = arc_controls_x[2 * (quadrant % 4) + 1];
- controls[2].y = arc_controls_y[2 * (quadrant % 4) + 1];
- controls[3].x = arc_nodes_x[(quadrant + 1) % 4];
- controls[3].y = arc_nodes_y[(quadrant + 1) % 4];
-
- if (quadrant == start_quad) {
- t = Arc2Param(controls, start_angle);
- BezierSubdivide(controls, t, False);
- /*
- * The path is still empty and we have to create the first
- * vertex.
- */
- start_p = controls[0];
- ZnListAdd(to_points, &controls[0], ZnListTail);
- }
- if (quadrant == end_quad) {
- t = Arc2Param(controls, end_angle);
- if (!t) {
- break;
- }
- BezierSubdivide(controls, t, True);
- }
- ZnListAdd(to_points, &controls[1], ZnListTail);
- ZnListAdd(to_points, &controls[2], ZnListTail);
- ZnListAdd(to_points, &controls[3], ZnListTail);
- }
-
- if (type == 2) {
- ZnListAdd(to_points, &center_p, ZnListTail);
- /*
- * Can't add this one, it would be interpreted by GetBezierPath
- * as an off-curve control. The path should be closed by the client
- * after expansion by GetBezierPath.
- *
- ZnListAdd(to_points, &start_p, ZnListTail);
- */
- }
- else if (type == 1) {
- ZnListAdd(to_points, &start_p, ZnListTail);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * SmoothPathWithBezier --
- * Compute in to_points a new set of points describing a smoothed path based
- * on the path given in from_points. The algorithm use Bezier cubic curves.
- *
- **********************************************************************************
- */
-void
-ZnSmoothPathWithBezier(ZnPoint *fp,
- unsigned int num_fp,
- ZnList to_points)
-{
- ZnBool closed;
- ZnPoint s[4];
- unsigned int i;
-
- /*
- * make sure the output vector is empty
- */
- ZnListEmpty(to_points);
-
- /*
- * If the curve is closed, generates a Bezier curve that
- * spans the closure. Else simply add the first point to
- * the path.
- */
- if ((fp[0].x == fp[num_fp-1].x) && (fp[0].y == fp[num_fp-1].y)) {
- closed = True;
- s[0].x = 0.5*fp[num_fp-2].x + 0.5*fp[0].x;
- s[0].y = 0.5*fp[num_fp-2].y + 0.5*fp[0].y;
- s[1].x = 0.167*fp[num_fp-2].x + 0.833*fp[0].x;
- s[1].y = 0.167*fp[num_fp-2].y + 0.833*fp[0].y;
- s[2].x = 0.833*fp[0].x + 0.167*fp[1].x;
- s[2].y = 0.833*fp[0].y + 0.167*fp[1].y;
- s[3].x = 0.5*fp[0].x + 0.5*fp[1].x;
- s[3].y = 0.5*fp[0].y + 0.5*fp[1].y;
- ZnListAdd(to_points, s, ZnListTail);
- ZnGetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0);
- }
- else {
- closed = False;
- ZnListAdd(to_points, &fp[0], ZnListTail);
- }
-
- for (i = 2; i < num_fp; i++, fp++) {
- /*
- * Setup the first two control points. This differ
- * for first segment of open curves.
- */
- if ((i == 2) && !closed) {
- s[0] = fp[0];
- s[1].x = 0.333*fp[0].x + 0.667*fp[1].x;
- s[1].y = 0.333*fp[0].y + 0.667*fp[1].y;
- }
- else {
- s[0].x = 0.5*fp[0].x + 0.5*fp[1].x;
- s[0].y = 0.5*fp[0].y + 0.5*fp[1].y;
- s[1].x = 0.167*fp[0].x + 0.833*fp[1].x;
- s[1].y = 0.167*fp[0].y + 0.833*fp[1].y;
- }
-
- /*
- * Setup the last two control points. This also differ
- * for last segment of open curves.
- */
- if ((i == num_fp-1) && !closed) {
- s[2].x = 0.667*fp[1].x + 0.333*fp[2].x;
- s[2].y = 0.667*fp[1].y + 0.333*fp[2].y;
- s[3] = fp[2];
- }
- else {
- s[2].x = 0.833*fp[1].x + 0.167*fp[2].x;
- s[2].y = 0.833*fp[1].y + 0.167*fp[2].y;
- s[3].x = 0.5*fp[1].x + 0.5*fp[2].x;
- s[3].y = 0.5*fp[1].y + 0.5*fp[2].y;
- }
-
- /*
- * If the first two points or the last two are equal
- * output the last control point. Else generate the
- * Bezier curve.
- */
- if (((fp[0].x == fp[1].x) && (fp[0].y == fp[1].y)) ||
- ((fp[1].x == fp[2].x) && (fp[1].y == fp[2].y))) {
- ZnListAdd(to_points, &s[3], ZnListTail);
- }
- else {
- ZnGetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * FitBezier --
- * Fit a Bezier curve to a (sub)set of digitized points.
- *
- * From: An Algorithm for Automatically Fitting Digitized Curves
- * by Philip J. Schneider in "Graphics Gems", Academic Press, 1990
- *
- **********************************************************************************
- */
-
-static ZnReal
-V2DistanceBetween2Points(ZnPoint *a,
- ZnPoint *b)
-{
- ZnReal dx = a->x - b->x;
- ZnReal dy = a->y - b->y;
- return sqrt((dx*dx)+(dy*dy));
-}
-
-static ZnReal
-V2SquaredLength(ZnPoint *a)
-{
- return (a->x * a->x)+(a->y * a->y);
-}
-
-static ZnReal
-V2Length(ZnPoint *a)
-{
- return sqrt(V2SquaredLength(a));
-}
-
-static ZnPoint *
-V2Scale(ZnPoint *v,
- ZnReal newlen)
-{
- ZnReal len = V2Length(v);
- if (len != 0.0) {
- v->x *= newlen/len;
- v->y *= newlen/len;
- }
- return v;
-}
-
-static ZnPoint *
-V2Negate(ZnPoint *v)
-{
- v->x = -v->x; v->y = -v->y;
- return v;
-}
-
-static ZnPoint *
-V2Normalize(ZnPoint *v)
-{
- ZnReal len = sqrt(V2Length(v));
- if (len != 0.0) {
- v->x /= len;
- v->y /= len;
- }
- return v;
-}
-static ZnPoint *
-V2Add(ZnPoint *a,
- ZnPoint *b,
- ZnPoint *c)
-{
- c->x = a->x + b->x;
- c->y = a->y + b->y;
- return c;
-}
-
-static ZnReal
-V2Dot(ZnPoint *a,
- ZnPoint *b)
-{
- return (a->x*b->x) + (a->y*b->y);
-}
-
-static ZnPoint
-V2AddII(ZnPoint a,
- ZnPoint b)
-{
- ZnPoint c;
- c.x = a.x + b.x;
- c.y = a.y + b.y;
- return c;
-}
-
-static ZnPoint
-V2ScaleIII(ZnPoint v,
- ZnReal s)
-{
- ZnPoint result;
- result.x = v.x * s;
- result.y = v.y * s;
- return result;
-}
-
-static ZnPoint
-V2SubII(ZnPoint a,
- ZnPoint b)
-{
- ZnPoint c;
- c.x = a.x - b.x;
- c.y = a.y - b.y;
- return c;
-}
-
-/*
- * B0, B1, B2, B3, Bezier multipliers.
- */
-static ZnReal
-B0(ZnReal u)
-{
- ZnReal tmp = 1.0 - u;
- return tmp * tmp * tmp;
-}
-
-static ZnReal
-B1(ZnReal u)
-{
- ZnReal tmp = 1.0 - u;
- return 3 * u * (tmp * tmp);
-}
-
-static ZnReal
-B2(ZnReal u)
-{
- ZnReal tmp = 1.0 - u;
- return 3 * u * u * tmp;
-}
-
-static ZnReal
-B3(ZnReal u)
-{
- return u * u * u;
-}
-
-/*
- * ChordLengthParameterize --
- * Assign parameter values to digitized points
- * using relative distances between points.
- */
-static ZnReal *
-ChordLengthParameterize(ZnPoint *d,
- unsigned int first,
- unsigned int last)
-{
- unsigned int i;
- ZnReal *u;
-
- u = (ZnReal *) ZnMalloc((unsigned) (last-first+1) * sizeof(ZnReal));
-
- u[0] = 0.0;
- for (i = first+1; i <= last; i++) {
- u[i-first] = u[i-first-1] + V2DistanceBetween2Points(&d[i], &d[i-1]);
- }
-
- for (i = first + 1; i <= last; i++) {
- u[i-first] = u[i-first] / u[last-first];
- }
-
- return u;
-}
-
-/*
- * Bezier --
- * Evaluate a Bezier curve at a particular parameter value
- *
- */
-static ZnPoint
-BezierII(int degree,
- ZnPoint *V,
- ZnReal t)
-{
- int i, j;
- ZnPoint Q; /* Point on curve at parameter t */
- ZnPoint *Vtemp; /* Local copy of control points */
-
- /* Copy array */
- Vtemp = (ZnPoint *) ZnMalloc((unsigned)((degree+1) * sizeof (ZnPoint)));
- for (i = 0; i <= degree; i++) {
- Vtemp[i] = V[i];
- }
-
- /* Triangle computation */
- for (i = 1; i <= degree; i++) {
- for (j = 0; j <= degree-i; j++) {
- Vtemp[j].x = (1.0 - t) * Vtemp[j].x + t * Vtemp[j+1].x;
- Vtemp[j].y = (1.0 - t) * Vtemp[j].y + t * Vtemp[j+1].y;
- }
- }
-
- Q = Vtemp[0];
- ZnFree(Vtemp);
- return Q;
-}
-
-/*
- * NewtonRaphsonRootFind --
- * Use Newton-Raphson iteration to find better root.
- */
-static ZnReal
-NewtonRaphsonRootFind(ZnPoint *Q,
- ZnPoint P,
- ZnReal u)
-{
- ZnReal numerator, denominator;
- ZnPoint Q1[3], Q2[2]; /* Q' and Q'' */
- ZnPoint Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
- ZnReal uPrime; /* Improved u */
- unsigned int i;
-
- /* Compute Q(u) */
- Q_u = BezierII(3, Q, u);
-
- /* Generate control vertices for Q' */
- for (i = 0; i <= 2; i++) {
- Q1[i].x = (Q[i+1].x - Q[i].x) * 3.0;
- Q1[i].y = (Q[i+1].y - Q[i].y) * 3.0;
- }
-
- /* Generate control vertices for Q'' */
- for (i = 0; i <= 1; i++) {
- Q2[i].x = (Q1[i+1].x - Q1[i].x) * 2.0;
- Q2[i].y = (Q1[i+1].y - Q1[i].y) * 2.0;
- }
-
- /* Compute Q'(u) and Q''(u) */
- Q1_u = BezierII(2, Q1, u);
- Q2_u = BezierII(1, Q2, u);
-
- /* Compute f(u)/f'(u) */
- numerator = (Q_u.x - P.x) * (Q1_u.x) + (Q_u.y - P.y) * (Q1_u.y);
- denominator = (Q1_u.x) * (Q1_u.x) + (Q1_u.y) * (Q1_u.y) +
- (Q_u.x - P.x) * (Q2_u.x) + (Q_u.y - P.y) * (Q2_u.y);
-
- /* u = u - f(u)/f'(u) */
- uPrime = u - (numerator/denominator);
- return (uPrime);
-}
-
-/*
- * Reparameterize --
- * Given set of points and their parameterization, try to find
- * a better parameterization.
- */
-static ZnReal *
-Reparameterize(ZnPoint *d,
- unsigned int first,
- unsigned int last,
- ZnReal *u,
- ZnPoint *bezCurve)
-{
- unsigned int nPts = last-first+1;
- unsigned int i;
- ZnReal *uPrime; /* New parameter values */
-
- uPrime = (ZnReal *) ZnMalloc(nPts * sizeof(ZnReal));
- for (i = first; i <= last; i++) {
- uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-first]);
- }
- return (uPrime);
-}
-
-/*
- * GenerateBezier --
- * Use least-squares method to find Bezier control
- * points for region.
- */
-static void
-GenerateBezier(ZnPoint *d,
- unsigned int first,
- unsigned int last,
- ZnReal *uPrime,
- ZnPoint tHat1,
- ZnPoint tHat2,
- ZnPoint *bez_curve)
-{
- unsigned int i;
- ZnPoint *A0, *A1; /* Precomputed rhs for eqn */
- unsigned int num_points; /* Number of pts in sub-curve */
- ZnReal C[2][2]; /* Matrix C */
- ZnReal X[2]; /* Matrix X */
- ZnReal det_C0_C1; /* Determinants of matrices */
- ZnReal det_C0_X, det_X_C1;
- ZnReal alpha_l; /* Alpha values, left and right */
- ZnReal alpha_r;
- ZnPoint tmp; /* Utility variable */
-
- num_points = last - first + 1;
- A0 = (ZnPoint *) ZnMalloc(num_points * sizeof(ZnPoint));
- A1 = (ZnPoint *) ZnMalloc(num_points * sizeof(ZnPoint));
-
- /* Compute the A's */
- for (i = 0; i < num_points; i++) {
- ZnPoint v1, v2;
- v1 = tHat1;
- v2 = tHat2;
- V2Scale(&v1, B1(uPrime[i]));
- V2Scale(&v2, B2(uPrime[i]));
- A0[i] = v1;
- A1[i] = v2;
- }
-
- /* Create the C and X matrices */
- C[0][0] = 0.0;
- C[0][1] = 0.0;
- C[1][0] = 0.0;
- C[1][1] = 0.0;
- X[0] = 0.0;
- X[1] = 0.0;
-
- for (i = 0; i < num_points; i++) {
- C[0][0] += V2Dot(&A0[i], &A0[i]);
- C[0][1] += V2Dot(&A0[i], &A1[i]);
- C[1][0] = C[0][1];
- C[1][1] += V2Dot(&A1[i], &A1[i]);
-
- tmp = V2SubII(d[first + i],
- V2AddII(V2ScaleIII(d[first], B0(uPrime[i])),
- V2AddII(V2ScaleIII(d[first], B1(uPrime[i])),
- V2AddII(V2ScaleIII(d[last], B2(uPrime[i])),
- V2ScaleIII(d[last], B3(uPrime[i]))))));
-
- X[0] += V2Dot(&A0[i], &tmp);
- X[1] += V2Dot(&A1[i], &tmp);
- }
-
- /* Compute the determinants of C and X */
- det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
- det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
- det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
-
- /* Finally, derive alpha values */
- if (det_C0_C1 == 0.0) {
- det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
- }
- alpha_l = det_X_C1 / det_C0_C1;
- alpha_r = det_C0_X / det_C0_C1;
-
- /* If alpha negative, use the Wu/Barsky heuristic (see text) */
- if (alpha_l < 0.0 || alpha_r < 0.0) {
- ZnReal dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
-
- bez_curve[0] = d[first];
- bez_curve[3] = d[last];
- V2Add(&bez_curve[0], V2Scale(&tHat1, dist), &bez_curve[1]);
- V2Add(&bez_curve[3], V2Scale(&tHat2, dist), &bez_curve[2]);
- }
- else {
- /* First and last control points of the Bezier curve are */
- /* positioned exactly at the first and last data points */
- /* Control points 1 and 2 are positioned an alpha distance out */
- /* on the tangent vectors, left and right, respectively */
- bez_curve[0] = d[first];
- bez_curve[3] = d[last];
- V2Add(&bez_curve[0], V2Scale(&tHat1, alpha_l), &bez_curve[1]);
- V2Add(&bez_curve[3], V2Scale(&tHat2, alpha_r), &bez_curve[2]);
- }
- ZnFree(A0);
- ZnFree(A1);
-}
-
-/*
- * ComputeMaxError --
- * Find the maximum squared distance of digitized points
- * to fitted curve.
-*/
-static ZnReal
-ComputeMaxError(ZnPoint *d,
- unsigned int first,
- unsigned int last,
- ZnPoint *bez_curve,
- ZnReal *u,
- unsigned int *splitPoint)
-{
- unsigned int i;
- ZnReal maxDist; /* Maximum error */
- ZnReal dist; /* Current error */
- ZnPoint P; /* Point on curve */
- ZnPoint v; /* Vector from point to curve */
-
- *splitPoint = (last - first + 1)/2;
- maxDist = 0.0;
- for (i = first + 1; i < last; i++) {
- P = BezierII(3, bez_curve, u[i-first]);
- v = V2SubII(P, d[i]);
- dist = V2SquaredLength(&v);
- if (dist >= maxDist) {
- maxDist = dist;
- *splitPoint = i;
- }
- }
- return (maxDist);
-}
-
-/*
- * ComputeLeftTangent,
- * ComputeRightTangent,
- * ComputeCenterTangent --
- * Approximate unit tangents at endpoints and
- * center of digitized curve.
- */
-static ZnPoint
-ComputeLeftTangent(ZnPoint *d,
- unsigned int end)
-{
- ZnPoint tHat1;
- tHat1 = V2SubII(d[end+1], d[end]);
- tHat1 = *V2Normalize(&tHat1);
- return tHat1;
-}
-
-static ZnPoint
-ComputeRightTangent(ZnPoint *d,
- unsigned int end)
-{
- ZnPoint tHat2;
- tHat2 = V2SubII(d[end-1], d[end]);
- tHat2 = *V2Normalize(&tHat2);
- return tHat2;
-}
-
-
-static ZnPoint
-ComputeCenterTangent(ZnPoint *d,
- unsigned int center)
-{
- ZnPoint V1, V2, tHatCenter;
-
- V1 = V2SubII(d[center-1], d[center]);
- V2 = V2SubII(d[center], d[center+1]);
- tHatCenter.x = (V1.x + V2.x)/2.0;
- tHatCenter.y = (V1.y + V2.y)/2.0;
- tHatCenter = *V2Normalize(&tHatCenter);
- return tHatCenter;
-}
-
-static void
-FitCubic(ZnPoint *d,
- unsigned int first,
- unsigned int last,
- ZnPoint tHat1,
- ZnPoint tHat2,
- ZnReal error,
- ZnList controls)
-{
- ZnPoint *bez_curve; /* Control points of fitted Bezier curve*/
- ZnReal *u; /* Parameter values for point */
- ZnReal *uPrime; /* Improved parameter values */
- ZnReal max_err; /* Maximum fitting error */
- unsigned int splitPoint; /* Point to split point set at */
- unsigned int num_points; /* Number of points in subset */
- ZnReal iteration_err; /* Error below which you try iterating */
- unsigned int max_iter = 4; /* Max times to try iterating */
- ZnPoint tHatCenter; /* Unit tangent vector at splitPoint */
- unsigned int i;
-
- iteration_err = error * error;
- num_points = last - first + 1;
- ZnListAssertSize(controls, ZnListSize(controls)+4);
- bez_curve = ZnListAt(controls, ZnListSize(controls)-4);
-
- /* Use heuristic if region only has two points in it */
- if (num_points == 2) {
- ZnReal dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
-
- bez_curve[0] = d[first];
- bez_curve[3] = d[last];
- V2Add(&bez_curve[0], V2Scale(&tHat1, dist), &bez_curve[1]);
- V2Add(&bez_curve[3], V2Scale(&tHat2, dist), &bez_curve[2]);
- return;
- }
-
- /* Parameterize points, and attempt to fit curve */
- u = ChordLengthParameterize(d, first, last);
- GenerateBezier(d, first, last, u, tHat1, tHat2, bez_curve);
-
- /* Find max deviation of points to fitted curve */
- max_err = ComputeMaxError(d, first, last, bez_curve, u, &splitPoint);
- if (max_err < error) {
- ZnFree(u);
- return;
- }
-
- /*
- * If error not too large, try some reparameterization
- * and iteration.
- */
- if (max_err < iteration_err) {
- for (i = 0; i < max_iter; i++) {
- uPrime = Reparameterize(d, first, last, u, bez_curve);
- GenerateBezier(d, first, last, uPrime, tHat1, tHat2, bez_curve);
- max_err = ComputeMaxError(d, first, last,
- bez_curve, uPrime, &splitPoint);
- if (max_err < error) {
- ZnFree(u);
- return;
- }
- ZnFree(u);
- u = uPrime;
- }
- }
-
- /* Fitting failed -- split at max error point and fit recursively */
- ZnFree(u);
- ZnListAssertSize(controls, ZnListSize(controls)-4);
- tHatCenter = ComputeCenterTangent(d, splitPoint);
- FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, controls);
- V2Negate(&tHatCenter);
- FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, controls);
-}
-
-void
-ZnFitBezier(ZnPoint *pts,
- unsigned int num_points,
- ZnReal error,
- ZnList controls)
-{
- ZnPoint tHat1, tHat2; /* Unit tangent vectors at endpoints */
-
- tHat1 = ComputeLeftTangent(pts, 0);
- tHat2 = ComputeRightTangent(pts, num_points-1);
- FitCubic(pts, 0, num_points-1, tHat1, tHat2, error, controls);
-}
-
diff --git a/generic/Geo.h b/generic/Geo.h
deleted file mode 100644
index 08c5892..0000000
--- a/generic/Geo.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Geo.h -- Header for common geometric routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Geo_h
-#define _Geo_h
-
-
-#include "Attrs.h"
-#include "List.h"
-
-#include <math.h>
-#include <limits.h>
-
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338327
-#endif
-#ifndef M_PI_2
-#define M_PI_2 1.57079632679489661923
-#endif
-#ifndef M_PI_4
-#define M_PI_4 0.78539816339744830962
-#endif
-
-#define PRECISION_LIMIT 1.0e-10
-#define X_PRECISION_LIMIT 5.0e-2
-#define ZN_LINE_END_POINTS 6
-
-/*
- * Constants used to specify circle approximation quality.
- */
-#define ZN_CIRCLE_COARSE 0
-#define ZN_CIRCLE_MEDIUM ZN_CIRCLE_COARSE+1
-#define ZN_CIRCLE_FINE ZN_CIRCLE_MEDIUM+1
-#define ZN_CIRCLE_FINER ZN_CIRCLE_FINE+1
-#define ZN_CIRCLE_FINEST ZN_CIRCLE_FINER+1
-
-
-/*
- * I would like to make these be floats,
- * but have to investigate how. Structures
- * handed to GL or GLU tess _must_ have
- * points has doubles.
- */
-typedef struct {
- double x, y;
-} ZnPoint;
-
-typedef struct {
- double x, y, w, h;
-} ZnRect;
-
-/*
- * ZnBBox: orig is into the area while corner is not.
- * Thus the test: ((bbox.orig.x == bbox.corner.x) ||
- * (bbox.orig.y == bbox.corner.y))
- * tells whether the bbox is empty or not.
- * When interpreting bboxes the X coordinate system is
- * the norm. x goes from left toward the right and y
- * goes from the top toward the bottom. Bboxes are
- * always axes aligned.
- */
-typedef struct {
- ZnPoint orig, corner;
-} ZnBBox;
-
-typedef struct {
- unsigned int num_points;
- ZnPoint *points;
- char *controls;
- ZnBool cw;
-} ZnContour;
-
-/*
- * contour1 can be used to store a single contour
- * without having to alloc the contours array.
- */
-typedef struct {
- unsigned int num_contours;
- ZnContour *contours;
- ZnContour contour1;
-} ZnPoly;
-
-/*
- * Keep this enum in sync with op_strings in Contour()
- * in tkZinc.c.
- */
-typedef enum {
- ZN_CONTOUR_ADD, ZN_CONTOUR_REMOVE
-} ZnContourCmd;
-
-typedef struct {
- unsigned int num_points;
- ZnPoint *points;
- ZnBool fan; /* When using a fan, all contour vertices must be
- * included to describe the contour as a polygon
- * (clipping code use that to speed up region
- * rendering) and the center must be the first
- * vertex. */
-} ZnStrip;
-
-typedef struct {
- unsigned int num_strips;
- ZnStrip *strips;
- ZnStrip strip1;
-} ZnTriStrip;
-
-
-#ifndef MIN
-#define MIN(a, b) ((a) <= (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) ((a) >= (b) ? (a) : (b))
-#endif
-#ifndef ABS
-#define ABS(a) ((a) < 0 ? -(a) : (a))
-#endif
-
-#define ZnDegRad(angle) \
- (M_PI * (double) (angle) / 180.0)
-#define ZnRadDeg(angle) \
- (fmod((angle) * 180.0 / M_PI, 360.0))
-#define ZnRadDeg360(angle) \
- (fmod(ZnRadDeg(angle)+360.0,360.0))
-
-#define ZnNearestInt(d) \
- (((int) ((d) + (((d) > 0) ? 0.5 : -0.5))))
-
-void
-ZnPolyInit(ZnPoly *poly);
-void
-ZnPolyContour1(ZnPoly *poly,
- ZnPoint *pts,
- unsigned int num_pts,
- ZnBool cw);
-void
-ZnPolySet(ZnPoly *poly1,
- ZnPoly *poly2);
-void
-ZnPolyFree(ZnPoly *poly);
-void
-ZnTriStrip1(ZnTriStrip *tristrip,
- ZnPoint *pts,
- unsigned int num_pts,
- ZnBool fan);
-void
-ZnTriFree(ZnTriStrip *tristrip);
-
-void
-ZnAnchor2Origin(ZnPoint *position,
- ZnDim width,
- ZnDim height,
- Tk_Anchor anchor,
- ZnPoint *origin);
-void
-ZnOrigin2Anchor(ZnPoint *origin,
- ZnDim width,
- ZnDim height,
- Tk_Anchor anchor,
- ZnPoint *position);
-void ZnRectOrigin2Anchor(ZnPoint *rect, Tk_Anchor anchor, ZnPoint *position);
-void
-ZnBBox2XRect(ZnBBox *bbox,
- XRectangle *rect);
-void
-ZnGetStringBBox(char *str,
- Tk_Font font,
- ZnPos x,
- ZnPos y,
- ZnBBox *str_bbox);
-void
-ZnResetBBox(ZnBBox *bbox);
-void
-ZnCopyBBox(ZnBBox *bbox_from,
- ZnBBox *bbox_to);
-void
-ZnIntersectBBox(ZnBBox *bbox1,
- ZnBBox *bbox2,
- ZnBBox *bbox_inter);
-ZnBool
-ZnIsEmptyBBox(ZnBBox *bbox);
-void
-ZnAddBBoxToBBox(ZnBBox *bbox,
- ZnBBox *bbox2);
-void
-ZnAddPointToBBox(ZnBBox *bbox,
- ZnPos px,
- ZnPos py);
-void
-ZnAddPointsToBBox(ZnBBox *bbox,
- ZnPoint *points,
- unsigned int num_points);
-void
-ZnAddStringToBBox(ZnBBox *bbox,
- char *str,
- Tk_Font font,
- ZnPos cx,
- ZnPos cy);
-ZnBool
-ZnPointInBBox(ZnBBox *bbox,
- ZnPos x,
- ZnPos y);
-
-int
-ZnLineInBBox(ZnPoint *p1,
- ZnPoint *p2,
- ZnBBox *bbox);
-
-int
-ZnBBoxInBBox(ZnBBox *bbox1,
- ZnBBox *bbox2);
-
-int
-ZnPolylineInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim width,
- int cap_style,
- int join_style,
- ZnBBox *bbox);
-
-int
-ZnPolygonInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnBBox *bbox,
- ZnBool *area_enclosed);
-
-int
-ZnOvalInBBox(ZnPoint *center,
- ZnDim width,
- ZnDim height,
- ZnBBox *bbox);
-
-ZnBool
-ZnHorizLineToArc(ZnReal x1,
- ZnReal x2,
- ZnReal y,
- ZnReal rx,
- ZnReal ry,
- int start_angle,
- int angle_extent);
-
-ZnBool
-ZnVertLineToArc(ZnReal x,
- ZnReal y1,
- ZnReal y2,
- ZnReal rx,
- ZnReal ry,
- int start_angle,
- int angle_extent);
-
-ZnBool
-ZnPointInAngle(int start_angle,
- int angle_extent,
- ZnPoint *p);
-
-void
-ZnPointPolarToCartesian(ZnReal heading,
- ZnReal rho,
- ZnReal theta,
- ZnReal *delta_x,
- ZnReal *delta_y);
-
-ZnReal
-ZnProjectionToAngle(ZnReal dx,
- ZnReal dy);
-
-ZnDim
-ZnRectangleToPointDist(ZnBBox *bbox,
- ZnPoint *p);
-ZnDim ZnLineToPointDist(ZnPoint *p1, ZnPoint *p2, ZnPoint *p, ZnPoint *closest);
-
-ZnDim
-ZnPolygonToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnPoint *p);
-
-ZnDim
-ZnPolylineToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnDim width,
- int cap_style,
- int join_style,
- ZnPoint *p);
-
-ZnDim
-ZnOvalToPointDist(ZnPoint *center,
- ZnDim width,
- ZnDim height,
- ZnDim line_width,
- ZnPoint *p);
-
-void
-ZnGetButtPoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim width,
- ZnBool projecting,
- ZnPoint *c1,
- ZnPoint *c2);
-
-ZnBool
-ZnGetMiterPoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnPoint *p3,
- ZnDim width,
- ZnPoint *c1,
- ZnPoint *c2);
-
-ZnBool
-ZnIntersectLines(ZnPoint *a1,
- ZnPoint *a2,
- ZnPoint *b1,
- ZnPoint *b2,
- ZnPoint *pi);
-
-void
-ZnShiftLine(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim dist,
- ZnPoint *p3,
- ZnPoint *p4);
-
-void
-ZnInsetPolygon(ZnPoint *p,
- unsigned int num_points,
- ZnDim inset);
-
-void
-ZnSmoothPathWithBezier(ZnPoint *from_points,
- unsigned int num_points,
- ZnList to_points);
-
-void
-ZnGetBezierPoints(ZnPoint *p1,
- ZnPoint *c1,
- ZnPoint *c2,
- ZnPoint *p2,
- ZnList to_points,
- double eps);
-void
-ZnGetBezierPath(ZnList from_points,
- ZnList to_points);
-
-
-ZnPoint *
-ZnGetCirclePoints(int type,
- int quality,
- ZnReal start_angle,
- ZnReal angle_extent,
- unsigned int *num_points,
- ZnList point_list);
-
-void
-ZnGetArcPath(ZnReal start_angle,
- ZnReal end_angle,
- int type,
- ZnList to_points);
-
-void
-ZnFitBezier(ZnPoint *pts,
- unsigned int num_points,
- ZnReal error,
- ZnList controls);
-
-ZnBool
-ZnTestCCW(ZnPoint *p,
- unsigned int num_points);
-
-
-#endif /* _Geo_h */
diff --git a/generic/Group.c b/generic/Group.c
deleted file mode 100644
index 1f6a183..0000000
--- a/generic/Group.c
+++ /dev/null
@@ -1,1781 +0,0 @@
-/*
- * Group.c -- Implementation of Group item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Wed Jun 23 10:09:20 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Item.h"
-#include "Group.h"
-#include "Geo.h"
-#include "tkZinc.h"
-
-#ifndef _WIN32
-#include <X11/extensions/shape.h>
-#endif
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * Group item special record.
- */
-typedef struct _GroupItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnItem clip;
- unsigned char alpha;
-
- /* Private data */
- ZnItem head; /* Doubly linked list of all items. */
- ZnItem tail;
- ZnList dependents; /* List of dependent items. */
-#ifdef ATC
- /* Overlap manager variables.
- * These variables are valid *only* if the overlap
- * manager is active. */
- ZnBool call_om; /* Tell if there is a need to call the */
- /* overlap manager. */
-#endif
-} GroupItemStruct, *GroupItem;
-
-
-#define ATOMIC_BIT (1<<ZN_PRIVATE_FLAGS_OFFSET)
-
-
-/*
- **********************************************************************************
- *
- * Specific Group item record
- *
- **********************************************************************************
- */
-static ZnAttrConfig group_attrs[] = {
- { ZN_CONFIG_ALPHA, "-alpha", NULL,
- Tk_Offset(GroupItemStruct, alpha), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-atomic", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ATOMIC_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_ITEM, "-clip", NULL,
- Tk_Offset(GroupItemStruct, clip), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_TRANSFO_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_TRANSFO_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(GroupItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(GroupItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(GroupItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- GroupItem group = (GroupItem) item;
-
- group->head = ZN_NO_ITEM;
- group->tail = ZN_NO_ITEM;
- group->clip = ZN_NO_ITEM;
- group->alpha = 100;
- group->dependents = NULL;
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- CLEAR(item->flags, ATOMIC_BIT);
- item->priority = 1;
-#ifdef ATC
- group->call_om = False;
-#endif
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- GroupItem group = (GroupItem) item;
- ZnList dependents;
- ZnItem connected, current_item, new_item;
- ZnItem *items;
- Tcl_HashTable mapping;
- Tcl_HashEntry *entry;
- int new, num_items, i;
-
- if (item == item->wi->top_group) {
- /* Do not try to clone the top group */
- return;
- }
-
- current_item = group->tail;
- group->head = group->tail = ZN_NO_ITEM;
-#ifdef ATC
- group->call_om = False;
-#endif
- dependents = group->dependents;
- if (dependents) {
- Tcl_InitHashTable(&mapping, TCL_ONE_WORD_KEYS);
- }
-
- /*
- * First clone all the children, and build a mapping
- * table if there is some attachments to relink.
- */
- while (current_item != ZN_NO_ITEM) {
- connected = current_item->connected_item;
- new_item = ZnITEM.CloneItem(current_item);
- new_item->connected_item = connected;
- ZnITEM.InsertItem(new_item, item, ZN_NO_ITEM, True);
-
- if (dependents) {
- entry = Tcl_CreateHashEntry(&mapping, (char *) current_item, &new);
- Tcl_SetHashValue(entry, (ClientData) new_item);
- }
- if (current_item == group->clip) {
- group->clip = new_item;
- }
- current_item = current_item->previous;
- }
-
- /*
- * Then rebuild the dependency list with
- * the new items.
- */
- if (dependents) {
- /*printf("rebuilding dependents\n");*/
- group->dependents = NULL;
- items = (ZnItem *) ZnListArray(dependents);
- num_items = ZnListSize(dependents);
- for (i = 0; i < num_items; i++, items++) {
- entry = Tcl_FindHashEntry(&mapping, (char *) *items);
- if (entry == NULL) {
- ZnWarning("Can't find item correspondance in Group Clone\n");
- abort();
- }
- else {
- current_item = (ZnItem) Tcl_GetHashValue(entry);
- }
- entry = Tcl_FindHashEntry(&mapping, (char *) current_item->connected_item);
- if (entry == NULL) {
- ZnWarning("Can't found item correspondance in Group Clone\n");
- abort();
- }
- else {
- /*printf("item %d correspond to ", current_item->connected_item->id);*/
- current_item->connected_item = (ZnItem) Tcl_GetHashValue(entry);
- /*printf("%d\n", current_item->connected_item->id);*/
- ZnInsertDependentItem(current_item);
- }
- }
- Tcl_DeleteHashTable(&mapping);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- GroupItem group = (GroupItem) item;
- ZnItem current_item, next_item;
-
- current_item = group->head;
- while (current_item != ZN_NO_ITEM) {
- next_item = current_item->next;
- ZnITEM.DestroyItem(current_item);
- current_item = next_item;
- }
- if (group->dependents) {
- ZnListFree(group->dependents);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * SetXShape --
- *
- **********************************************************************************
- */
-#if defined(SHAPE) && !defined(_WIN32)
-static void
-SetXShape(ZnItem grp)
-{
- ZnWInfo *wi = grp->wi;
- ZnItem clip = ((GroupItem) grp)->clip;
- unsigned int i, j, num_pts, max_num_pts;
- ZnPos min_x, min_y, max_x, max_y;
- ZnTriStrip tristrip;
- ZnPoint *p;
- ZnBool simple;
- ZnDim width, height;
- XPoint xpts[3], *xp2, *xpts2;
- TkRegion reg, reg_op, reg_to;
-
- if (ISCLEAR(wi->flags, ZN_HAS_X_SHAPE)) {
- return;
- }
-
- if ((clip == ZN_NO_ITEM) || !wi->reshape) {
- /*
- * Reset both clip just to be sure (the application can have
- * changed wi->full_reshape while resetting wi->reshape).
- */
- XShapeCombineMask(wi->dpy, Tk_WindowId(wi->win), ShapeBounding,
- 0, 0, None, ShapeSet);
- XShapeCombineMask(wi->dpy, wi->real_top, ShapeBounding,
- 0, 0, None, ShapeSet);
- }
- else {
- /*
- * Get the clip shape.
- */
- tristrip.num_strips = 0;
- simple = clip->class->GetClipVertices(clip, &tristrip);
- if (simple || (tristrip.num_strips == 0)) {
- /*
- * Nothing to do: after normalisation the rectangular shape will
- * fit exactly the window. We may test here if a shape is currently
- * active and reset the mask only in this case (need a flag in wi).
- */
- XShapeCombineMask(wi->dpy, Tk_WindowId(wi->win), ShapeBounding,
- 0, 0, None, ShapeSet);
- XShapeCombineMask(wi->dpy, wi->real_top, ShapeBounding,
- 0, 0, None, ShapeSet);
- }
- else {
- /*
- * First make the vertices start at zero.
- * In case of a fan we benefit from the fact that
- * ALL the contour vertices are included in
- * the tristrip, so we dont need to consider the
- * center (arc in pie slice mode).
- */
- max_x = min_x = tristrip.strips[0].points[0].x;
- max_y = min_y = tristrip.strips[0].points[0].y;
- max_num_pts = tristrip.strips[0].num_points;
- for (j = 0; j < tristrip.num_strips; j++) {
- p = tristrip.strips[j].points;
- num_pts = tristrip.strips[j].num_points;
- if (num_pts > max_num_pts) {
- max_num_pts = num_pts;
- }
- for (i = 0; i < num_pts; p++, i++) {
- if (p->x < min_x) {
- min_x = p->x;
- }
- if (p->y < min_y) {
- min_y = p->y;
- }
- if (p->x > max_x) {
- max_x = p->x;
- }
- if (p->y > max_y) {
- max_y = p->y;
- }
- }
- }
- max_x -= min_x;
- max_y -= min_y;
- XShapeCombineMask(wi->dpy, wi->full_reshape?Tk_WindowId(wi->win):wi->real_top,
- ShapeBounding, 0, 0, None, ShapeSet);
- reg = TkCreateRegion();
-
- /*
- * Now normalize the shape and map it to the window size,
- * then Translate it in a region and apply this region to
- * the window.
- */
- width = wi->width;
- height = wi->height;
- for (j = 0; j < tristrip.num_strips; j++) {
- p = tristrip.strips[j].points;
- num_pts = tristrip.strips[j].num_points;
-
- /*
- * In case of a fan we benefit from the fact that
- * ALL the contour vertices are included in
- * the tristrip, so we can use the corresponding
- * polygon instead of going through all the triangles.
- */
- if (tristrip.strips[j].fan) {
- /* Skip the center */
- p++;
- num_pts--;
- xp2 = xpts2 = ZnMalloc(num_pts*sizeof(XPoint));
- for (i = 0 ; i < num_pts; i++, p++, xp2++) {
- xp2->x = (short) ((p->x - min_x) * width / max_x);
- xp2->y = (short) ((p->y - min_y) * height / max_y);
- }
- reg_op = ZnPolygonRegion(xpts2, num_pts, EvenOddRule);
- reg_to = TkCreateRegion();
- ZnUnionRegion(reg, reg_op, reg_to);
- TkDestroyRegion(reg);
- TkDestroyRegion(reg_op);
- reg = reg_to;
- ZnFree(xpts2);
- }
- else {
- xpts[0].x = (short) ((p->x - min_x) * width / max_x);
- xpts[0].y = (short) ((p->y - min_y) * height / max_y);
- p++;
- xpts[1].x = (short) ((p->x - min_x) * width / max_x);
- xpts[1].y = (short) ((p->y - min_y) * height / max_y);
- p++;
- for (i = 2 ; i < num_pts; i++, p++) {
- xpts[2].x = (short) ((p->x - min_x) * width / max_x);
- xpts[2].y = (short) ((p->y - min_y) * height / max_y);
- reg_op = ZnPolygonRegion(xpts, 3, EvenOddRule);
- reg_to = TkCreateRegion();
- ZnUnionRegion(reg, reg_op, reg_to);
- TkDestroyRegion(reg);
- TkDestroyRegion(reg_op);
- reg = reg_to;
- xpts[0] = xpts[1];
- xpts[1] = xpts[2];
- }
- }
- }
- XShapeCombineRegion(wi->dpy, wi->full_reshape?wi->real_top:Tk_WindowId(wi->win),
- ShapeBounding, 0, 0, (Region) reg, ShapeSet);
- TkDestroyRegion(reg);
- }
- }
-}
-#else
-static void
-SetXShape(ZnItem grp)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- GroupItem group = (GroupItem) item;
- ZnWInfo *wi = item->wi;
-
- if (ZnConfigureAttributes(wi, item, item, group_attrs, argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- /*
- * If the clip item changed, check if it is a legal
- * item type that is inside this group.
- */
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- if (group->clip &&
- (!group->clip->class->GetClipVertices || (group->clip->parent != item))) {
- group->clip = ZN_NO_ITEM;
- Tcl_AppendResult(wi->interp,
- " clip item must be a child of the group", NULL);
- return TCL_ERROR;
- }
- if (!group->clip && (item == wi->top_group)) {
- SetXShape(item);
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, group_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * PushClip --
- * Save the current clip shape and current clipbox if needed.
- * Intersect the previous shape and the local to obtain the
- * new current shape. Use this shape to compute the current
- * clipbox and if set_gc is True compute the current region.
- *
- **********************************************************************************
- */
-static void
-PushClip(GroupItem group,
- ZnBool set_gc)
-{
- ZnWInfo *wi = ((ZnItem) group)->wi;
- ZnTriStrip tristrip;
- ZnBool simple;
-
- if ((group->clip != ZN_NO_ITEM) &&
- ((((ZnItem) group) != wi->top_group)
-#if defined(SHAPE) && ! defined (_WIN32)
- || !wi->reshape
-#endif
- )) {
- simple = group->clip->class->GetClipVertices(group->clip, &tristrip);
- /*printf("Group: PushClip group %d\n", ((ZnItem) group)->id);*/
- if (tristrip.num_strips) {
- ZnPushClip(wi, &tristrip, simple, set_gc);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * PopClip --
- * Re-install the previous clip shape if any (stack can be empty).
- *
- **********************************************************************************
- */
-static void
-PopClip(GroupItem group,
- ZnBool set_gc)
-{
- ZnWInfo *wi = ((ZnItem) group)->wi;
-
- if ((group->clip != ZN_NO_ITEM) &&
- ((((ZnItem) group) != wi->top_group)
-#if defined(SHAPE) && !defined(_WIN32)
- || !wi->reshape
-#endif
- )) {
- /*printf("Group: PopClip group %d\n", ((ZnItem) group)->id);*/
- ZnPopClip(wi, set_gc);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * PushTransform --
- * Save the current transform then concatenate the item transform to
- * form the new current transform.
- *
- **********************************************************************************
- */
-static void
-PushTransform(ZnItem item)
-{
- ZnPoint *pos;
-
- pos = NULL;
- if (item->class->pos_offset >= 0) {
- pos = (ZnPoint *) (((char *) item) + item->class->pos_offset);
- if (pos->x == 0 && pos->y == 0) {
- pos = NULL;
- }
- }
- if (!item->transfo &&
- !pos &&
- ISSET(item->flags, ZN_COMPOSE_SCALE_BIT) &&
- ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT)) {
- return;
- }
-
- ZnPushTransform(item->wi, item->transfo, pos,
- ISSET(item->flags, ZN_COMPOSE_SCALE_BIT),
- ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT));
- /*printf("Pushing transfo for item: %d\n;", item->id);
- ZnPrintTransfo(wi->current_transfo);*/
-}
-
-
-/*
- **********************************************************************************
- *
- * PopTransform --
- * Restore the previously saved transform from the stack.
- *
- **********************************************************************************
- */
-static void
-PopTransform(ZnItem item)
-{
- ZnPoint *pos;
-
- pos = NULL;
- if (item->class->pos_offset >= 0) {
- pos = (ZnPoint *) (((char *) item) + item->class->pos_offset);
- if (pos->x == 0 && pos->y == 0) {
- pos = NULL;
- }
- }
- if (!item->transfo &&
- !pos &&
- ISSET(item->flags, ZN_COMPOSE_SCALE_BIT) &&
- ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT)) {
- return;
- }
-
- ZnPopTransform(item->wi);
- /*printf("Popping transfo for item: %d\n", item->id);
- ZnPrintTransfo(wi->current_transfo);*/
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- * Compute the geometrical elements of a group. First of all save the current
- * transform and combine it with the item transform. Then call the item
- * ComputeCoordinates method.
- * For regular child items (not groups) some of the code of the item
- * itself is factored out in CallRegularCC.
- *
- **********************************************************************************
- */
-static void
-CallRegularCC(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- /*ZnBBox *clip_box;*/
-
- /*
- * Do some generic pre-work in behalf of the (regular) children.
- */
- if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
- ZnDamage(wi, &item->item_bounding_box);
- }
- PushTransform(item);
-
- /*printf("calling cc on regular item %d\n", item->id);*/
- /*ZnPrintTransfo(wi->current_transfo);*/
- item->class->ComputeCoordinates(item, False);
- /*
- * If a current clipbox exists adjust the item
- * bounding box accordingly. When computing coordinates
- * the damaged area is not pushed onto the clipstack,
- * the following predicate is thus valid for testing
- * a clipbox.
- */
- /* Tue Nov 14 15:21:05 2000 Suppressed to have a real
- bbox to align tiles (i.e if an object is larger than
- its enclosing clipping, the bbox is equal to the clip
- area and the tiling will not move with the object until
- it partially uncovered the clip area.
- Have to watch any possible breakage.
-
- if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
- ZnBBox inter;
-
- ZnIntersectBBox(&item->item_bounding_box, clip_box, &inter);
- item->item_bounding_box = inter;
- }*/
- /*
- * Do some generic post-work in behalf of the (regular) children.
- */
-#ifdef GL
-#ifdef GL_LIST
- /*
- * Remove the item display list so that it will be recreated
- * to reflect the changes.
- */
- if (item->gl_list) {
- glDeleteLists(item->gl_list, 1);
- item->gl_list = 0;
- }
-#endif
-#endif
- if (ISSET(item->inv_flags, ZN_REPICK_FLAG)) {
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- }
- if (ISSET(item->inv_flags, ZN_COORDS_FLAG) &&
- (ISSET(item->flags, ZN_SENSITIVE_BIT) ||
- ISSET(item->flags, ZN_VISIBLE_BIT))) {
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- }
- /*
- * Damage if the item is visible or if it is
- * a group clipper.
- */
- if (ISSET(item->flags, ZN_VISIBLE_BIT) ||
- (item == ((GroupItem) item->parent)->clip)) {
- ZnDamage(wi, &item->item_bounding_box);
- }
- PopTransform(item);
- item->inv_flags = 0;
- /*printf("Done cc on regular item %d\n", item->id);*/
-}
-
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- GroupItem group = (GroupItem) item;
- ZnItem current_item;
- ZnItem *deps;
- int num_deps, i;
- ZnBBox *clip_box;
-
- PushTransform(item);
- /* printf("Group.c\n");
- ZnPrintTransfo(item->wi->current_transfo);
- printf("\n");*/
-
- force |= ISSET(item->inv_flags, ZN_TRANSFO_FLAG);
-
- /*
- * If the clip item changed or there is no clip anymore
- * force an update.
- */
- force |= ISSET(item->inv_flags, ZN_ITEM_FLAG);
-
- /*
- * Clip shape is computed in the group's local
- * coordinates.
- */
- if (group->clip != ZN_NO_ITEM) {
- /*
- * Update the geometry of the clip item if needed.
- * Its bounding box will be clipped by the current
- * clipbox (i.e the clipbox of the group's parent).
- */
- if (force ||
- ISSET(group->clip->inv_flags, ZN_COORDS_FLAG) ||
- ISSET(group->clip->inv_flags, ZN_TRANSFO_FLAG)) {
- /*printf("calling cc on clip item %d for group %d\n",
- group->clip->id, item->id);*/
- CallRegularCC(group->clip);
- if (item == item->wi->top_group) {
- SetXShape(item);
- }
- /*
- * If the clip item has changed we need to compute
- * new clipped bounding boxes for all the children.
- */
- force = True;
- }
- }
-
- PushClip(group, False);
-
- for (current_item = group->head; current_item != ZN_NO_ITEM;
- current_item = current_item->next) {
- /*
- * Skip the clip item, it has been already updated.
- * Skip as well items with a dependency, they will
- * be updated later.
- */
- if ((current_item == group->clip) ||
- (current_item->connected_item != ZN_NO_ITEM)) {
- continue;
- }
- if (force ||
- ISSET(current_item->inv_flags, ZN_COORDS_FLAG) ||
- ISSET(current_item->inv_flags, ZN_TRANSFO_FLAG)) {
- if (current_item->class != ZnGroup) {
- /*printf("calling cc on item %d\n", current_item->id);*/
- CallRegularCC(current_item);
- }
- else {
- /*printf("calling cc on group %d\n", current_item->id);*/
- current_item->class->ComputeCoordinates(current_item, force);
- }
- }
- }
- /*
- * Update coordinates and bounding boxes following
- * a possible change in connected items. Only regular
- * items can be concerned.
- */
- if (group->dependents) {
- num_deps = ZnListSize(group->dependents);
- deps = (ZnItem *) ZnListArray(group->dependents);
- for (i = 0; i < num_deps; i++) {
- current_item = deps[i];
- if (force ||
- ISSET(current_item->inv_flags, ZN_COORDS_FLAG) ||
- ISSET(current_item->inv_flags, ZN_TRANSFO_FLAG) ||
- ISSET(current_item->connected_item->flags, ZN_UPDATE_DEPENDENT_BIT)) {
- /*printf("Updating dependent: %d\n", current_item->id);*/
- CallRegularCC(current_item);
- }
- }
- /*
- * Now, we must reset the update_dependent flag
- */
- for (i = 0; i < num_deps; i++) {
- CLEAR(deps[i]->connected_item->flags, ZN_UPDATE_DEPENDENT_BIT);
- }
- /*printf("... done\n");*/
- }
- /*
- * Compute the bounding box.
- */
- ZnResetBBox(&item->item_bounding_box);
- current_item = group->head;
- while (current_item != ZN_NO_ITEM) {
- ZnAddBBoxToBBox(&item->item_bounding_box, &current_item->item_bounding_box);
- current_item = current_item->next;
- }
- /*
- * Limit the group actual bounding box to
- * the clip shape boundary.
- */
- if (group->clip) {
- clip_box = &group->clip->item_bounding_box;
- ZnIntersectBBox(&item->item_bounding_box, clip_box, &item->item_bounding_box);
- }
- item->inv_flags = 0;
-
- PopClip(group, False);
- PopTransform(item);
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- GroupItem group = (GroupItem) item;
- ZnItem current_item;
- ZnBBox enclosing, inter;
- int result = -1;
- ZnBool outside, inside;
- ZnBool atomic, report, empty = True;
-
-
- PushTransform(item);
- report = ta->report;
-
- /*
- * Is this group the target group ?
- */
- if ((ta->in_group != ZN_NO_ITEM) && (ta->in_group != item)) {
- /* No, try the subgroups. */
- for (current_item = group->head;
- current_item != ZN_NO_ITEM;
- current_item = current_item->next) {
- if (current_item->class != ZnGroup) {
- continue;
- }
- result = current_item->class->ToArea(current_item, ta);
- if (ta->in_group == ZN_NO_ITEM) {
- /* The target group has been found, return its result. */
- goto out;
- }
- }
- /* No group found in this subtree. */
- goto out;
- }
-
- /*
- * At this point we are either in the target group
- * or one of its sub-groups. If in the target group,
- * erase the target in the call struct to remember
- * the fact.
- */
- if (ta->in_group == item) {
- /*
- * We are in the target group, mark the fact and bypass the group
- * atomicity.
- */
- ta->in_group = ZN_NO_ITEM;
- atomic = False;
- }
- else {
- /*
- * We are below the start group, If this group is ATOMIC,
- * ask the child groups to report instead of adding their
- * children to the result.
- */
- atomic = ISSET(item->flags, ATOMIC_BIT) && !ta->override_atomic;
- ta->report |= atomic;
- }
-
- enclosing.orig.x = ta->area->orig.x - 1;
- enclosing.orig.y = ta->area->orig.y - 1;
- enclosing.corner.x = ta->area->corner.x + 1;
- enclosing.corner.y = ta->area->corner.y + 1;
- outside = inside = True;
- /*
- * Process each item and proceed with subtrees if
- * asked for by the recursive flag.
- */
- /* printf("searching in group %d\n", item?item->id:0);*/
- for (current_item = group->head;
- current_item != ZN_NO_ITEM;
- current_item = current_item->next) {
- if (ISCLEAR(current_item->flags, ZN_VISIBLE_BIT) &&
- ISCLEAR(current_item->flags, ZN_SENSITIVE_BIT)) {
- continue;
- }
- /*printf("visible&sensitive %d\n", current_item?current_item->id:0);*/
- ZnIntersectBBox(&enclosing, &current_item->item_bounding_box, &inter);
- if (ZnIsEmptyBBox(&inter)) {
- continue;
- }
- /*printf("bbox test passed %d\n", current_item?current_item->id:0);*/
- if ((current_item->class != ZnGroup) || atomic || ta->recursive || ISSET(current_item->flags, ATOMIC_BIT)) {
- if (current_item->class != ZnGroup) {
- /*printf("testing %d\n", current_item?current_item->id:0);*/
- PushTransform(current_item);
- result = current_item->class->ToArea(current_item, ta);
- PopTransform(current_item);
- }
- else {
- result = current_item->class->ToArea(current_item, ta);
- }
- outside &= (result == -1);
- inside &= (result == 1);
- empty = False;
-
- /*
- * If this group is ATOMIC, it must report itself as matching
- * if a/ the request is 'enclosed' and all the children are
- * enclosed or b/ the request is 'overlapping' and at least one
- * child overlaps (or is enclosed).
- * So here we can do early tests to shortcut the search when
- * the most stringent conditions are met.
- */
- if (atomic) {
- if (!ta->enclosed && (result >= 0)) {
- result = 0;
- goto out;
- } else if (ta->enclosed && (result == 0)) {
- goto out;
- }
- }
- if (!ta->report && (result >= ta->enclosed)) {
- /*printf("Doing %d\n", current_item?current_item->id:0);*/
- ZnDoItem(item->wi->interp, current_item, ZN_NO_PART, ta->tag_uid);
- }
- }
- }
-
- /*
- * If there are no items or only sub-groups in this group and
- * the search is not recursive we must report outside.
- */
- if (empty) {
- result = -1;
- }
- else {
- if (atomic) {
- result = outside ? -1 : 1;
- }
- else if (ta->report) { /* Need to report matching children to ancestor */
- if (outside && inside) {
- result = 0;
- }
- else {
- result = outside ? -1 : 1;
- }
- }
- else {
- result = -1;
- }
- }
-
- out:
- ta->report = report;
- PopTransform(item);
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- GroupItem group = (GroupItem) item;
- ZnWInfo *wi = item->wi;
- ZnItem current_item;
- ZnBBox bbox, old_damaged_area, *clip_box;
-
- PushTransform(item);
- PushClip(group, True);
- if (group->clip != ZN_NO_ITEM) {
- old_damaged_area = wi->damaged_area;
- if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
- ZnIntersectBBox(&wi->damaged_area, clip_box, &bbox);
- wi->damaged_area = bbox;
- }
- }
-
- current_item = group->tail;
- while (current_item != ZN_NO_ITEM) {
- if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {
- ZnIntersectBBox(&wi->damaged_area, &current_item->item_bounding_box, &bbox);
- if (!ZnIsEmptyBBox(&bbox)) {
- if (current_item->class != ZnGroup) {
- PushTransform(current_item);
- }
- current_item->class->Draw(current_item);
- if (wi->draw_bboxes) {
- XGCValues values;
- values.foreground = ZnGetGradientPixel(wi->bbox_color, 0.0);
- values.fill_style = FillSolid;
- values.line_width = 1;
- values.line_style = (current_item->class==ZnGroup)?LineOnOffDash:LineSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCLineStyle|GCLineWidth|GCFillStyle,
- &values);
- XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- (int) current_item->item_bounding_box.orig.x,
- (int) current_item->item_bounding_box.orig.y,
- (unsigned int) (current_item->item_bounding_box.corner.x -
- current_item->item_bounding_box.orig.x),
- (unsigned int) (current_item->item_bounding_box.corner.y -
- current_item->item_bounding_box.orig.y));
- }
- if (current_item->class != ZnGroup) {
- PopTransform(current_item);
- }
- }
- }
- current_item = current_item->previous;
- }
-
- if (group->clip != ZN_NO_ITEM) {
- wi->damaged_area = old_damaged_area;
- }
- PopClip(group, True);
- PopTransform(item);
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- GroupItem group = (GroupItem) item;
- ZnItem current_item;
- ZnWInfo *wi = item->wi;
-#ifdef GL_DAMAGE
- ZnBBox *clip_box;
- ZnBBox bbox, old_damaged_area;
-#endif
- unsigned char save_alpha = wi->alpha;
- unsigned char save_alpha2;
-
- if (ISSET(item->flags, ZN_COMPOSE_ALPHA_BIT)) {
- wi->alpha = wi->alpha * group->alpha / 100;
- }
- else {
- wi->alpha = group->alpha;
- }
- save_alpha2 = wi->alpha;
-
- PushTransform(item);
- PushClip(group, True);
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT) && (group->clip != ZN_NO_ITEM)) {
- old_damaged_area = wi->damaged_area;
- if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
- ZnIntersectBBox(&wi->damaged_area, clip_box, &bbox);
- wi->damaged_area = bbox;
- }
- }
-#endif
-
- current_item = group->tail;
- while (current_item != ZN_NO_ITEM) {
- if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {
-#ifdef GL_DAMAGE
- ZnIntersectBBox(&wi->damaged_area, &current_item->item_bounding_box, &bbox);
- if (!ZnIsEmptyBBox(&bbox) || ISSET(wi->flags, ZN_CONFIGURE_EVENT)) {
-#endif
- if (current_item->class != ZnGroup) {
- PushTransform(current_item);
- if (ISCLEAR(current_item->flags, ZN_COMPOSE_ALPHA_BIT)) {
- wi->alpha = 100;
- }
- }
- current_item->class->Render(current_item);
- if (current_item->class != ZnGroup) {
- PopTransform(current_item);
- wi->alpha = save_alpha2;
- }
-#ifdef GL_DAMAGE
- }
-#endif
- }
- current_item = current_item->previous;
- }
-
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT) && (group->clip != ZN_NO_ITEM)) {
- wi->damaged_area = old_damaged_area;
- }
-#endif
-
- PopClip(group, True);
- PopTransform(item);
-
- wi->alpha = save_alpha;
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- ZnBool sensitive = ISSET(item->flags, ZN_SENSITIVE_BIT);
- ZnItem parent = item->parent;
-
- while (sensitive && (parent != ZN_NO_ITEM)) {
- sensitive &= ISSET(parent->flags, ZN_SENSITIVE_BIT);
- parent = parent->parent;
- }
- return sensitive;
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- * Given a point an an aperture, find the topmost group item/part
- * that is (a) within the pick_aperture
- * (b) the top most
- * (c) has either its sensibility or its visibility set.
- *
- * Results:
- * The return value is the distance of the picked item/part if one
- * has been found or a really big distance if not. a_item and a_part
- * are set to point the picked item/part or to ZN_NO_ITEM/ZN_NO_PART.
- * If the group is ATOMIC, a_item points the group instead of the
- * actual item.
- *
- * Side effects:
- * None.
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- GroupItem group = (GroupItem) item;
- ZnItem p_item=ZN_NO_ITEM, current_item;
- ZnWInfo *wi = item->wi;
- int p_part=0, aperture = ps->aperture;
- double dist, best = 1e10;
- ZnBBox bbox, inter, *clip_box;
- ZnPoint *p = ps->point;
- ZnBool atomic;
- TkRegion reg;
-
- ps->a_item= ZN_NO_ITEM;
- ps->a_part = ZN_NO_PART;
-
- if (group->head == ZN_NO_ITEM) {
- return best;
- }
-
- PushTransform(item);
- PushClip(group, False);
-
- /*
- * Is this group the target group ?
- */
- if ((ps->in_group != ZN_NO_ITEM) && (ps->in_group != item)) {
- /* No, try the subgroups. */
- for (current_item = group->head;
- current_item != ZN_NO_ITEM;
- current_item = current_item->next) {
- if (current_item->class != ZnGroup) {
- continue;
- }
- best = current_item->class->Pick(current_item, ps);
- if (ps->in_group == ZN_NO_ITEM) {
- /* The target group has been found, return its result. */
- goto out;
- }
- }
- /* No group found in this subtree. */
- goto out;
- }
-
- /*
- * At this point we are either in the target group
- * or one of its sub-groups. If in the target group,
- * erase the target in the call struct to remember
- * the fact.
- */
- if (ps->in_group == item) {
- ps->in_group = ZN_NO_ITEM;
- }
-
- bbox.orig.x = p->x - aperture;
- bbox.orig.y = p->y - aperture;
- bbox.corner.x = p->x + (aperture?aperture:1);
- bbox.corner.y = p->y + (aperture?aperture:1);
-
- if (ZnCurrentClip(wi, &reg, &clip_box, NULL)) {
- ZnIntersectBBox(&bbox, clip_box, &inter);
- if (ZnIsEmptyBBox(&inter)) {
- goto out;
- }
- if (reg && !ZnPointInRegion(reg, (int) p->x, (int) p->y)) {
- goto out;
- }
- }
-
- current_item = (ps->start_item == ZN_NO_ITEM) ? group->head : ps->start_item;
- atomic = ISSET(item->flags, ATOMIC_BIT) && !ps->override_atomic;
-
- for ( ; current_item != ZN_NO_ITEM; current_item = current_item->next) {
- /*
- * Sensitive item must be reported even if they are invisible.
- * It is legal to fire bindings on invisible sensitive items.
- * This is _not_ a bug do _not_ modify the test below.
- */
- if (ISCLEAR(current_item->flags, ZN_SENSITIVE_BIT) &&
- ISCLEAR(current_item->flags, ZN_VISIBLE_BIT)) {
- continue;
- }
- ZnIntersectBBox(&bbox, &current_item->item_bounding_box, &inter);
- if (ZnIsEmptyBBox(&inter)) {
- continue;
- }
- if (current_item->class != ZnGroup) {
- PushTransform(current_item);
- p_item = ps->a_item;
- p_part = ps->a_part;
- ps->a_item = current_item;
- ps->a_part = ZN_NO_PART;
- dist = current_item->class->Pick(current_item, ps);
- dist -= aperture;
- PopTransform(current_item);
- }
- else if (!atomic && !ps->recursive) {
- continue;
- }
- else {
- dist = current_item->class->Pick(current_item, ps);
- }
- if (dist < 0.0) {
- dist = 0.0;
- }
- if (dist >= best) {
- /* Not a good one, restore the previous best and try again. */
- ps->a_item = p_item;
- ps->a_part = p_part;
- continue;
- }
- if (atomic) {
- /* If ATOMIC, this group is the item to be reported. */
- ps->a_item = item;
- ps->a_part = ZN_NO_PART;
- }
-
- best = dist;
- /*printf("found %d:%d, at %g\n", (ps->a_item)->id, ps->a_part, dist);*/
- if (dist == 0.0) {
- /* No need to look further, the item found is the topmost
- * closest. */
- break;
- }
- }
-
- out:
- PopClip(group, False);
- PopTransform(item);
-
- return best;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the group translation (can be also interpreted as the
- * position of the group origin in the group's parent).
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " can't add or remove vertices in groups", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on groups", NULL);
- return TCL_ERROR;
- }
- if (!item->transfo && ((*pts)[0].x == 0.0) && ((*pts)[0].y == 0.0)) {
- return TCL_OK;
- }
- if (!item->transfo) {
- item->transfo = ZnTransfoNew();
- }
- ZnTranslate(item->transfo, (*pts)[0].x, (*pts)[0].y, True);
- ZnITEM.Invalidate(item, ZN_TRANSFO_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- ZnPoint *p;
-
- ZnListAssertSize(ZnWorkPoints, 1);
- p = (ZnPoint *) ZnListArray(ZnWorkPoints);
- ZnTransfoDecompose(item->transfo, NULL, p, NULL, NULL);
- *num_pts = 1;
- *pts = p;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- GroupItem group = (GroupItem) item;
- ZnWInfo *wi = item->wi;
- ZnItem current_item;
- ZnBBox bbox;
- int result = TCL_OK;
- char msg[500];
-
- PushTransform(item);
- PushClip(group, True);
-
- for (current_item = group->tail; current_item != ZN_NO_ITEM;
- current_item = current_item->previous) {
- if (ISCLEAR(current_item->flags, ZN_VISIBLE_BIT)) {
- continue;
- }
- //printf("area %g %g %g %g\n", area->orig.x, area->orig.y,
- // area->corner.x, area->corner.y);
- ZnIntersectBBox(area, &current_item->item_bounding_box, &bbox);
- if (ZnIsEmptyBBox(&bbox)) {
- continue;
- }
- if (current_item->class->PostScript == NULL) {
- continue;
- }
-
- if (current_item->class != ZnGroup) {
- PushTransform(current_item);
- if (!prepass) {
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- }
- ZnPostscriptTrace(current_item, 1);
- }
- result = current_item->class->PostScript(current_item, prepass, area);
- if (current_item->class != ZnGroup) {
- ZnPostscriptTrace(current_item, 0);
- if (!prepass && (result == TCL_OK)) {
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- PopTransform(current_item);
- }
- if (result == TCL_ERROR) {
- if (!prepass) {
- /*
- * Add some trace to ease the error lookup.
- */
- sprintf(msg, "\n (generating Postscript for item %d)", current_item->id);
- Tcl_AddErrorInfo(wi->interp, msg);
- break;
- }
- }
- }
-
- PopClip(group, True);
- PopTransform(item);
-
- if (!prepass && (result == TCL_OK)) {
- ZnFlushPsChan(wi->interp, wi->ps_info);
- }
- return result;
-}
-
-
-
-ZnItem
-ZnGroupHead(ZnItem group)
-{
- if (group->class != ZnGroup) {
- return ZN_NO_ITEM;
- }
- return ((GroupItem) group)->head;
-}
-
-ZnItem
-ZnGroupTail(ZnItem group)
-{
- if (group->class != ZnGroup) {
- return ZN_NO_ITEM;
- }
- return ((GroupItem) group)->tail;
-}
-
-#ifdef ATC
-ZnBool
-ZnGroupCallOm(ZnItem group)
-{
- if (group->class != ZnGroup) {
- return False;
- }
- return ((GroupItem) group)->call_om;
-}
-
-void
-ZnGroupSetCallOm(ZnItem group,
- ZnBool set)
-{
- if (group->class != ZnGroup) {
- return;
- }
- ((GroupItem) group)->call_om = set;
-}
-#else
-ZnBool
-ZnGroupCallOm(ZnItem group)
-{
- return False;
-}
-
-void
-ZnGroupSetCallOm(ZnItem group,
- ZnBool set)
-{
- return;
-}
-#endif
-
-ZnBool
-ZnGroupAtomic(ZnItem group)
-{
- if (group->class != ZnGroup) {
- return True;
- }
- return ISSET(group->flags, ATOMIC_BIT);
-}
-
-void
-ZnGroupRemoveClip(ZnItem group,
- ZnItem clip)
-{
- GroupItem grp = (GroupItem) group;
-
- if (grp->clip == clip) {
- grp->clip = ZN_NO_ITEM;
- ZnITEM.Invalidate(group, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnInsertDependentItem --
- *
- **********************************************************************************
- */
-void
-ZnInsertDependentItem(ZnItem item)
-{
- GroupItem group = (GroupItem) item->parent;
-
- if (!group) {
- return;
- }
- if (!group->dependents) {
- group->dependents = ZnListNew(2, sizeof(ZnItem));
- }
- ZnListAdd(group->dependents, &item, ZnListTail);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnExtractDependentItem --
- *
- **********************************************************************************
- */
-void
-ZnExtractDependentItem(ZnItem item)
-{
- GroupItem group = (GroupItem) item->parent;
- unsigned int index, num_items;
- ZnItem *deps;
-
- if (!group || !group->dependents) {
- return;
- }
- num_items = ZnListSize(group->dependents);
- deps = (ZnItem *) ZnListArray(group->dependents);
- for (index = 0; index < num_items; index++) {
- if (deps[index]->id == item->id) {
- ZnListDelete(group->dependents, index);
- if (ZnListSize(group->dependents) == 0) {
- ZnListFree(group->dependents);
- group->dependents = NULL;
- break;
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDisconnectDependentItems --
- *
- *
- **********************************************************************************
- */
-void
-ZnDisconnectDependentItems(ZnItem item)
-{
- ZnItem current_item;
- GroupItem group = (GroupItem) item->parent;
- ZnItem *deps;
- unsigned int num_deps;
- int i;
-
- if (!group || !group->dependents) {
- return;
- }
- deps = (ZnItem *) ZnListArray(group->dependents);
- num_deps = ZnListSize(group->dependents);
-
- for (i = num_deps-1; i >= 0; i--) {
- current_item = deps[i];
- if (current_item->connected_item == item) {
- current_item->connected_item = ZN_NO_ITEM;
- ZnListDelete(group->dependents, i);
- ZnITEM.Invalidate(current_item, ZN_COORDS_FLAG);
- }
- }
- if (ZnListSize(group->dependents) == 0) {
- ZnListFree(group->dependents);
- group->dependents = NULL;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGroupExtractItem --
- *
- **********************************************************************************
- */
-void
-ZnGroupExtractItem(ZnItem item)
-{
- GroupItem group;
-
- if (!item->parent) {
- return;
- }
- group = (GroupItem) item->parent;
-
- if (item->previous != ZN_NO_ITEM) {
- item->previous->next = item->next;
- }
- else {
- group->head = item->next;
- }
-
- if (item->next != ZN_NO_ITEM) {
- item->next->previous = item->previous;
- }
- else {
- group->tail = item->previous;
- }
-
- ZnITEM.Invalidate((ZnItem) group, ZN_COORDS_FLAG);
-
- item->previous = ZN_NO_ITEM;
- item->next = ZN_NO_ITEM;
- item->parent = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGroupInsertItem --
- *
- **********************************************************************************
- */
-void
-ZnGroupInsertItem(ZnItem group,
- ZnItem item,
- ZnItem mark_item,
- ZnBool before)
-{
- GroupItem grp = (GroupItem) group;
-
- /*
- * Empty list, add the first item.
- */
- if (grp->head == ZN_NO_ITEM) {
- grp->head = grp->tail = item;
- item->previous = item->next = ZN_NO_ITEM;
- return;
- }
-
- if (mark_item != ZN_NO_ITEM) {
- /*
- * Better leave here, mark_item will not
- * have the links set right.
- */
- if (mark_item == item) {
- return;
- }
- /*
- * Force the priority to be the same as the reference
- * item;
- */
- item->priority = mark_item->priority;
- }
- else {
- mark_item = grp->head;
- while ((mark_item != ZN_NO_ITEM) &&
- (mark_item->priority > item->priority)) {
- mark_item = mark_item->next;
- }
- before = True;
- }
-
- if (before && (mark_item != ZN_NO_ITEM)) {
- /*
- * Insert before mark.
- */
- item->next = mark_item;
- item->previous = mark_item->previous;
- if (mark_item->previous == ZN_NO_ITEM) {
- grp->head = item;
- }
- else {
- mark_item->previous->next = item;
- }
- mark_item->previous = item;
- }
- else {
- /*
- * Insert after mark either because 'before' is False
- * and mark_item valid or because the right place is at
- * the end of the list and mark_item is ZN_NO_ITEM.
- */
- if (mark_item == ZN_NO_ITEM) {
- grp->tail->next = item;
- item->previous = grp->tail;
- grp->tail = item;
- }
- else {
- item->previous = mark_item;
- item->next = mark_item->next;
- if (item->next == ZN_NO_ITEM) {
- grp->tail = item;
- }
- else {
- item->next->previous = item;
- }
- mark_item->next = item;
- }
- }
-
- ZnITEM.Invalidate(group, ZN_COORDS_FLAG);
-}
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnBBox *bbox = &item->item_bounding_box;
-
- ZnOrigin2Anchor(&bbox->orig,
- bbox->corner.x - bbox->orig.x,
- bbox->corner.y - bbox->orig.y,
- anchor, p);
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct GROUP_ITEM_CLASS = {
- "group",
- sizeof(GroupItemStruct),
- group_attrs,
- 0, /* num_parts */
- ZN_CLASS_ONE_COORD, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- NULL, /* GetClipVertices */
- NULL, /* GetContours */
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnGroup = (ZnItemClassId) &GROUP_ITEM_CLASS;
diff --git a/generic/Group.h b/generic/Group.h
deleted file mode 100644
index 937dec7..0000000
--- a/generic/Group.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Group.h -- Header for Group items.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 2002 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Group_h
-#define _Group_h
-
-
-ZnItem ZnGroupHead(ZnItem group);
-ZnItem ZnGroupTail(ZnItem group);
-ZnBool ZnGroupCallOm(ZnItem group);
-ZnBool ZnGroupAtomic(ZnItem group);
-void ZnGroupSetCallOm(ZnItem group, ZnBool set);
-void ZnInsertDependentItem(ZnItem item);
-void ZnExtractDependentItem(ZnItem item);
-void ZnDisconnectDependentItems(ZnItem item);
-void ZnGroupInsertItem(ZnItem group, ZnItem item, ZnItem mark_item, ZnBool before);
-void ZnGroupExtractItem(ZnItem item);
-void ZnGroupRemoveClip(ZnItem group, ZnItem clip);
-
-#endif /* _Group_h */
diff --git a/generic/Icon.c b/generic/Icon.c
deleted file mode 100644
index 5b9eae8..0000000
--- a/generic/Icon.c
+++ /dev/null
@@ -1,949 +0,0 @@
-/*
- * Icon.c -- Implementation of Icon item.
- *
- * Authors : Patrick LECOANET
- * Creation date : Sat Mar 25 13:53:39 1995
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "Types.h"
-#include "Image.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- **********************************************************************************
- *
- * Specific Icon item record
- *
- **********************************************************************************
- */
-typedef struct _IconItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint pos;
- ZnImage image;
- Tk_Anchor anchor;
- Tk_Anchor connection_anchor;
- ZnGradient *color; /* Used only if the image is a bitmap (in GL alpha part
- * is always meaningful). */
-
- /* Private data */
- ZnPoint dev[4];
-} IconItemStruct, *IconItem;
-
-
-static ZnAttrConfig icon_attrs[] = {
- { ZN_CONFIG_ANCHOR, "-anchor", NULL,
- Tk_Offset(IconItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-color", NULL,
- Tk_Offset(IconItemStruct, color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(IconItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
- Tk_Offset(IconItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_IMAGE, "-image", NULL,
- Tk_Offset(IconItemStruct, image), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-mask", NULL,
- Tk_Offset(IconItemStruct, image), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(IconItemStruct, pos), 0,
- ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(IconItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(IconItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(IconItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(IconItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
-
- /*printf("size of an icon(header) = %d(%d)\n",
- sizeof(IconItemStruct), sizeof(ZnItemStruct));*/
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 1;
-
- icon->pos.x = icon->pos.y = 0.0;
- icon->image = ZnUnspecifiedImage;
- icon->anchor = TK_ANCHOR_NW;
- icon->connection_anchor = TK_ANCHOR_SW;
- icon->color = ZnGetGradientByValue(wi->fore_color);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- IconItem icon = (IconItem) item;
-
- if (icon->image != ZnUnspecifiedImage) {
- icon->image = ZnGetImageByValue(icon->image, ZnUpdateItemImage, item);
- }
- icon->color = ZnGetGradientByValue(icon->color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- IconItem icon = (IconItem) item;
-
- if (icon->image != ZnUnspecifiedImage) {
- ZnFreeImage(icon->image, ZnUpdateItemImage, item);
- icon->image = ZnUnspecifiedImage;
- }
- ZnFreeGradient(icon->color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ZnItem old_connected;
-
- old_connected = item->connected_item;
- if (ZnConfigureAttributes(item->wi, item, item, icon_attrs,
- argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- /*
- * If the new connected item is not appropriate back up
- * to the old one.
- */
- if ((item->connected_item == ZN_NO_ITEM) ||
- (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
- (item->parent == item->connected_item->parent))) {
- ZnITEM.UpdateItemDependency(item, old_connected);
- }
- else {
- item->connected_item = old_connected;
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, icon_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- * Compute the transformation to be used and the origin
- * of the icon (upper left point in item coordinates).
- */
-static ZnTransfo *
-ComputeTransfoAndOrigin(ZnItem item,
- ZnPoint *origin)
-{
- IconItem icon = (IconItem) item;
- int w, h;
- ZnTransfo *t;
-
- ZnSizeOfImage(icon->image, &w, &h);
-
- /*
- * The connected item support anchors, this is checked by configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- ZnTransfo inv;
-
- item->connected_item->class->GetAnchor(item->connected_item,
- icon->connection_anchor,
- origin);
-
- /* GetAnchor return a position in device coordinates not in
- * the item coordinate space. To compute the icon origin
- * (upper left corner), we must apply the inverse transform
- * to the ref point before calling anchor2origin.
- */
- ZnTransfoInvert(item->transfo, &inv);
- ZnTransformPoint(&inv, origin, origin);
- /*
- * The relevant transform in case of an attachment is the item
- * transform alone. This is case of local coordinate space where
- * only the translation is a function of the whole transform
- * stack, scale and rotation are reset.
- */
- t = item->transfo;
- }
- else {
- origin->x = origin->y = 0;
- t = item->wi->current_transfo;
- }
-
- ZnAnchor2Origin(origin, (ZnReal) w, (ZnReal) h, icon->anchor, origin);
- //origin->x = ZnNearestInt(origin->x);
- //origin->y = ZnNearestInt(origin->y);
-
- return t;
-}
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- //ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
- int width, height, i;
- ZnPoint quad[4];
- ZnTransfo *t;
-
- ZnResetBBox(&item->item_bounding_box);
-
- /*
- * If there is no image then nothing to show.
- */
- if (icon->image == ZnUnspecifiedImage) {
- return;
- }
-
- ZnSizeOfImage(icon->image, &width, &height);
- t = ComputeTransfoAndOrigin(item, quad);
-
- quad[1].x = quad[0].x;
- quad[1].y = quad[0].y + height;
- quad[2].x = quad[0].x + width;
- quad[2].y = quad[1].y;
- quad[3].x = quad[2].x;
- quad[3].y = quad[0].y;
- ZnTransformPoints(t, quad, icon->dev, 4);
-
- for (i = 0; i < 4; i++) {
- icon->dev[i].x = ZnNearestInt(icon->dev[i].x);
- icon->dev[i].y = ZnNearestInt(icon->dev[i].y);
- }
-
- /*
- * Compute the bounding box.
- */
- ZnAddPointsToBBox(&item->item_bounding_box, icon->dev, 4);
-
- /*
- * Update connected items.
- */
- SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- IconItem icon = (IconItem) item;
-
- if (icon->image == ZnUnspecifiedImage) {
- return -1;
- }
-
- return ZnPolygonInBBox(icon->dev, 4, ta->area, NULL);
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
- XGCValues values;
- unsigned int gc_mask = 0;
- int w, h;
- ZnBBox box, inter, *clip_box;
- TkRegion clip_region, photo_region, clip;
- ZnBool simple;
- Pixmap pixmap;
-
- if (icon->image == ZnUnspecifiedImage) {
- return;
- }
-
- ZnSizeOfImage(icon->image, &w, &h);
- box.orig = *icon->dev;
- box.corner.x = icon->dev->x + w;
- box.corner.y = icon->dev->y + h;
- if (!ZnImageIsBitmap(icon->image)) {
- if (ZnTransfoIsTranslation(item->wi->current_transfo)) {
- /*
- * The code below does not use of Tk_RedrawImage to be
- * able to clip with the current clip region.
- */
- ZnIntersectBBox(&box, &wi->damaged_area, &inter);
- box = inter;
- ZnCurrentClip(wi, &clip_region, NULL, NULL);
- pixmap = ZnImagePixmap(icon->image, wi->win);
- photo_region = ZnImageRegion(icon->image);
- clip = TkCreateRegion();
- /*
- * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
- * some internal TkPhoto functions.
- * This is a workaround using a rectangular region based
- * on the image size.
- */
- if (photo_region == NULL) {
- XRectangle rect;
- rect.x = rect.y = 0;
- rect.width = w;
- rect.height = h;
- TkUnionRectWithRegion(&rect, clip, clip);
- }
- else {
- ZnUnionRegion(clip, photo_region, clip);
- }
- ZnOffsetRegion(clip, (int) icon->dev->x, (int) icon->dev->y);
- TkIntersectRegion(clip_region, clip, clip);
- TkSetRegion(wi->dpy, wi->gc, clip);
- XCopyArea(wi->dpy, pixmap, wi->draw_buffer, wi->gc,
- (int) (box.orig.x-icon->dev->x),
- (int) (box.orig.y-icon->dev->y),
- (unsigned int) (box.corner.x-box.orig.x),
- (unsigned int) (box.corner.y-box.orig.y),
- (int) box.orig.x,
- (int) box.orig.y);
- values.clip_x_origin = values.clip_y_origin = 0;
- XChangeGC(wi->dpy, wi->gc, GCClipXOrigin|GCClipYOrigin, &values);
- TkSetRegion(wi->dpy, wi->gc, clip_region);
- TkDestroyRegion(clip);
- }
- else {
- ZnPoint box[4];
- int i;
- XImage *dest_im, *src_im;
- XImage *dest_mask, *src_mask;
- Pixmap drw, mask;
- unsigned int dest_im_width, dest_im_height;
- unsigned int max_width, max_height;
- GC gc, mask_gc;
- TkRegion current_clip;
- ZnBBox *current_clip_box;
-
- dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
- item->item_bounding_box.orig.x);
- max_width = MAX(dest_im_width, (unsigned int) w);
- dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
- item->item_bounding_box.orig.y);
- max_height = MAX(dest_im_height, (unsigned int) h);
-
- mask = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height, 1);
-
- drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height,
- Tk_Depth(wi->win));
- mask_gc = XCreateGC(wi->dpy, mask, 0, NULL);
- gc = XCreateGC(wi->dpy, drw, 0, NULL);
- dest_mask = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
- XYPixmap, 0, NULL, dest_im_width, dest_im_height,
- 8, 0);
- dest_mask->data = ZnMalloc(dest_mask->bytes_per_line * dest_mask->height);
- memset(dest_mask->data, 0, dest_mask->bytes_per_line * dest_mask->height);
- XSetForeground(wi->dpy, mask_gc, 0);
- XFillRectangle(wi->dpy, mask, mask_gc, 0, 0, max_width, max_height);
- dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), Tk_Depth(wi->win),
- ZPixmap, 0, NULL, dest_im_width, dest_im_height,
- 32, 0);
- dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
- memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);
-
- pixmap = ZnImagePixmap(icon->image, wi->win);
- photo_region = ZnImageRegion(icon->image);
- clip = TkCreateRegion();
- /*
- * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
- * some internal TkPhoto functions.
- * This is a workaround using a rectangular region based
- * on the image size.
- */
- if (photo_region == NULL) {
- XRectangle rect;
- rect.x = rect.y = 0;
- rect.width = w;
- rect.height = h;
- TkUnionRectWithRegion(&rect, clip, clip);
- }
- else {
- ZnUnionRegion(clip, photo_region, clip);
- }
- XSetForeground(wi->dpy, mask_gc, 1);
- TkSetRegion(wi->dpy, mask_gc, clip);
- XFillRectangle(wi->dpy, mask, mask_gc, 0, 0, w, h);
-
- src_mask = XGetImage(wi->dpy, mask, 0, 0, w, h, 1, XYPixmap);
- src_im = XGetImage(wi->dpy, pixmap, 0, 0, w, h, ~0L, ZPixmap);
-
- box[0] = icon->dev[0];
- box[1] = icon->dev[1];
- box[2] = icon->dev[3];
- box[3] = icon->dev[2];
- for (i = 0; i < 4; i++) {
- box[i].x -= item->item_bounding_box.orig.x;
- box[i].y -= item->item_bounding_box.orig.y;
- box[i].x = ZnNearestInt(box[i].x);
- box[i].y = ZnNearestInt(box[i].y);
- }
-
- ZnMapImage(src_mask, dest_mask, box);
- ZnMapImage(src_im, dest_im, box);
-
- ZnCurrentClip(wi, &current_clip, &current_clip_box, NULL);
- TkSetRegion(wi->dpy, mask_gc, current_clip);
- XSetClipOrigin(wi->dpy, mask_gc,
- (int) -item->item_bounding_box.orig.x, (int) -item->item_bounding_box.orig.y);
- TkPutImage(NULL, 0,wi->dpy, mask, mask_gc, dest_mask,
- 0, 0, 0, 0, dest_im_width, dest_im_height);
- TkPutImage(NULL, 0, wi->dpy, drw, gc, dest_im,
- 0, 0, 0, 0, dest_im_width, dest_im_height);
-
- XSetClipMask(wi->dpy, gc, mask);
- XSetClipOrigin(wi->dpy, gc,
- (int) item->item_bounding_box.orig.x,
- (int) item->item_bounding_box.orig.y);
- XCopyArea(wi->dpy, drw, wi->draw_buffer, gc,
- 0, 0, dest_im_width, dest_im_height,
- (int) item->item_bounding_box.orig.x,
- (int) item->item_bounding_box.orig.y);
-
- XFreeGC(wi->dpy, gc);
- XFreeGC(wi->dpy, mask_gc);
- Tk_FreePixmap(wi->dpy, drw);
- Tk_FreePixmap(wi->dpy, mask);
- XDestroyImage(src_mask);
- XDestroyImage(dest_mask);
- XDestroyImage(src_im);
- XDestroyImage(dest_im);
- }
- }
- else {
- /*
- * If the current transform is a pure translation, it is
- * possible to optimize by directly drawing to the X back
- * buffer. Else, we draw in a temporary buffer, get
- * its content as an image, transform the image into another
- * one and use this last image as a mask to draw in the X
- * back buffer.
- */
- pixmap = ZnImagePixmap(icon->image, wi->win);
- if (ZnTransfoIsTranslation(item->wi->current_transfo)) {
- ZnCurrentClip(wi, NULL, &clip_box, &simple);
- if (simple) {
- ZnIntersectBBox(&box, clip_box, &inter);
- box = inter;
- }
- values.fill_style = FillStippled;
- values.stipple = pixmap;
- values.ts_x_origin = (int) icon->dev->x;
- values.ts_y_origin = (int) icon->dev->y;
- values.foreground = ZnGetGradientPixel(icon->color, 0.0);
- gc_mask |= GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground;
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- (int) box.orig.x,
- (int) box.orig.y,
- (unsigned int) (box.corner.x-box.orig.x),
- (unsigned int) (box.corner.y-box.orig.y));
- }
- else {
- ZnPoint box[4];
- int i;
- XImage *dest_im, *src_im;
- Pixmap drw;
- unsigned int dest_im_width, dest_im_height;
- unsigned int max_width, max_height;
- GC gc;
-
- dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
- item->item_bounding_box.orig.x);
- max_width = MAX(dest_im_width, (unsigned int) w);
- dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
- item->item_bounding_box.orig.y);
- max_height = MAX(dest_im_height, (unsigned int) h);
-
- drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height, 1);
- gc = XCreateGC(wi->dpy, drw, 0, NULL);
- XSetForeground(wi->dpy, gc, 0);
- XFillRectangle(wi->dpy, drw, gc, 0, 0, max_width, max_height);
- dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
- XYPixmap, 0, NULL, dest_im_width, dest_im_height,
- 8, 0);
- dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
- memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);
-
- values.fill_style = FillStippled;
- values.stipple = pixmap;
- values.ts_x_origin = 0;
- values.ts_y_origin = 0;
- values.foreground = 1;
- gc_mask |= GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground;
- XChangeGC(wi->dpy, gc, gc_mask, &values);
- XFillRectangle(wi->dpy, drw, gc, 0, 0, w, h);
-
- src_im = XGetImage(wi->dpy, drw, 0, 0, w, h, 1, XYPixmap);
-
- box[0] = icon->dev[0];
- box[1] = icon->dev[1];
- box[2] = icon->dev[3];
- box[3] = icon->dev[2];
- for (i = 0; i < 4; i++) {
- box[i].x -= item->item_bounding_box.orig.x;
- box[i].y -= item->item_bounding_box.orig.y;
- box[i].x = ZnNearestInt(box[i].x);
- box[i].y = ZnNearestInt(box[i].y);
- }
-
- ZnMapImage(src_im, dest_im, box);
-
- TkPutImage(NULL, 0,wi->dpy, drw, gc, dest_im,
- 0, 0, 0, 0, dest_im_width, dest_im_height);
-
- values.foreground = ZnGetGradientPixel(icon->color, 0.0);
- values.stipple = drw;
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- values.fill_style = FillStippled;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
- &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- (int) item->item_bounding_box.orig.x,
- (int) item->item_bounding_box.orig.y,
- (int) dest_im_width, (int) dest_im_height);
-
- XFreeGC(wi->dpy, gc);
- Tk_FreePixmap(wi->dpy, drw);
- XDestroyImage(src_im);
- XDestroyImage(dest_im);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
-
- if (icon->image != ZnUnspecifiedImage) {
- ZnRenderImage(wi, icon->image, icon->color, icon->dev,
- ZnImageIsBitmap(icon->image));
- }
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- IconItem icon = (IconItem) item;
- ZnWInfo *wi = item->wi;
- double dist;
- double off_dist = MAX(1, wi->pick_aperture+1);
- int x, y, width, height;
- ZnPoint p;
- ZnBBox bbox;
- ZnTransfo t;
-
- if (icon->image == ZnUnspecifiedImage) {
- return 1.0e40;
- }
-
- ZnTransfoInvert(wi->current_transfo, &t);
- ZnTransformPoint(&t, ps->point, &p);
- ZnTransformPoint(&t, &icon->dev[0], &bbox.orig);
- ZnSizeOfImage(icon->image, &width, &height);
- bbox.corner.x = bbox.orig.x + width;
- bbox.corner.y = bbox.orig.y + height;
- dist = ZnRectangleToPointDist(&bbox, &p);
- x = (int) (p.x - bbox.orig.x);
- y = (int) (p.y - bbox.orig.y);
- /*printf("dist: %g\n", dist);*/
-
- /*
- * If inside the icon rectangle, try to see if the point
- * is actually on the image or not. If it lies in an
- * area that is between pick_aperture+1 around the external
- * rectangle and the actual shape, the distance will be reported
- * as pick_aperture+1. Inside the actual shape it will be
- * reported as 0. This is a kludge, there is currently
- * no means to compute the real distance in the icon's
- * vicinity.
- */
- if (dist <= 0) {
- dist = 0.0;
- if (icon->image != ZnUnspecifiedImage) {
- if (ZnPointInImage(icon->image, x, y)) {
- /*
- * The point is actually on the image shape.
- */
- return dist;
- }
- else {
- /*
- * The point is not on the shape but still
- * inside the image's bounding box.
- */
- return off_dist;
- }
- }
- else {
- return dist;
- }
- }
- else if (dist < off_dist) {
- dist = off_dist;
- }
-
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- IconItem icon = (IconItem) item;
- int w, h, result;
- ZnPoint origin;
- char path[500];
-
- if (prepass || (icon->image == ZnUnspecifiedImage)) {
- return TCL_OK;
- }
-
- ZnSizeOfImage(icon->image, &w, &h);
-
- ComputeTransfoAndOrigin(item, &origin);
-
- sprintf(path, "/InitialTransform load setmatrix\n"
- "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
- "1 -1 scale\n"
- "%.15g %.15g translate\n",
- wi->current_transfo->_[0][0], wi->current_transfo->_[0][1],
- wi->current_transfo->_[1][0], wi->current_transfo->_[1][1],
- wi->current_transfo->_[2][0], wi->current_transfo->_[2][1],
- origin.x, origin.y - h);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- if (ZnImageIsBitmap(icon->image)) {
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(icon->color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- result = ZnPostscriptBitmap(wi->interp, wi->win, wi->ps_info,
- icon->image, 0, 0, w, h);
- }
- else {
- result = Tk_PostscriptImage(ZnImageTkImage(icon->image), wi->interp, wi->win,
- wi->ps_info, 0, 0, w, h, prepass);
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- IconItem icon = (IconItem) item;
-
- if (icon->image == ZnUnspecifiedImage) {
- *p = *icon->dev;
- }
- else {
- ZnPoint q[4];
- q[0] = icon->dev[0];
- q[1] = icon->dev[1];
- q[2] = icon->dev[3];
- q[3] = icon->dev[2];
- ZnRectOrigin2Anchor(q, anchor, p);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- IconItem icon = (IconItem) item;
- ZnPoint *points;
-
- ZnListAssertSize(ZnWorkPoints, 4);
- points = ZnListArray(ZnWorkPoints);
- points[0] = icon->dev[0];
- points[1] = icon->dev[1];
- points[2] = icon->dev[3];
- points[3] = icon->dev[2];
- ZnTriStrip1(tristrip, points, 4, False);
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item origin. This doesn't take care of
- * the possible attachment. The change will be effective at the
- * end of the attachment.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- IconItem icon = (IconItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " icons can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on icons", NULL);
- return TCL_ERROR;
- }
- icon->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &icon->pos;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct ICON_ITEM_CLASS = {
- "icon",
- sizeof(IconItemStruct),
- icon_attrs,
- 0, /* num_parts */
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- Tk_Offset(IconItemStruct, pos),
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- NULL, /* GetContours */
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnIcon = (ZnItemClassId) &ICON_ITEM_CLASS;
diff --git a/generic/Image.c b/generic/Image.c
deleted file mode 100644
index 723adcb..0000000
--- a/generic/Image.c
+++ /dev/null
@@ -1,1695 +0,0 @@
-/*
- * Image.c -- Image support routines.
- *
- * Authors : Patrick LECOANET
- * Creation date : Wed Dec 8 11:04:44 1999
- */
-
-/*
- * Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "tkZinc.h"
-#include "Image.h"
-#include "WidgetInfo.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "perfos.h"
-
-#include <memory.h>
-#include <ctype.h>
-#ifdef GL
-#include <stdlib.h>
-#endif
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-static int images_inited = 0;
-static Tcl_HashTable images;
-#ifdef GL
-static Tcl_HashTable font_textures;
-#endif
-
-typedef struct _ClientStruct {
- void (*inv_proc)(void *cd);
- void *client_data;
- int refcount;
-} ClientStruct;
-
-typedef struct _ImageStruct {
- union {
- Pixmap pixmap;
-#ifdef GL
- GLuint texobj;
-#endif
- } i;
- Display *dpy;
- Screen *screen;
- struct _ImageBits *bits;
-
- /* Bookkeeping */
-
- ZnBool for_gl;
- int refcount;
- ZnList clients;
- struct _ImageStruct *next;
-} ImageStruct, *Image;
-
-
-typedef struct _ImageBits {
- unsigned char *bpixels; /* Needed for bitmaps. Set to NULL if the image
- * is not a bitmap. */
- int rowstride;
-#ifdef GL
- ZnReal t; /* Texture parameters for the image. */
- ZnReal s;
- int t_width; /* Texture size used for this image. */
- int t_height;
- unsigned char *t_bits; /* Can be NULL if texture is not used (no GL
- * rendering active on this image). */
-#endif
-
- /* Bookeeping */
- Display *dpy; /* The tkimage below comes from this display. */
- Tcl_Interp *interp; /* The interp that created the tkimage below. */
- Tk_Image tkimage; /* Keep this handle to be informed of changes */
- Tk_PhotoHandle tkphoto;
- TkRegion valid_region;
- int width;
- int height;
- int depth;
- Tcl_HashEntry *hash; /* From this it is easy to get the image/bitmap
- * name. */
- Image images; /* Linked list of widget/display dependant
- * specializations of this image. If NULL, the
- * image has no specialization and can be freed. */
-} ImageBits;
-
-
-char *ZnNameOfImage(ZnImage image);
-
-#ifdef GL
-
-static int
-To2Power(int a)
-{
- int result = 1;
-
- while (result < a) {
- result *= 2;
- }
- return result;
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * ZnGetImage --
- *
- **********************************************************************************
- */
-static void
-InvalidateImage(ClientData client_data,
- int x,
- int y,
- int width,
- int height,
- int image_width,
- int image_height)
-{
- ImageBits *bits = (ImageBits *) client_data;
- Image this;
- int num_cs, count, i;
- ClientStruct *cs;
- char *image_name;
-
- /* printf("Invalidation, bits: %d, %d %d %d %d %d %d\n",
- client_data, x, y, width, height, image_width, image_height);*/
- if (ZnImageIsBitmap(bits->images)) {
- /* This is a bitmap nothing to update
- * (This should not happen) */
- return;
- }
-
-#ifdef GL
- if (bits->t_bits) {
- ZnFree(bits->t_bits);
- bits->t_bits = NULL;
- }
-#endif
- if (bits->valid_region) {
- TkDestroyRegion(bits->valid_region);
- bits->valid_region = NULL;
- }
-
- bits->width = image_width;
- bits->height = image_height;
- image_name = ZnNameOfImage(bits->images);
-
- /*
- * The photo pointer must be updated. It changes when creating an new image with
- * the same name as an old. The image is first deleted then re-instantiated.
- * As a side effect we also rely on it for telling if an image is a photo.
- */
- bits->tkphoto = Tk_FindPhoto(bits->interp, image_name);
-
- count = 0;
- this = bits->images;
- while (this) {
-#ifdef GL
- if (this->for_gl) {
- if (this->i.texobj) {
- ZnGLContextEntry *ce;
- ce = ZnGLMakeCurrent(this->dpy, 0);
- glDeleteTextures(1, &this->i.texobj);
- ZnGLReleaseContext(ce);
- this->i.texobj = 0;
- }
- }
- else {
-#endif
- if (this->i.pixmap != None) {
- Tk_FreePixmap(this->dpy, this->i.pixmap);
- this->i.pixmap = None;
- }
-#ifdef GL
- }
-#endif
-
- num_cs = ZnListSize(this->clients);
- cs = ZnListArray(this->clients);
- for (i = 0; i < num_cs; i++, cs++) {
- if (cs->inv_proc) {
- (*cs->inv_proc)(cs->client_data);
- }
- }
- count += num_cs;
- this = this->next;
- }
- /*printf("Invalidate on image %s with %d clients\n",
- Tcl_GetHashKey(&images, bits->hash), count);*/
-}
-
-ZnImage
-ZnGetImage(ZnWInfo *wi,
- Tk_Uid image_name,
- void (*inv_proc)(void *cd),
- void *client_data)
-{
- Tcl_HashEntry *entry;
- int new, num_cs, i;
- ImageBits *bits;
- ZnBool for_gl = wi->render>0;
- Image image;
- Tk_ImageType *type;
- ClientStruct cs, *cs_ptr;
-
- /*printf("ZnGetImage: %s\n", image_name);*/
- if (!images_inited) {
- Tcl_InitHashTable(&images, TCL_STRING_KEYS);
- images_inited = 1;
- }
- image_name = Tk_GetUid(image_name);
- entry = Tcl_FindHashEntry(&images, image_name);
- if (entry != NULL) {
- /*printf("Image \"%s\" is in cache\n", image_name);*/
- bits = (ImageBits *) Tcl_GetHashValue(entry);
- }
- else {
- /*printf("New image \"%s\"\n", image_name);*/
- if (strcmp(image_name, "") == 0) {
- return ZnUnspecifiedImage;
- }
-
- bits = ZnMalloc(sizeof(ImageBits));
-#ifdef GL
- bits->t_bits = NULL;
-#endif
- bits->images = NULL;
- bits->bpixels = NULL;
- bits->valid_region = NULL;
- bits->tkimage = NULL;
- bits->tkphoto = NULL;
- bits->interp = wi->interp;
- bits->dpy = wi->dpy;
-
- if (!Tk_GetImageMasterData(wi->interp, image_name, &type)) {
- /*
- * This doesn't seem to be a Tk image, try to load
- * a Tk bitmap.
- */
- Pixmap pmap;
- XImage *mask;
- int x, y;
- unsigned char *line;
-
- pmap = Tk_GetBitmap(wi->interp, wi->win, image_name);
- if (pmap == None) {
- ZnWarning("unknown bitmap/image \"");
- goto im_error;
- }
-
- Tk_SizeOfBitmap(wi->dpy, pmap, &bits->width, &bits->height);
- mask = XGetImage(wi->dpy, pmap, 0, 0, (unsigned int) bits->width,
- (unsigned int) bits->height, 1L, XYPixmap);
- bits->depth = 1;
- bits->rowstride = mask->bytes_per_line;
- bits->bpixels = ZnMalloc((unsigned int) (bits->height * bits->rowstride));
- memset(bits->bpixels, 0, (unsigned int) (bits->height * bits->rowstride));
- line = bits->bpixels;
- for (y = 0; y < bits->height; y++) {
- for (x = 0; x < bits->width; x++) {
- if (XGetPixel(mask, x, y)) {
- line[x >> 3] |= 0x80 >> (x & 7);
- }
- }
- line += bits->rowstride;
- }
- XDestroyImage(mask);
- Tk_FreeBitmap(wi->dpy, pmap);
- }
-
- else if (strcmp(type->name, "photo") == 0) {
- /* Processing will yield an image photo */
- bits->tkphoto = Tk_FindPhoto(wi->interp, image_name);
- Tk_PhotoGetSize(bits->tkphoto, &bits->width, &bits->height);
- if ((bits->width == 0) || (bits->height == 0)) {
- ZnWarning("bogus photo image \"");
- goto im_error;
- }
- bits->depth = Tk_Depth(wi->win);
- bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name,
- InvalidateImage, (ClientData) bits);
- }
- else { /* Other image types */
- bits->depth = Tk_Depth(wi->win);
- bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name,
- InvalidateImage, (ClientData) bits);
- Tk_SizeOfImage(bits->tkimage, &bits->width, &bits->height);
- if ((bits->width == 0) || (bits->height == 0)) {
- ZnWarning("bogus ");
- ZnWarning(type->name);
- ZnWarning(" image \"");
- im_error:
- ZnWarning(image_name);
- ZnWarning("\"\n");
- ZnFree(bits);
- return ZnUnspecifiedImage;
- }
- }
-
- entry = Tcl_CreateHashEntry(&images, image_name, &new);
- bits->hash = entry;
- Tcl_SetHashValue(entry, (ClientData) bits);
- }
-
- /*
- * Try to find an image instance that fits this widget/display.
- */
- for (image = bits->images; image != NULL; image = image->next) {
- if (image->for_gl == for_gl) {
- if ((for_gl && (image->dpy == wi->dpy)) ||
- (!for_gl && (image->screen == wi->screen))) {
- if (!ZnImageIsBitmap(image)) {
- cs_ptr = ZnListArray(image->clients);
- num_cs = ZnListSize(image->clients);
- for (i = 0; i < num_cs; i++, cs_ptr++) {
- if ((cs_ptr->inv_proc == inv_proc) &&
- (cs_ptr->client_data == client_data)) {
- cs_ptr->refcount++;
- return image;
- }
- }
- /* Add a new client reference to call back.
- */
- cs.inv_proc = inv_proc;
- cs.client_data = client_data;
- cs.refcount = 1;
- ZnListAdd(image->clients, &cs, ZnListTail);
- return image;
- }
- image->refcount++;
- return image;
- }
- }
- }
-
- /*
- * Create a new instance for this case.
- */
- /*printf("new instance for \"%s\"\n", image_name);*/
- image = ZnMalloc(sizeof(ImageStruct));
- image->bits = bits;
- image->refcount = 0;
- image->for_gl = for_gl;
- image->dpy = wi->dpy;
- image->screen = wi->screen;
-
- if (!ZnImageIsBitmap(image)) {
- image->clients = ZnListNew(1, sizeof(ClientStruct));
- cs.inv_proc = inv_proc;
- cs.client_data = client_data;
- cs.refcount = 1;
- ZnListAdd(image->clients, &cs, ZnListTail);
- }
- else {
- image->refcount++;
- }
-
- /* Init the real resource and let the client load it
- * on demand */
- if (image->for_gl) {
-#ifdef GL
- image->i.texobj = 0;
-#endif
- }
- else {
- image->i.pixmap = None;
- /* image->i.pixmap = Tk_GetBitmap(wi->interp, wi->win, image_name);
- printf("pmap: %d\n", image->i.pixmap);*/
- }
- image->next = bits->images;
- bits->images = image;
-
- return image;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetImageByValue --
- *
- **********************************************************************************
- */
-ZnImage
-ZnGetImageByValue(ZnImage image,
- void (*inv_proc)(void *cd),
- void *client_data)
-{
- Image this = (Image) image;
- ClientStruct cs, *cs_ptr;
- int i, num_cs;
-
- /*printf("ZnGetImageByValue: %s\n", ZnNameOfImage(image));*/
- if (!ZnImageIsBitmap(image)) {
- cs_ptr = ZnListArray(this->clients);
- num_cs = ZnListSize(this->clients);
- for (i = 0; i < num_cs; i++, cs_ptr++) {
- if ((cs_ptr->inv_proc == inv_proc) &&
- (cs_ptr->client_data == client_data)) {
- cs_ptr->refcount++;
- return image;
- }
- }
- cs.inv_proc = inv_proc;
- cs.client_data = client_data;
- cs.refcount = 1;
- ZnListAdd(this->clients, &cs, ZnListTail);
- }
- else {
- this->refcount++;
- }
-
- return image;
-}
-
-/*
- **********************************************************************************
- *
- * ZnImageIsBitmap --
- *
- **********************************************************************************
- */
-ZnBool
-ZnImageIsBitmap(ZnImage image)
-{
- return (((Image) image)->bits->bpixels != NULL);
-}
-
-/*
- **********************************************************************************
- *
- * ZnFreeImage --
- *
- **********************************************************************************
- */
-void
-ZnFreeImage(ZnImage image,
- void (*inv_proc)(void *cd),
- void *client_data)
-{
- Image prev, scan, this = ((Image) image);
- ImageBits *bits = this->bits;
- ClientStruct *cs_ptr;
- int i, num_cs, rm_image;
-
- /*printf("ZnFreeImage: %s\n", ZnNameOfImage(image));*/
- /*
- * Search the instance in the list.
- */
- for (prev=NULL, scan=bits->images; (scan!=NULL)&&(scan!=this);
- prev=scan, scan=scan->next);
- if (scan != this) {
- return; /* Not found ? */
- }
-
- if (!ZnImageIsBitmap(image)) {
- cs_ptr = ZnListArray(this->clients);
- num_cs = ZnListSize(this->clients);
- for (i = 0; i < num_cs; i++, cs_ptr++) {
- if ((cs_ptr->inv_proc == inv_proc) &&
- (cs_ptr->client_data == client_data)) {
- cs_ptr->refcount--;
- if (cs_ptr->refcount == 0) {
- ZnListDelete(this->clients, i);
- }
- break;
- }
- }
- rm_image = ZnListSize(this->clients)==0;
- }
- else {
- this->refcount--;
- rm_image = this->refcount==0;
- }
-
- if (!rm_image) {
- return;
- }
-
- /*
- * Unlink the deleted image instance.
- */
- if (prev == NULL) {
- bits->images = this->next;
- }
- else {
- prev->next = this->next;
- }
- if (this->for_gl) {
-#ifdef GL
- if (this->i.texobj) {
- ZnGLContextEntry *ce;
- ce = ZnGLMakeCurrent(this->dpy, 0);
- /* printf("%d Liberation de la texture %d pour l'image %s\n",
- wi, this->i.texobj, ZnNameOfImage(image));*/
- glDeleteTextures(1, &this->i.texobj);
- this->i.texobj = 0;
- ZnGLReleaseContext(ce);
- }
-#endif
- }
- else if (bits->tkimage) {
- /*
- * This is an image, we need to free the instances.
- */
- if (this->i.pixmap != None) {
- Tk_FreePixmap(this->dpy, this->i.pixmap);
- }
- }
- else {
- /*
- * This is a bitmap ask Tk to free the resource.
- */
- if (this->i.pixmap != None) {
- Tk_FreeBitmap(this->dpy, this->i.pixmap);
- }
- }
- ZnFree(this);
-
- /*
- * No clients for this image, it can be freed.
- */
- if (bits->images == NULL) {
- /*printf("destruction complète de l'image %s\n", ZnNameOfImage(this));*/
-#ifdef GL
- if (bits->t_bits) {
- ZnFree(bits->t_bits);
- }
-#endif
- if (bits->bpixels) {
- ZnFree(bits->bpixels);
- }
- if (bits->tkimage) {
- Tk_FreeImage(bits->tkimage);
- }
- if (bits->valid_region) {
- TkDestroyRegion(bits->valid_region);
- }
- Tcl_DeleteHashEntry(bits->hash);
- ZnFree(bits);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnNameOfImage --
- *
- **********************************************************************************
- */
-char *
-ZnNameOfImage(ZnImage image)
-{
- return Tcl_GetHashKey(&images, ((Image) image)->bits->hash);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnSizeOfImage --
- *
- **********************************************************************************
- */
-void
-ZnSizeOfImage(ZnImage image,
- int *width,
- int *height)
-{
- Image this = (Image) image;
-
- *width = this->bits->width;
- *height = this->bits->height;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnImagePixmap --
- *
- **********************************************************************************
- */
-Pixmap
-ZnImagePixmap(ZnImage image,
- Tk_Window win)
-{
- Image this = (Image) image;
- ImageBits *bits = this->bits;
-
- /*printf("ZnImagePixmap: %s\n", ZnNameOfImage(image));*/
- if (this->for_gl) {
- fprintf(stderr,
- "Bogus use of an image, it was created for GL and used in an X11 context\n");
- return None;
- }
-
- if (this->i.pixmap == None) {
- if (ZnImageIsBitmap(image)) {
- this->i.pixmap = Tk_GetBitmap(bits->interp, win, Tk_GetUid(ZnNameOfImage(image)));
- }
- else {
- Tk_Image tkimage;
-
- /*
- * If the original image was created on the same display
- * as the required display, we can get the pixmap from it.
- * On the other hand we need first to obtain an image
- * instance on the right display.
- */
- if (bits->dpy == this->dpy) {
- tkimage = bits->tkimage;
- }
- else {
- /* Create a temporary tkimage to draw the pixmap. */
- tkimage = Tk_GetImage(bits->interp, win, ZnNameOfImage(image), NULL, NULL);
- }
-
- this->i.pixmap = Tk_GetPixmap(this->dpy, Tk_WindowId(win),
- bits->width, bits->height, bits->depth);
- Tk_RedrawImage(tkimage, 0, 0, bits->width, bits->height, this->i.pixmap, 0, 0);
-
- if (tkimage != bits->tkimage) {
- Tk_FreeImage(tkimage);
- }
- }
- }
-
- return this->i.pixmap;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPointInImage --
- *
- * Return whether the given point is inside the image.
- *
- **********************************************************************************
- */
-ZnBool
-ZnPointInImage(ZnImage image,
- int x,
- int y)
-{
- if (ZnImageIsBitmap(image)) {
- ImageBits *bits = ((Image) image)->bits;
- if ((x < 0) || (y < 0) ||
- (x >= bits->width) || (y >= bits->height)) {
- return False;
- }
- return ZnGetBitmapPixel(bits->bpixels, bits->rowstride, x, y);
- }
- else {
- return ZnPointInRegion(ZnImageRegion(image), x, y);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnImageRegion --
- *
- * Only defined for Tk images (including Tk images defined from bitmaps).
- *
- **********************************************************************************
- */
-static void
-BuildImageRegion(Display *dpy,
- ImageBits *bits)
-{
- Pixmap pmap;
- int x, y, end;
- GC gc;
- XImage *im1, *im2;
- XRectangle rect;
-
- /*printf("BuildImageRegion: %s\n", ZnNameOfImage(bits->images));*/
- pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy), bits->width, bits->height, bits->depth);
- gc = XCreateGC(dpy, pmap, 0, NULL);
- XSetForeground(dpy, gc, 0);
- XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height);
- Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
- im1 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
-
- XSetForeground(dpy, gc, 1);
- XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height);
- Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
- im2 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
- Tk_FreePixmap(dpy, pmap);
- XFreeGC(dpy, gc);
-
- bits->valid_region = TkCreateRegion();
-
- for (y = 0; y < bits->height; y++) {
- x = 0;
- while (x < bits->width) {
- while ((x < bits->width) &&
- (XGetPixel(im1, x, y) != XGetPixel(im2, x, y))) {
- /* Search the first non-transparent pixel */
- x++;
- }
- end = x;
- while ((end < bits->width) &&
- (XGetPixel(im1, end, y) == XGetPixel(im2, end, y))) {
- /* Search the first transparent pixel */
- end++;
- }
- if (end > x) {
- rect.x = x;
- rect.y = y;
- rect.width = end - x;
- rect.height = 1;
- TkUnionRectWithRegion(&rect, bits->valid_region, bits->valid_region);
- }
- x = end;
- }
- }
-
- XDestroyImage(im1);
- XDestroyImage(im2);
-}
-
-TkRegion
-ZnImageRegion(ZnImage image)
-{
- if (ZnImageIsBitmap(image)) {
- return NULL;
- }
- else {
- Image this = (Image) image;
- ImageBits *bits = this->bits;
-#ifdef PTK
- if (!bits->valid_region) {
- BuildImageRegion(this->dpy, bits);
- }
- return bits->valid_region;
-#else
- if (bits->tkphoto) {
- return TkPhotoGetValidRegion(bits->tkphoto);
- }
- else {
- if (!bits->valid_region) {
- BuildImageRegion(this->dpy, bits);
- }
- return bits->valid_region;
- }
-#endif
- }
-}
-
-
-Tk_Image
-ZnImageTkImage(ZnImage image)
-{
- return ((Image) image)->bits->tkimage;
-}
-
-Tk_PhotoHandle
-ZnImageTkPhoto(ZnImage image)
-{
- return ((Image) image)->bits->tkphoto;
-}
-
-/*
- **********************************************************************************
- *
- * ZnImageTex --
- *
- **********************************************************************************
- */
-#ifdef GL
-/*
- * Working only for 16 bits displays with 5r6g5b mask,
- * and 24/32 bits displays. Byte ordering ok on Intel
- * plateform only.
- */
-static void
-From5r6g5b(unsigned char *data,
- int width,
- int height,
- int bytes_per_line,
- unsigned char *t_bits,
- int t_width,
- int t_height,
- TkRegion valid_region)
-{
- int x, y;
- int rowstride = t_width * 4;
- unsigned char *obptr;
- unsigned char *bptr, *bp2;
- unsigned char alpha;
- unsigned short temp;
-
- bptr = t_bits;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = data;
- for (x = 0; x < width; x++) {
- /*
- * Configure the alpha value.
- */
- alpha = ZnPointInRegion(valid_region, x, y) ? 255 : 0;
-
- /*
- * Dispatch the 3 color components.
- */
- temp = ((unsigned short *)obptr)[0];
- *bp2 = (temp >> 8) & 0xf8; /* r */
- bp2++;
- *bp2 = (temp >> 3) & 0xfc; /* v */
- bp2++;
- *bp2 = (temp << 3); /* b */
- bp2++;
- *bp2 = alpha;
- bp2++;
- obptr += 2;
- }
- for (x = width; x < t_width; x++) {
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- }
- bptr += rowstride;
- data += bytes_per_line;
- }
- for (y = height; y < t_height; y++) {
- memset(bptr, 0, rowstride);
- bptr += rowstride;
- }
-}
-
-static void
-From8r8g8b(unsigned char *data,
- int width,
- int height,
- int bytes_per_line,
- unsigned char *t_bits,
- int t_width,
- int t_height,
- TkRegion valid_region)
-{
- int x, y;
- int rowstride = t_width * 4;
- unsigned char *obptr;
- unsigned char *bptr, *bp2;
- unsigned char alpha;
-
- bptr = t_bits;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = data;
- for (x = 0; x < width; x++) {
- /*
- * Configure the alpha value.
- */
- alpha = ZnPointInRegion(valid_region, x, y) ? 255 : 0;
-
- /*
- * Dispatch the 3 color components.
- * Be careful the Red and Blue are swapped it works on an Intel
- * plateform but may need some more tests to be fully generic.
- */
- *bp2++ = obptr[2]; /* r */
- *bp2++ = obptr[1]; /* v */
- *bp2++ = obptr[0]; /* b */
- obptr += 4;
- *bp2++ = alpha;
- }
- for (x = width; x < t_width; x++) {
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- *bp2 = 0;
- bp2++;
- }
- bptr += rowstride;
- data += bytes_per_line;
- }
- for (y = height; y < t_height; y++) {
- memset(bptr, 0, rowstride);
- bptr += rowstride;
- }
-}
-
-static void
-GatherImageTexels(Display *dpy,
- ImageBits *bits)
-{
- Pixmap pmap;
- XImage *im;
- TkRegion valid_region;
- int t_size;
-
- /*printf("GatherImageTexels: %s\n", ZnNameOfImage(bits->images));*/
- valid_region = ZnImageRegion(bits->images);
-
- t_size = bits->t_width * 4 * bits->t_height;
- bits->t_bits = ZnMalloc(t_size);
-
- pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy),
- bits->width, bits->height, bits->depth);
- Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
- im = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
- Tk_FreePixmap(dpy, pmap);
-
- if (bits->depth == 16) {
- From5r6g5b(im->data, bits->width, bits->height, im->bytes_per_line,
- bits->t_bits, bits->t_width, bits->t_height, valid_region);
- }
- else if ((bits->depth == 24) || (bits->depth == 32)) {
- From8r8g8b(im->data, bits->width, bits->height, im->bytes_per_line,
- bits->t_bits, bits->t_width, bits->t_height, valid_region);
- }
-
- XDestroyImage(im);
-}
-
-GLuint
-ZnImageTex(ZnImage image,
- ZnReal *t,
- ZnReal *s)
-{
- Image this = (Image) image;
- ImageBits *bits = this->bits;
- ZnBool is_bmap = ZnImageIsBitmap(image);
- unsigned int t_size, width, height;
-
- if (!this->for_gl) {
- fprintf(stderr, "Bogus use of an image, it was created for X11 and used in a GL context\n");
- return 0;
- }
- ZnSizeOfImage(image, &width, &height);
- if (!bits->t_bits) {
- /*printf("chargement texture pour image %s\n", ZnNameOfImage(this));*/
- bits->t_width = To2Power((int) width);
- bits->t_height = To2Power((int) height);
- bits->s = width / (ZnReal) bits->t_width;
- bits->t = height / (ZnReal) bits->t_height;
-
- /*
- * This is a bitmap: use the pixels stored in bpixels.
- */
- if (is_bmap) {
- unsigned int i, j;
- unsigned char *ostart, *dstart, *d, *o;
-
- t_size = bits->t_width * bits->t_height;
- bits->t_bits = ZnMalloc(t_size);
- memset(bits->t_bits, 0, t_size);
- ostart = bits->bpixels;
- dstart = bits->t_bits;
- for (i = 0; i < height; i++) {
- d = dstart;
- o = ostart;
- for (j = 0; j < width; j++) {
- *d++ = ZnGetBitmapPixel(bits->bpixels, bits->rowstride, j, i) ? 255 : 0;
- }
- ostart += bits->rowstride;
- dstart += bits->t_width;
- }
- }
-
- /*
- * This is a photo: use the photo API, it is simple.
- */
- else if (bits->tkphoto) {
- unsigned int x, y, t_stride;
- unsigned char *obptr, *bptr, *bp2, *pixels;
- int green_off, blue_off, alpha_off;
- Tk_PhotoImageBlock block;
-
- t_stride = bits->t_width * 4;
- t_size = t_stride * bits->t_height;
- /*printf("t_width: %d(%d), t_height: %d(%d)\n", bits->t_width, width, bits->t_height, height);*/
- bits->t_bits = ZnMalloc(t_size);
- Tk_PhotoGetImage(bits->tkphoto, &block);
- green_off = block.offset[1] - block.offset[0];
- blue_off = block.offset[2] - block.offset[0];
-#ifdef PTK
- alpha_off = 3;
-#else
- alpha_off = block.offset[3] - block.offset[0];
-#endif
- /*printf("width %d, height: %d redoff: %d, greenoff: %d, blueoff: %d, alphaoff: %d\n",
- block.width, block.height, block.offset[0], green_off,
- blue_off, alpha_off);*/
- pixels = block.pixelPtr;
- bptr = bits->t_bits;
-
- for (y = 0; y < height; y++) {
- bp2 = bptr;
- obptr = pixels;
- for (x = 0; x < width; x++) {
- *bp2++ = obptr[0]; /* r */
- *bp2++ = obptr[green_off]; /* g */
- *bp2++ = obptr[blue_off]; /* b */
- *bp2++ = obptr[alpha_off]; /* alpha */
- obptr += block.pixelSize;
- }
- /*for (x = width; x < t_width; x++) {
- *bp2 = 0; bp2++;
- *bp2 = 0; bp2++;
- *bp2 = 0; bp2++;
- *bp2 = 0; bp2++;
- }*/
- bptr += t_stride;
- pixels += block.pitch;
- }
- /*for (y = height; y < t_height; y++) {
- memset(bptr, 0, t_stride);
- bptr += t_stride;
- }*/
- }
-
- /*
- * This is another image format (not a photo): try to
- * guess the pixels and the transparency (on or off)
- * from a locally drawn pixmap.
- */
- else {
- GatherImageTexels(bits->dpy, bits);
- }
- }
-
- if (!this->i.texobj) {
- glGenTextures(1, &this->i.texobj);
- /*printf("%d creation texture %d pour image %s\n",
- bits, this->i.texobj, ZnNameOfImage(this));*/
- glBindTexture(GL_TEXTURE_2D, this->i.texobj);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glGetError();
- if (is_bmap) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
- this->bits->t_width, this->bits->t_height,
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, this->bits->t_bits);
- }
- else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- this->bits->t_width, this->bits->t_height,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, this->bits->t_bits);
- }
- if (glGetError() != GL_NO_ERROR) {
- ZnWarning("Can't allocate the texture for image ");
- ZnWarning(ZnNameOfImage(image));
- ZnWarning("\n");
- }
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- *t = this->bits->t;
- *s = this->bits->s;
- return this->i.texobj;
-}
-#endif
-
-
-#ifdef GL
-
-#define MAX_GLYPHS_PER_GRAB 256
-
-typedef struct _TexFontInfo {
- struct _TexFont *txf;
- GLuint texobj;
- Display *dpy;
- unsigned int refcount;
- struct _TexFontInfo *next;
-} TexFontInfo;
-
-typedef struct {
- short width;
-} PerGlyphInfo, *PerGlyphInfoPtr;
-
-typedef struct _TexFont {
- TexFontInfo *tfi;
- Tk_Font tkfont;
- unsigned int tex_width;
- unsigned int tex_height;
- int ascent;
- int descent;
- unsigned int max_char_width;
- unsigned char *teximage;
- unsigned int num_glyphs;
- PerGlyphInfo *glyph;
- ZnTexGVI *tgvi;
- Tcl_HashEntry *hash;
-} TexFont;
-
-typedef struct _DeferredGLGlyphs {
- ZnWInfo *wi;
- TexFont *txf;
-} DeferredGLGlyphsStruct;
-
-ZnList DeferredGLGlyphs;
-
-
-#ifndef PTK_800
-#include "CharsetUTF8.h"
-#else
-#include "CharsetISO8859-15.h"
-#endif
-
-
-static void
-SuckGlyphsFromServer(ZnWInfo *wi,
- TexFont *txf)
-{
- Pixmap offscreen = 0;
- XImage *image = NULL;
- GC xgc = 0;
- unsigned int height, length, pixwidth;
- unsigned int i, j, use_max_width;
- unsigned int wgap=2, hgap=2, tex_width, tex_height;
- unsigned char *to;
- unsigned int x, y;
- unsigned int width=0, maxSpanLength;
- int grabList[MAX_GLYPHS_PER_GRAB];
- unsigned int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
- unsigned int numToGrab, glyph;
- ZnTexGVI *tgvip;
- Tk_FontMetrics fm;
- CONST unsigned char *cur, *next;
-#ifndef PTK_800
- Tcl_UniChar uni_ch;
-#endif
- ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
-
- /*printf("loading a font \n");*/
- Tk_GetFontMetrics(txf->tkfont, &fm);
-#ifndef PTK_800
- txf->num_glyphs = Tcl_NumUtfChars(ZnDefaultCharset, strlen(ZnDefaultCharset));
-#else
- txf->num_glyphs = strlen(ZnDefaultCharset);
-#endif
- txf->glyph = ZnMalloc(txf->num_glyphs * sizeof(PerGlyphInfo));
- if (!txf->glyph) {
- goto FreeAndReturn;
- }
- txf->tgvi = ZnMalloc(txf->num_glyphs * sizeof(ZnTexGVI));
- if (!txf->tgvi) {
- goto FreeAndReturn;
- }
-
- txf->ascent = fm.ascent;
- txf->descent = fm.descent;
- txf->max_char_width = 0;
- tex_width = tex_height = 0;
- use_max_width = 0;
- height = txf->ascent + txf->descent;
- tgvip = txf->tgvi;
-
- /*
- * Compute the max character size in the font. This may be
- * a bit heavy hammer style but it avoid guessing on characters
- * not available in the font.
- */
- cur = ZnDefaultCharset;
- i = 0;
- while (*cur) {
-#ifndef PTK_800
- next = Tcl_UtfNext(cur);
-#else
- next = cur + 1;
-#endif
- Tk_MeasureChars(txf->tkfont, cur, next - cur, 0, TK_AT_LEAST_ONE, &length);
- txf->glyph[i].width = length;
- txf->max_char_width = MAX(txf->max_char_width, length);
-
- if (tex_width + length + wgap > ce->max_tex_size) {
- tex_width = 0;
- use_max_width = 1;
- tex_height += height + hgap;
- if ((tex_height > ce->max_tex_size) || (length > ce->max_tex_size)) {
- goto FreeAndReturn;
- }
- }
-
- tgvip->v0x = 0;
- tgvip->v0y = txf->descent - height;
- tgvip->v1x = length;
- tgvip->v1y = txf->descent;
- tgvip->t0x = (GLfloat) tex_width;
- tgvip->t0y = (GLfloat) tex_height;
- tgvip->t1x = tgvip->t0x + length;
- tgvip->t1y = tgvip->t0y + height;
- tgvip->advance = (GLfloat) length;
-#ifndef PTK_800
- Tcl_UtfToUniChar(cur, &uni_ch);
- tgvip->code = uni_ch;
-#else
- tgvip->code = *cur;
-#endif
- tex_width += length + wgap;
-
- cur = next;
- i++;
- tgvip++;
- }
-
- if (use_max_width) {
- tex_width = ce->max_tex_size;
- }
- tex_height += height;
-
- /*
- * Round the texture size to the next power of two.
- */
- tex_height = To2Power(tex_height);
- tex_width = To2Power(tex_width);
- if ((tex_height > ce->max_tex_size) || (tex_width > ce->max_tex_size)) {
- fprintf(stderr, "Font doesn't fit into a texture\n");
- goto FreeAndReturn;
- }
- txf->tex_width = tex_width;
- txf->tex_height = tex_height;
- /*printf("(%s) Texture size is %d x %d for %d chars (max size: %d)\n",
- Tk_NameOfFont(font), txf->tex_width, txf->tex_height, txf->num_glyphs, ce->max_tex_size);*/
-
- /*
- * Now render the font bits into the texture.
- */
- txf->teximage = ZnMalloc(tex_height * tex_width);
- if (!txf->teximage) {
- goto FreeAndReturn;
- }
- memset(txf->teximage, 0, tex_height * tex_width);
-
- maxSpanLength = (txf->max_char_width + 7) / 8;
- /* Be careful determining the width of the pixmap; the X protocol allows
- pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
- max out at 2^15-1 (signed short size). If the width is too large, we
- need to limit the glyphs per grab. */
- if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
- glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
- }
- pixwidth = glyphsPerGrab * 8 * maxSpanLength;
- offscreen = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
- (int) pixwidth, (int) height, 1);
-
- xgc = XCreateGC(wi->dpy, offscreen, 0, NULL);
- XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
- XSetBackground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
- XFillRectangle(wi->dpy, offscreen, xgc, 0, 0, pixwidth, height);
- XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
- XSetFont(wi->dpy, xgc, Tk_FontId(txf->tkfont));
-
- numToGrab = 0;
- cur = ZnDefaultCharset;
- i = 0;
-
- while (*cur) {
-#ifndef PTK_800
- next = Tcl_UtfNext(cur);
-#else
- next = cur + 1;
-#endif
- if (txf->glyph[i].width != 0) {
- Tk_DrawChars(wi->dpy, offscreen, xgc, txf->tkfont, cur, next - cur,
- (int) (8*maxSpanLength*numToGrab), txf->ascent);
- grabList[numToGrab] = i;
- numToGrab++;
- }
-
- if ((numToGrab >= glyphsPerGrab) || (i == txf->num_glyphs - 1)) {
- image = XGetImage(wi->dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap);
-
- for (j = 0; j < numToGrab; j++) {
- glyph = grabList[j];
- width = txf->glyph[glyph].width;
- tgvip = &txf->tgvi[glyph];
- to = txf->teximage + (int) (tgvip->t0y * tex_width) + (int) tgvip->t0x;
- tgvip->t0x = tgvip->t0x / (GLfloat) tex_width;
- tgvip->t0y = tgvip->t0y / (GLfloat) tex_height;
- tgvip->t1x = tgvip->t1x / (GLfloat) tex_width;
- tgvip->t1y = tgvip->t1y / (GLfloat) tex_height;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++, to++) {
- /* XXX The algorithm used to suck across the font ensures that
- each glyph begins on a byte boundary. In theory this would
- make it convienent to copy the glyph into a byte oriented
- bitmap. We actually use the XGetPixel function to extract
- each pixel from the image which is not that efficient. We
- could either do tighter packing in the pixmap or more
- efficient extraction from the image. Oh well. */
- if (XGetPixel(image, (int) (j*maxSpanLength*8) + x, y) == BlackPixelOfScreen(wi->screen)) {
- *to = 255;
- }
- }
- to += tex_width - width;
- }
- }
- XDestroyImage(image);
- image = NULL;
- numToGrab = 0;
- /* do we need to clear the offscreen pixmap to get more? */
- if (i < txf->num_glyphs - 1) {
- XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
- XFillRectangle(wi->dpy, offscreen, xgc, 0, 0,
- 8 * maxSpanLength * glyphsPerGrab, height);
- XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
- }
- }
-
- cur = next;
- i++;
- }
-
- XFreeGC(wi->dpy, xgc);
- Tk_FreePixmap(wi->dpy, offscreen);
- return;
-
- FreeAndReturn:
- if (txf->glyph) {
- ZnFree(txf->glyph);
- txf->glyph = NULL;
- }
- if (txf->tgvi) {
- ZnFree(txf->tgvi);
- txf->tgvi = NULL;
- }
- if (txf->teximage) {
- ZnFree(txf->teximage);
- txf->teximage = NULL;
- }
- ZnWarning("Cannot load font texture for font ");
- ZnWarning(Tk_NameOfFont(txf->tkfont));
- ZnWarning("\n");
-}
-
-static void
-ZnNeedToGetGLGlyphs(ZnWInfo *wi,
- TexFont *txf)
-{
- DeferredGLGlyphsStruct dgg, *dggp;
- int i, num;
-
- if (!DeferredGLGlyphs) {
- DeferredGLGlyphs = ZnListNew(4, sizeof(DeferredGLGlyphsStruct));
- }
- dggp = ZnListArray(DeferredGLGlyphs);
- num = ZnListSize(DeferredGLGlyphs);
- for (i = 0; i < num; i++, dggp++) {
- if (dggp->txf == txf) {
- return;
- }
- }
-
- dgg.wi = wi;
- dgg.txf = txf;
- ZnListAdd(DeferredGLGlyphs, &dgg, ZnListTail);
- /*printf("adding a font to load\n");*/
-}
-
-void
-ZnGetDeferredGLGlyphs(void)
-{
- DeferredGLGlyphsStruct *dggp;
- int i, num = ZnListSize(DeferredGLGlyphs);
-
- if (!num) {
- return;
- }
- dggp = ZnListArray(DeferredGLGlyphs);
- for (i = 0; i < num; i++, dggp++) {
- SuckGlyphsFromServer(dggp->wi, dggp->txf);
- }
- ZnListEmpty(DeferredGLGlyphs);
-}
-
-static void
-ZnRemovedDeferredGLGlyph(TexFont *txf)
-{
- DeferredGLGlyphsStruct *dggp;
- int i, num;
-
- dggp = ZnListArray(DeferredGLGlyphs);
- num = ZnListSize(DeferredGLGlyphs);
- for (i = 0; i < num; i++, dggp++) {
- if (dggp->txf == txf) {
- ZnListDelete(DeferredGLGlyphs, i);
- return;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetTexFont --
- *
- **********************************************************************************
- */
-ZnTexFontInfo
-ZnGetTexFont(ZnWInfo *wi,
- Tk_Font font)
-{
- TexFont *txf;
- TexFontInfo *tfi;
- static int inited = 0;
- Tcl_HashEntry *entry;
- int new;
-
- if (!inited) {
- Tcl_InitHashTable(&font_textures, TCL_STRING_KEYS);
- inited = 1;
- }
-
- /* printf("family: %s, size: %d, weight: %d, slant: %d, underline: %d, overstrike: %d\n",
- tft->fa.family, tft->fa.size, tft->fa.weight, tft->fa.slant, tft->fa.underline,
- tft->fa.overstrike);
- */
- entry = Tcl_FindHashEntry(&font_textures, Tk_NameOfFont(font));
- if (entry != NULL) {
- /*printf("Found an already created font %s\n", Tk_NameOfFont(font));*/
- txf = (TexFont *) Tcl_GetHashValue(entry);
- }
- else {
- /*printf("Creating a new texture font for %s\n", Tk_NameOfFont(font));*/
- txf = ZnMalloc(sizeof(TexFont));
- if (txf == NULL) {
- return NULL;
- }
- txf->tfi = NULL;
- txf->tgvi = NULL;
- txf->glyph = NULL;
- txf->teximage = NULL;
-
- /* Get a local reference to the font, it will be deallocated
- * when no further references on this TexFont exist. */
- txf->tkfont = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(font));
-
- /*printf("Scheduling glyph loading for font %s\n", ZnNameOfTexFont(tfi));*/
- ZnNeedToGetGLGlyphs(wi, txf);
-
- entry = Tcl_CreateHashEntry(&font_textures, Tk_NameOfFont(font), &new);
- Tcl_SetHashValue(entry, (ClientData) txf);
- txf->hash = entry;
- }
-
- /*
- * Now locate the texture obj in the texture list for this widget.
- */
- for (tfi = txf->tfi; tfi != NULL; tfi = tfi->next) {
- if (tfi->dpy == wi->dpy) {
- tfi->refcount++;
- return tfi;
- }
- }
- /*
- * Not found allocate a new texture object.
- */
- tfi = ZnMalloc(sizeof(TexFontInfo));
- if (tfi == NULL) {
- return NULL;
- }
- tfi->refcount = 1;
- tfi->dpy = wi->dpy;
- tfi->txf = txf;
- tfi->texobj = 0;
- tfi->next = txf->tfi;
- txf->tfi = tfi;
-
- return tfi;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnNameOfTexFont --
- *
- **********************************************************************************
- */
-char const *
-ZnNameOfTexFont(ZnTexFontInfo tfi)
-{
- return Tk_NameOfFont(((TexFontInfo *) tfi)->txf->tkfont);
-}
-
-/*
- **********************************************************************************
- *
- * ZnTexFontTex --
- *
- **********************************************************************************
- */
-GLuint
-ZnTexFontTex(ZnTexFontInfo tfi)
-{
- TexFontInfo *this = (TexFontInfo *) tfi;
- TexFont *txf = this->txf;
-
- if (!txf->teximage) {
- return 0;
- }
- if (!this->texobj) {
- glGenTextures(1, &this->texobj);
- /*printf("%d creation texture %d pour la fonte %s\n",
- this->dpy, this->texobj, ZnNameOfTexFont(tfi));*/
- glBindTexture(GL_TEXTURE_2D, this->texobj);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glGetError();
- /*printf("Demande texture de %d x %d\n", txf->tex_width, txf->tex_height);*/
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, txf->tex_width,
- txf->tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
- txf->teximage);
- if (glGetError() != GL_NO_ERROR) {
- ZnWarning("Can't allocate the texture for font ");
- ZnWarning(ZnNameOfTexFont(tfi));
- ZnWarning("\n");
- }
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- /*printf("%d utilisation de la texture %d\n", this->wi, this->texobj);*/
- return this->texobj;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnFreeTexFont --
- *
- **********************************************************************************
- */
-void
-ZnFreeTexFont(ZnTexFontInfo tfi)
-{
- TexFontInfo *this = ((TexFontInfo *) tfi);
- TexFont *txf = this->txf;
- TexFontInfo *prev, *scan;
-
- for (prev=NULL, scan=this->txf->tfi; (scan!=NULL)&&(scan != this);
- prev=scan, scan=scan->next);
- if (scan != this) {
- return;
- }
-
- /*
- * Decrement tex font object refcount.
- */
- this->refcount--;
- if (this->refcount != 0) {
- return;
- }
-
- /*
- * Unlink the deleted tex font info.
- */
- if (prev == NULL) {
- txf->tfi = this->next;
- }
- else {
- prev->next = this->next;
- }
- if (this->texobj) {
- ZnGLContextEntry *ce;
- /*printf("%d Freeing texture %d from font %s\n",
- this->dpy, this->texobj, ZnNameOfTexFont(tfi));*/
- ce = ZnGLMakeCurrent(this->dpy, 0);
- if (ce) {
- glDeleteTextures(1, &this->texobj);
- ZnGLReleaseContext(ce);
- }
- }
- /*
- * Remove the font from the deferred load list
- */
- ZnRemovedDeferredGLGlyph(txf);
-
- /*
- * There is no more client for this font
- * deallocate the structures.
- */
- if (txf->tfi == NULL) {
- /*printf("%d Freeing txf for %s\n", this, ZnNameOfTexFont(tfi));*/
- Tk_FreeFont(txf->tkfont);
- ZnFree(txf->glyph);
- ZnFree(txf->tgvi);
- ZnFree(txf->teximage);
- Tcl_DeleteHashEntry(txf->hash);
- ZnFree(txf);
- }
-
- ZnFree(this);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetFontIndex --
- *
- **********************************************************************************
- */
-int
-ZnGetFontIndex(ZnTexFontInfo tfi,
- int c)
-{
- TexFont *txf;
- ZnTexGVI *tgvi;
- int code, min, max, mid;
-
- if (c < 127) {
- /*
- * It is possible to index the points below 127. Unicode
- * is the same as ascii down there.
- */
- return c - 32;
- }
-
- /*
- * Else, search by dichotomy in the remaining chars.
- */
- txf = ((TexFontInfo *) tfi)->txf;
- tgvi = txf->tgvi;
- if (!tgvi) {
- return -1;
- }
- min = 127 - 32;
- max = txf->num_glyphs;
- while (min < max) {
- mid = (min + max) >> 1;
- code = tgvi[mid].code;
- if (c == code) {
- return mid;
- }
- if (c < code) {
- max = mid;
- }
- else {
- min = mid + 1;
- }
- }
- //fprintf(stderr, "Tried to access unavailable texture font character %d (Unicode)\n", c);
- return -1;
-}
-
-/*
- **********************************************************************************
- *
- * ZnTexFontGVI --
- *
- **********************************************************************************
- */
-ZnTexGVI *
-ZnTexFontGVI(ZnTexFontInfo tfi,
- int c)
-{
- TexFont *txf = ((TexFontInfo *) tfi)->txf;
- ZnTexGVI *tgvi = NULL;
- int index;
-
- index = ZnGetFontIndex(tfi, c);
- if (index >= 0) {
- tgvi = &txf->tgvi[index];
- }
-
- return tgvi;
-}
-
-#endif
diff --git a/generic/Image.h b/generic/Image.h
deleted file mode 100644
index 426c0df..0000000
--- a/generic/Image.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Image.h -- Image support routines.
- *
- * Authors : Patrick LECOANET
- * Creation date : Wed Dec 8 11:04:44 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Image_h
-#define _Image_h
-
-#include "Types.h"
-
-struct _ZnWInfo;
-
-
-typedef void *ZnImage;
-
-#define ZnGetBitmapPixel(bits, stride, x, y)\
- (((bits)[(y)*(stride)+((x)>>3)]<<((x)&7))&0x80)
-
-ZnImage ZnGetImage(struct _ZnWInfo *wi, Tk_Uid image_name,
- void (*inv_proc)(void *cd), void *cd);
-ZnImage ZnGetImageByValue(ZnImage image, void (*inv_proc)(void *cd), void *cd);
-void ZnFreeImage(ZnImage image, void (*inv_proc)(void *cd), void *cd);
-char * ZnNameOfImage(ZnImage image);
-void ZnSizeOfImage(ZnImage image, int *width, int *height);
-Pixmap ZnImagePixmap(ZnImage image, Tk_Window win);
-ZnBool ZnImageIsBitmap(ZnImage image);
-TkRegion ZnImageRegion(ZnImage image);
-Tk_Image ZnImageTkImage(ZnImage image);
-Tk_PhotoHandle ZnImageTkPhoto(ZnImage image);
-ZnBool
-ZnPointInImage(ZnImage image, int x, int y);
-#ifdef GL
-GLuint ZnImageTex(ZnImage image, ZnReal *t, ZnReal *s);
-
-typedef struct _ZnTexGlyphVertexInfo {
- GLfloat t0x;
- GLfloat t0y;
- GLshort v0x;
- GLshort v0y;
- GLfloat t1x;
- GLfloat t1y;
- GLshort v1x;
- GLshort v1y;
- GLfloat advance;
- int code;
-} ZnTexGVI;
-
-
-typedef void *ZnTexFontInfo;
-
-ZnTexFontInfo ZnGetTexFont(struct _ZnWInfo *wi, Tk_Font font);
-void ZnFreeTexFont(ZnTexFontInfo tfi);
-ZnTexGVI *ZnTexFontGVI(ZnTexFontInfo tfi, int c);
-int ZnGetFontIndex(ZnTexFontInfo tfi, int c);
-GLuint ZnTexFontTex(ZnTexFontInfo tfi);
-void ZnGetDeferredGLGlyphs(void);
-#endif
-
-#endif /* _Image_h */
diff --git a/generic/Item.c b/generic/Item.c
deleted file mode 100644
index 8fe85f6..0000000
--- a/generic/Item.c
+++ /dev/null
@@ -1,2664 +0,0 @@
-/*
- * Item.c -- Implementation of items.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "Field.h"
-#include "Item.h"
-#include "Group.h"
-#include "WidgetInfo.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "MapInfo.h"
-#include "Image.h"
-#include "Color.h"
-#include "tkZinc.h"
-#ifdef ATC
-#include "OverlapMan.h"
-#endif
-
-#include <GL/glu.h>
-#include <limits.h> /* For INT_MAX */
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-static ZnList item_classes = NULL;
-static ZnList item_stack = NULL;
-
-
-/*
- * This array must be kept in sync with the
- * corresponding defines in Item.h.
- */
-static char *attribute_type_strings[] = {
- "",
- "boolean",
- "bitmap",
- "bitmaplist",
- "string",
- "font",
- "edgelist",
- "relief",
- "dimension",
- "priority",
- "alignment",
- "autoalignment",
- "lineend",
- "labelformat",
- "linestyle",
- "lineshape",
- "item",
- "angle",
- "integer",
- "unsignedint",
- "point",
- "anchor",
- "taglist",
- "mapinfo",
- "image",
- "leaderanchors",
- "joinstyle",
- "capstyle",
- "gradient",
- "gradientlist",
- "window",
- "alpha",
- "fillrule",
- "short",
- "unsignedshort"
- "char"
- "unsignedchar"
-};
-
-
-#ifndef PTK
-static int SetAttrFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *obj));
-
-/*
- * The structure below defines an object type that is used to cache the
- * result of looking up an attribute name. If an object has this type, then
- * its internalPtr1 field points to the attr_desc table in which it was looked up,
- * and the internalPtr2 field points to the entry that matched.
- */
-
-Tcl_ObjType ZnAttrObjType = {
- "attribute", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
- (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
- SetAttrFromAny /* setFromAnyProc */
-};
-#endif
-
-
-/*
- **********************************************************************************
- *
- * Forward functions
- *
- **********************************************************************************
- */
-static void Invalidate(ZnItem item, int reason);
-static Tcl_Obj *AttributeToObj(Tcl_Interp *interp, void *record, ZnAttrConfig *desc);
-
-
-
-/*
- **********************************************************************************
- *
- * ZnUpdateItemImage --
- *
- **********************************************************************************
- */
-void
-ZnUpdateItemImage(void *client_data)
-{
- ZnItem item = (ZnItem) client_data;
-
- /*printf("Invalidation of item %ld\n", item->id);*/
- Invalidate(item, ZN_CLFC_FLAG | ZN_COORDS_FLAG);
-}
-
-
-/*
- **********************************************************************************
- *
- * InitAttrDesc --
- *
- **********************************************************************************
- */
-static void
-InitAttrDesc(ZnAttrConfig *attr_desc)
-{
- if (!attr_desc) {
- return;
- }
-
- while (attr_desc->type != ZN_CONFIG_END) {
- attr_desc->uid = Tk_GetUid(attr_desc->name);
- attr_desc++;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetAttrFromAny --
- *
- * This procedure is called to convert a Tcl object to an attribute
- * descriptor. This is only possible if given a attr_desc table, so
- * this method always returns an error.
- *
- *----------------------------------------------------------------------
- */
-#ifndef PTK
-static int
-SetAttrFromAny(Tcl_Interp *interp,
- Tcl_Obj *obj)
-{
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "can't convert value to attribute except via GetAttrDesc",
- -1);
- return TCL_ERROR;
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * GetAttrDesc --
- *
- **********************************************************************************
- */
-static ZnAttrConfig *
-GetAttrDesc(Tcl_Interp *interp,
- Tcl_Obj *arg,
- ZnAttrConfig *desc_table)
-{
- Tk_Uid attr_uid;
- ZnAttrConfig *desc;
-
-#ifndef PTK
- if (arg->typePtr == &ZnAttrObjType) {
- if (arg->internalRep.twoPtrValue.ptr1 == (void *) desc_table) {
- return (ZnAttrConfig *) arg->internalRep.twoPtrValue.ptr2;
- }
- }
-#endif
-
- /*
- * Answer not cached, look it up.
- */
- attr_uid = Tk_GetUid(Tcl_GetString(arg));
- desc = desc_table;
-
- while (True) {
- if (desc->type == ZN_CONFIG_END) {
- Tcl_AppendResult(interp, "unknown attribute \"", attr_uid, "\"", NULL);
- return NULL;
- }
- else if (attr_uid == desc->uid) {
-#ifndef PTK
- if ((arg->typePtr != NULL) && (arg->typePtr->freeIntRepProc != NULL)) {
- arg->typePtr->freeIntRepProc(arg);
- }
- arg->internalRep.twoPtrValue.ptr1 = (void *) desc_table;
- arg->internalRep.twoPtrValue.ptr2 = (void *) desc;
- arg->typePtr = &ZnAttrObjType;
-#endif
- return desc;
- }
- else {
- desc++;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * AttributesInfo --
- *
- **********************************************************************************
- */
-int
-ZnAttributesInfo(Tcl_Interp *interp,
- void *record,
- ZnAttrConfig *desc_table,
- int argc,
- Tcl_Obj *CONST args[])
-{
- Tcl_Obj *l, *entries[5];
-
- if (argc == 1) {
- ZnAttrConfig *desc = GetAttrDesc(interp, args[0], desc_table);
- if (!desc) {
- return TCL_ERROR;
- }
- entries[0] = Tcl_NewStringObj(desc->name, -1);
- entries[1] = Tcl_NewStringObj(attribute_type_strings[desc->type], -1);
- entries[2] = Tcl_NewBooleanObj(desc->read_only ? 1 : 0);
- entries[3] = Tcl_NewStringObj("", -1);
- entries[4] = AttributeToObj(interp, record, desc);
- l = Tcl_NewListObj(5, entries);
- Tcl_SetObjResult(interp, l);
- }
- else {
- l = Tcl_NewObj();
- while (desc_table->type != ZN_CONFIG_END) {
- entries[0] = Tcl_NewStringObj(desc_table->name, -1);
- entries[1] = Tcl_NewStringObj(attribute_type_strings[desc_table->type], -1);
- entries[2] = Tcl_NewBooleanObj(desc_table->read_only ? 1 : 0);
- entries[3] = Tcl_NewStringObj("", -1);
- entries[4] = AttributeToObj(interp, record, desc_table);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(5, entries));
- desc_table++;
- }
- Tcl_SetObjResult(interp, l);
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnConfigureAttributes --
- *
- **********************************************************************************
- */
-int
-ZnConfigureAttributes(ZnWInfo *wi,
- ZnItem item,
- void *record,
- ZnAttrConfig *desc_table,
- int argc,
- Tcl_Obj *CONST args[],
- int *flags)
-{
- int i;
- ZnAttrConfig *desc;
- ZnPtr valp;
- char *str;
-
- for (i = 0; i < argc; i += 2) {
- desc = GetAttrDesc(wi->interp, args[i], desc_table);
- if (!desc) {
- return TCL_ERROR;
- }
- else if (desc->read_only) {
- Tcl_AppendResult(wi->interp, "attribute \"",
- Tcl_GetString(args[i]), "\" can only be read", NULL);
- return TCL_ERROR;
- }
-
- valp = ((char *) record) + desc->offset;
- /*printf("record <0x%X>, valp <0x%X>, offset %d\n", record, valp, desc->offset);*/
- switch (desc->type) {
- case ZN_CONFIG_GRADIENT:
- {
- ZnGradient *g;
- Tk_Uid new_name = Tk_GetUid(Tcl_GetString(args[i+1]));
- char *name = NULL;
- if (*((ZnGradient **) valp)) {
- name = ZnNameOfGradient(*((ZnGradient **) valp));
- }
- if (name != new_name) {
- g = ZnGetGradient(wi->interp, wi->win, new_name);
- if (!g) {
- Tcl_AppendResult(wi->interp,
- " gradient expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (*((ZnGradient **) valp)) {
- ZnFreeGradient(*((ZnGradient **) valp));
- }
- *((ZnGradient **) valp) = g;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_GRADIENT_LIST:
- {
- ZnList new_grad_list = NULL;
- ZnGradient **grads;
- unsigned int num_grads, j, k;
- Tcl_Obj **elems;
-
- if (Tcl_ListObjGetElements(wi->interp, args[i+1],
- &num_grads, &elems) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp,
- " gradient list expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (num_grads) {
- new_grad_list = ZnListNew(num_grads, sizeof(ZnGradient *));
- ZnListAssertSize(new_grad_list, num_grads);
- grads = ZnListArray(new_grad_list);
- for (j = 0; j < num_grads; j++) {
- str = Tcl_GetString(elems[j]);
- if (!*str) {
- if (j == 0) {
- goto grads_err;
- }
- grads[j] = grads[j-1];
- }
- else {
- grads[j] = ZnGetGradient(wi->interp, wi->win, str);
- }
- if (!grads[j]) {
- grads_err:
- Tcl_AppendResult(wi->interp, " invalid gradient \"", str,
- "\" in gradient list", NULL);
- for (k = 0; k < j; k++) {
- ZnFreeGradient(grads[k]);
- }
- ZnListFree(new_grad_list);
- return TCL_ERROR;
- }
- }
- }
- if (*((ZnList *) valp)) {
- num_grads = ZnListSize(*((ZnList *) valp));
- grads = ZnListArray(*((ZnList *) valp));
- for (j = 0; j < num_grads; j++) {
- if (grads[j]) {
- ZnFreeGradient(grads[j]);
- }
- }
- ZnListFree(*((ZnList *) valp));
- *((ZnList *) valp) = new_grad_list;
- *flags |= desc->flags;
- }
- else {
- if (new_grad_list) {
- *((ZnList *) valp) = new_grad_list;
- *flags |= desc->flags;
- }
- }
- break;
- }
- case ZN_CONFIG_BOOL:
- {
- int b;
- if (Tcl_GetBooleanFromObj(wi->interp, args[i+1], &b) != TCL_OK) {
- Tcl_AppendResult(wi->interp, " boolean expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (b ^ (ISSET(*((unsigned short *) valp), desc->bool_bit) != 0)) {
- ASSIGN(*((unsigned short *) valp), desc->bool_bit, b);
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_IMAGE:
- case ZN_CONFIG_BITMAP:
- {
- ZnImage image = ZnUnspecifiedImage;
- ZnBool is_bmap = True;
- char *name = "";
-
- if (*((ZnImage *) valp) != ZnUnspecifiedImage) {
- name = ZnNameOfImage(*((ZnImage *) valp));
- }
- str = Tcl_GetString(args[i+1]);
- if (strcmp(name, str) != 0) {
- if (strlen(str) != 0) {
- if (desc->type == ZN_CONFIG_IMAGE) {
- image = ZnGetImage(wi, str, ZnUpdateItemImage, record);
- if (image == ZnUnspecifiedImage) {
- Tcl_AppendResult(wi->interp, " image expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- }
- else {
- image = ZnGetImage(wi, str, NULL, NULL);
- if ((image == ZnUnspecifiedImage) ||
- (!(is_bmap = ZnImageIsBitmap(image)))) {
- if (!is_bmap) {
- ZnFreeImage(image, NULL, NULL);
- }
- Tcl_AppendResult(wi->interp, " bitmap expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- }
- }
- if (*((ZnImage *) valp) != ZnUnspecifiedImage) {
- ZnFreeImage(*((ZnImage *) valp), ZnUpdateItemImage, record);
- }
- *((ZnImage *) valp) = image;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_BITMAP_LIST:
- {
- ZnList new_pat_list = NULL;
- ZnImage *pats;
- unsigned int num_pats, j, k;
- Tcl_Obj **elems;
- ZnBool is_bmap = True;
-
- if (Tcl_ListObjGetElements(wi->interp, args[i+1],
- &num_pats, &elems) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp,
- " pattern list expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (num_pats) {
- new_pat_list = ZnListNew(num_pats, sizeof(Pixmap));
- ZnListAssertSize(new_pat_list, num_pats);
- pats = ZnListArray(new_pat_list);
- for (j = 0; j < num_pats; j++) {
- str = Tcl_GetString(elems[j]);
- if (strlen(str) != 0) {
- pats[j] = ZnGetImage(wi, str, NULL, NULL);
- if ((pats[j] == ZnUnspecifiedImage) ||
- !(is_bmap = ZnImageIsBitmap(pats[j]))) {
- if (!is_bmap) {
- ZnFreeImage(pats[j], NULL, NULL);
- }
- for (k = 0; k < j; k++) {
- ZnFreeImage(pats[k], NULL, NULL);
- }
- ZnListFree(new_pat_list);
- Tcl_AppendResult(wi->interp, " unknown pattern \"", str,
- "\" in pattern list", NULL);
- return TCL_ERROR;
- }
- }
- else {
- pats[j] = ZnUnspecifiedImage;
- }
- }
- }
- if (*((ZnList *) valp)) {
- num_pats = ZnListSize(*((ZnList *) valp));
- pats = ZnListArray(*((ZnList *) valp));
- for (j = 0; j < num_pats; j++) {
- if (pats[j] != ZnUnspecifiedImage) {
- ZnFreeImage(pats[j], NULL, NULL);
- }
- }
- ZnListFree(*((ZnList *) valp));
- *((ZnList *) valp) = new_pat_list;
- *flags |= desc->flags;
- }
- else {
- if (new_pat_list) {
- *((ZnList *) valp) = new_pat_list;
- *flags |= desc->flags;
- }
- }
- break;
- }
- case ZN_CONFIG_TAG_LIST:
- {
- int num_tags, j;
- Tcl_Obj **elems;
-
- if (Tcl_ListObjGetElements(wi->interp, args[i+1],
- &num_tags, &elems) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp,
- " tag list expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (*((ZnList *) valp)) {
- ZnITEM.FreeTags(item);
- *flags |= desc->flags;
- }
- if (num_tags) {
- for (j = 0; j < num_tags; j++) {
- ZnITEM.AddTag(item, Tk_GetUid(Tcl_GetString(elems[j])));
- }
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_STRING:
- case ZN_CONFIG_MAP_INFO:
- {
- char *text = NULL;
- str = Tcl_GetString(args[i+1]);
- if (!*((char **) valp) || strcmp(str, *((char **) valp)) != 0) {
- if (strlen(str)) {
- text = (char *) ZnMalloc(strlen(str)+1);
- strcpy(text, str);
- }
- if (*((char **) valp)) {
- ZnFree(*((char **) valp));
- }
- *((char **) valp) = text;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_FONT:
- {
- Tk_Font font;
- Tk_Uid name = "";
- if (*((Tk_Font *) valp)) {
- name = Tk_NameOfFont(*((Tk_Font *) valp));
- }
- str = Tcl_GetString(args[i+1]);
- if (strcmp(name, str) != 0) {
- font = Tk_GetFont(wi->interp, wi->win, str);
- if (!font) {
- Tcl_AppendResult(wi->interp, " font expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (*((Tk_Font *) valp)) {
- Tk_FreeFont(*((Tk_Font *) valp));
- }
- *((Tk_Font *) valp) = font;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_EDGE_LIST:
- {
- ZnBorder border;
-
- if (ZnGetBorder(wi, args[i+1], &border) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " edge list expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (border != *((ZnBorder *) valp)) {
- *((ZnBorder *) valp) = border;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_LINE_SHAPE:
- {
- ZnLineShape line_shape;
-
- if (ZnGetLineShape(wi, Tcl_GetString(args[i+1]), &line_shape) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " line shape expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (line_shape != *((ZnLineShape *) valp)) {
- *((ZnLineShape *) valp) = line_shape;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_LINE_STYLE:
- {
- ZnLineStyle line_style;
-
- if (ZnGetLineStyle(wi, Tcl_GetString(args[i+1]), &line_style) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " line style expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (line_style != *((ZnLineStyle *) valp)) {
- *((ZnLineStyle *) valp) = line_style;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_LINE_END:
- {
- ZnLineEnd line_end = NULL;
- str = Tcl_GetString(args[i+1]);
- if (strlen(str) != 0) {
- line_end = ZnLineEndCreate(wi->interp, str);
- if (line_end == NULL) {
- return TCL_ERROR;
- }
- }
- if (*((ZnLineEnd *) valp) != NULL) {
- ZnLineEndDelete(*((ZnLineEnd *) valp));
- *((ZnLineEnd *) valp) = line_end;
- *flags |= desc->flags;
- }
- else {
- if (line_end != NULL) {
- *((ZnLineEnd *) valp) = line_end;
- *flags |= desc->flags;
- }
- }
- break;
- }
- case ZN_CONFIG_RELIEF:
- {
- ZnReliefStyle relief;
- if (ZnGetRelief(wi, Tcl_GetString(args[i+1]), &relief) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " relief expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (relief != *((ZnReliefStyle *) valp)) {
- /*printf("valp <0x%X>, flags <0x%X>, relief %d\n", valp, flags, relief);*/
- *((ZnReliefStyle *) valp) = relief;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_JOIN_STYLE:
- {
- int join;
- if (Tk_GetJoinStyle(wi->interp, Tcl_GetString(args[i+1]), &join) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " join expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (join != *((int *) valp)) {
- *((int *) valp) = join;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_CAP_STYLE:
- {
- int cap;
- if (Tk_GetCapStyle(wi->interp, Tcl_GetString(args[i+1]), &cap) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " cap expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (cap != *((int *) valp)) {
- *((int *) valp) = cap;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_POINT:
- {
- ZnPoint point;
- int largc;
- Tcl_Obj **largv;
- double d;
-
- if ((Tcl_ListObjGetElements(wi->interp, args[i+1],
- &largc, &largv) == TCL_ERROR) ||
- (largc != 2)) {
- point_error:
- Tcl_AppendResult(wi->interp, " position expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, largv[0], &d) == TCL_ERROR) {
- goto point_error;
- }
- point.x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, largv[1], &d) == TCL_ERROR) {
- goto point_error;
- }
- point.y = d;
- if ((point.x != ((ZnPoint *) valp)->x) ||
- (point.y != ((ZnPoint *) valp)->y)) {
- *((ZnPoint *) valp) = point;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_DIM:
- {
- ZnDim dim;
- if (Tcl_GetDoubleFromObj(wi->interp, args[i+1], &dim) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " dimension expected for attribute \"",
- Tcl_GetString(args[i+1]), "\"", NULL);
- return TCL_ERROR;
- }
- if (dim != *((ZnDim *) valp)) {
- *((ZnDim *) valp) = dim;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_PRI:
- {
- int pri;
- if (Tcl_GetIntFromObj(wi->interp, args[i+1], &pri) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (pri < 0) {
- Tcl_AppendResult(wi->interp, " priority must be a positive integer \"",
- Tcl_GetString(args[i+1]), "\"", NULL);
- return TCL_ERROR;
- }
- if (pri != *((unsigned short *) valp)) {
- *((unsigned short *) valp) = pri;
- ZnITEM.UpdateItemPriority(item, ZN_NO_ITEM, True);
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_ITEM:
- /*
- * Can be an item id or a tag. In this last case
- * consider only the first item (unspecified order)
- * associated with the tag.
- */
- {
- ZnItem item2;
- int result;
- ZnTagSearch *search_var = NULL;
-
- if (strlen(Tcl_GetString(args[i+1])) == 0) {
- item2 = ZN_NO_ITEM;
- }
- else {
- result = ZnItemWithTagOrId(wi, args[i+1], &item2, &search_var);
- ZnTagSearchDestroy(search_var);
- if ((result == TCL_ERROR) || (item2 == ZN_NO_ITEM)) {
- Tcl_AppendResult(wi->interp, " unknown item \"",
- Tcl_GetString(args[i+1]), "\"", NULL);
- return TCL_ERROR;
- }
- }
- if (item2 != *((ZnItem *) valp)) {
- *((ZnItem *) valp) = item2;
- *flags |= desc->flags;
- }
- }
- break;
- case ZN_CONFIG_WINDOW:
- {
- Tk_Window win, ancestor, parent;
- str = Tcl_GetString(args[i+1]);
- if (strlen(str) == 0) {
- win = NULL;
- }
- else {
- win = Tk_NameToWindow(wi->interp, str, wi->win);
- if (win == NULL) {
- return TCL_ERROR;
- }
- else {
- /*
- * Make sure that the zinc widget is either the parent of the
- * window associated with the item or a descendant of that
- * parent. Also, don't allow a toplevel window or the widget
- * itself to be managed.
- */
- parent = Tk_Parent(win);
- for (ancestor = wi->win; ; ancestor = Tk_Parent(ancestor)) {
- if (ancestor == parent) {
- break;
- }
- if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) {
- badWindow:
- Tcl_AppendResult(wi->interp, "can't use ",
- Tk_PathName(win),
- " in a window item of this zinc widget",
- (char *) NULL);
- win = NULL;
- return TCL_ERROR;
- }
- }
- if (((Tk_FakeWin *) (win))->flags & TK_TOP_LEVEL) {
- goto badWindow;
- }
- if (win == wi->win) {
- goto badWindow;
- }
- if (win != *((Tk_Window *) valp)) {
- *((Tk_Window *) valp) = win;
- *flags |= desc->flags;
- }
- }
- }
- }
- break;
- case ZN_CONFIG_CHAR:
- case ZN_CONFIG_UCHAR:
- case ZN_CONFIG_ALPHA:
- {
- int integer;
- if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
- return TCL_ERROR;
- }
- switch (desc->type) {
- case ZN_CONFIG_UCHAR:
- if (integer < 0) {
- integer = 0;
- }
- case ZN_CONFIG_ALPHA:
- if (integer < 0) {
- integer = 0;
- }
- if (integer > 100) {
- integer = 100;
- }
- break;
- }
- if (integer != *((char *) valp)) {
- *((char *) valp) = integer;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_SHORT:
- case ZN_CONFIG_USHORT:
- {
- int integer;
- if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (desc->type == ZN_CONFIG_SHORT) {
- if (integer < SHRT_MIN) {
- integer = SHRT_MIN;
- }
- else if (integer > SHRT_MAX) {
- integer = SHRT_MAX;
- }
- if (integer != *((short *) valp)) {
- *((short *) valp) = integer;
- *flags |= desc->flags;
- }
- }
- else {
- if (integer < 0) {
- integer = 0;
- }
- else if (integer > USHRT_MAX) {
- integer = USHRT_MAX;
- }
- if (integer != *((unsigned short *) valp)) {
- *((unsigned short *) valp) = integer;
- *flags |= desc->flags;
- }
- }
- break;
- }
- case ZN_CONFIG_INT:
- case ZN_CONFIG_UINT:
- case ZN_CONFIG_ANGLE:
- {
- int integer;
- if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
- return TCL_ERROR;
- }
- switch (desc->type) {
- case ZN_CONFIG_ANGLE:
- if ((integer > 360) || (integer < -360)) {
- integer = integer % 360;
- }
- break;
- case ZN_CONFIG_UINT:
- if (integer < 0) {
- integer = 0;
- }
- break;
- }
- if (integer != *((int *) valp)) {
- *((int *) valp) = integer;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_FILL_RULE:
- {
- ZnFillRule fill_rule;
-
- if (ZnGetFillRule(wi, Tcl_GetString(args[i+1]), &fill_rule) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " fill rule expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (fill_rule != *((ZnFillRule *) valp)) {
- *((ZnFillRule *) valp) = fill_rule;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_ALIGNMENT:
- {
- Tk_Justify justify;
- if (Tk_GetJustify(wi->interp, Tcl_GetString(args[i+1]), &justify) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " justify expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (justify != *((Tk_Justify *) valp)) {
- *((Tk_Justify *) valp) = justify;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_ANCHOR:
- {
- Tk_Anchor anchor;
- if (Tk_GetAnchor(wi->interp, Tcl_GetString(args[i+1]), &anchor) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " anchor expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (anchor != *((Tk_Anchor *) valp)) {
- *((Tk_Anchor *) valp) = anchor;
- *flags |= desc->flags;
- }
- break;
- }
- case ZN_CONFIG_LABEL_FORMAT:
- {
- ZnLabelFormat frmt = NULL;
-
- str = Tcl_GetString(args[i+1]);
- while (*str && (*str == ' ')) {
- str++;
- }
- if (strlen(str) != 0) {
- frmt = ZnLFCreate(wi->interp, str,
- ZnFIELD.NumFields(item->class->GetFieldSet(item)));
- if (frmt == NULL) {
- return TCL_ERROR;
- }
- }
-
- if (*((ZnLabelFormat *) valp) != NULL) {
- ZnLFDelete(*((ZnLabelFormat *) valp));
- *((ZnLabelFormat *) valp) = frmt;
- *flags |= desc->flags;
- }
- else {
- if (frmt != NULL) {
- *((ZnLabelFormat *) valp) = frmt;
- *flags |= desc->flags;
- }
- }
- break;
- }
-
- case ZN_CONFIG_AUTO_ALIGNMENT:
- {
- ZnAutoAlign aa;
-
- if (ZnGetAutoAlign(wi, Tcl_GetString(args[i+1]), &aa) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " auto alignment expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if ((aa.automatic != ((ZnAutoAlign *) valp)->automatic) ||
- (aa.align[0] != ((ZnAutoAlign *) valp)->align[0]) ||
- (aa.align[1] != ((ZnAutoAlign *) valp)->align[1]) ||
- (aa.align[2] != ((ZnAutoAlign *) valp)->align[2])) {
- *((ZnAutoAlign *) valp) = aa;
- *flags |= desc->flags;
- }
- break;
- }
-
- case ZN_CONFIG_LEADER_ANCHORS:
- {
- ZnLeaderAnchors lanch = NULL;
- if (ZnGetLeaderAnchors(wi, Tcl_GetString(args[i+1]), &lanch) == TCL_ERROR) {
- Tcl_AppendResult(wi->interp, " leader anchors expected for attribute \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- if (*((ZnLeaderAnchors *) valp) != NULL) {
- ZnFree(*((ZnLeaderAnchors *) valp));
- *((ZnLeaderAnchors *) valp) = lanch;
- *flags |= desc->flags;
- }
- else {
- if (lanch != NULL) {
- *((ZnLeaderAnchors *) valp) = lanch;
- *flags |= desc->flags;
- }
- }
- break;
- }
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * AttributeToObj --
- *
- * Returns the obj representation of the attribute pointed
- * by 'valp'. The attribute type is given by 'type'. The function
- * never fail.
- *
- **********************************************************************************
- */
-static Tcl_Obj *
-AttributeToObj(Tcl_Interp *interp,
- void *record,
- ZnAttrConfig *desc)
-{
- char *valp = ((char *) record) + desc->offset;
- char *str = "";
- Tcl_Obj *o, *obj;
- unsigned int i;
- char buffer[256];
-
- switch (desc->type) {
- case ZN_CONFIG_GRADIENT:
- if (*((ZnGradient **) valp)) {
- str = ZnNameOfGradient(*((ZnGradient **) valp));
- }
- break;
- case ZN_CONFIG_GRADIENT_LIST:
- {
- unsigned int num_grads;
- ZnGradient **grads;
-
- if (*((ZnList *) valp)) {
- grads = ZnListArray(*((ZnList *) valp));
- num_grads = ZnListSize(*((ZnList *) valp));
-
- obj = Tcl_NewObj();
- for (i = 0; i < num_grads; i++) {
- o = Tcl_NewStringObj(ZnNameOfGradient(grads[i]), -1);
- Tcl_ListObjAppendElement(interp, obj, o);
- }
- return obj;
- }
- }
- break;
- case ZN_CONFIG_BOOL:
- return Tcl_NewBooleanObj(ISSET(*((unsigned short *) valp), desc->bool_bit)?1:0);
- case ZN_CONFIG_IMAGE:
- if (*((ZnImage *) valp)) {
- str = ZnNameOfImage(*((ZnImage *) valp));
-#if PTK
- // Just return the perl image object, it is far more
- // useful than the mere string name.
- return LangObjectObj(interp, str);
-#endif
- }
- break;
- case ZN_CONFIG_BITMAP:
- if (*((ZnImage *) valp)) {
- str = ZnNameOfImage(*((ZnImage *) valp));
- }
- break;
- case ZN_CONFIG_BITMAP_LIST:
- {
- unsigned int num_pats=0;
- ZnImage *pats;
-
- if (*((ZnList *) valp)) {
- pats = (ZnImage *) ZnListArray(*((ZnList *) valp));
- num_pats = ZnListSize(*((ZnList *) valp));
-
- obj = Tcl_NewObj();
- for (i = 0; i < num_pats; i++) {
- if (pats[i] != ZnUnspecifiedImage) {
- o = Tcl_NewStringObj(ZnNameOfImage(pats[i]), -1);
- }
- else {
- o = Tcl_NewStringObj("", -1);
- }
- Tcl_ListObjAppendElement(interp, obj, o);
- }
- return obj;
- }
- break;
- }
- case ZN_CONFIG_TAG_LIST:
- {
- unsigned int num_tags=0;
- Tk_Uid *tags;
-
- if (*((ZnList *) valp)) {
- tags = (Tk_Uid *) ZnListArray(*((ZnList *) valp));
- num_tags = ZnListSize(*((ZnList *) valp));
- obj = Tcl_NewObj();
- for (i = 0; i < num_tags; i++) {
- Tcl_ListObjAppendElement(interp, obj,
- Tcl_NewStringObj(tags[i], -1));
- }
- return obj;
- }
- break;
- }
- case ZN_CONFIG_STRING:
- case ZN_CONFIG_MAP_INFO:
- if (*((char **) valp)) {
- str = *((char **) valp);
- }
- break;
- case ZN_CONFIG_FONT:
- if (*((Tk_Font *) valp)) {
- str = (char *) Tk_NameOfFont(*((Tk_Font *) valp));
- }
- break;
- case ZN_CONFIG_EDGE_LIST:
- str = buffer;
- ZnNameOfBorder(*((ZnBorder *) valp), buffer);
- break;
- case ZN_CONFIG_LINE_SHAPE:
- str = ZnNameOfLineShape(*((ZnLineShape *) valp));
- break;
- case ZN_CONFIG_FILL_RULE:
- str = ZnNameOfFillRule(*((ZnFillRule *) valp));
- break;
- case ZN_CONFIG_LINE_STYLE:
- str = ZnNameOfLineStyle(*((ZnLineStyle *) valp));
- break;
- case ZN_CONFIG_LINE_END:
- if (*((ZnLineEnd *) valp)) {
- str = ZnLineEndGetString(*((ZnLineEnd *) valp));
- }
- break;
- case ZN_CONFIG_RELIEF:
- str = ZnNameOfRelief(*((ZnReliefStyle *) valp));
- break;
- case ZN_CONFIG_JOIN_STYLE:
- str = (char *) Tk_NameOfJoinStyle(*((int *) valp));
- break;
- case ZN_CONFIG_CAP_STYLE:
- str = (char *) Tk_NameOfCapStyle(*((int *) valp));
- break;
- case ZN_CONFIG_POINT:
- obj = Tcl_NewObj();
- Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->x));
- Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->y));
- return obj;
- case ZN_CONFIG_ITEM:
- if (*((ZnItem *) valp) != ZN_NO_ITEM) {
- return Tcl_NewLongObj((int) (*((ZnItem *) valp))->id);
- }
- break;
- case ZN_CONFIG_WINDOW:
- if (*((Tk_Window *) valp) != NULL) {
- str = Tk_PathName(*((Tk_Window *) valp));
- }
- break;
- case ZN_CONFIG_CHAR:
- return Tcl_NewIntObj(*((char *) valp));
- case ZN_CONFIG_UCHAR:
- case ZN_CONFIG_ALPHA:
- return Tcl_NewIntObj(*((unsigned char *) valp));
- case ZN_CONFIG_USHORT:
- case ZN_CONFIG_PRI:
- return Tcl_NewIntObj(*((unsigned short *) valp));
- case ZN_CONFIG_SHORT:
- return Tcl_NewIntObj(*((short *) valp));
- case ZN_CONFIG_UINT:
- return Tcl_NewIntObj(*((unsigned int *) valp));
- case ZN_CONFIG_INT:
- case ZN_CONFIG_ANGLE:
- return Tcl_NewIntObj(*((int *) valp));
- case ZN_CONFIG_DIM:
- return Tcl_NewDoubleObj(*((ZnDim *) valp));
- case ZN_CONFIG_ALIGNMENT:
- str = (char *) Tk_NameOfJustify(*((Tk_Justify *) valp));
- break;
- case ZN_CONFIG_ANCHOR:
- str = (char *) Tk_NameOfAnchor(*((Tk_Anchor *) valp));
- break;
- case ZN_CONFIG_LABEL_FORMAT:
- if (*((ZnLabelFormat *) valp)) {
- str = ZnLFGetString(*((ZnLabelFormat *) valp));
- }
- break;
- case ZN_CONFIG_AUTO_ALIGNMENT:
- str = buffer;
- ZnNameOfAutoAlign((ZnAutoAlign *) valp, buffer);
- break;
- case ZN_CONFIG_LEADER_ANCHORS:
- str = buffer;
- ZnNameOfLeaderAnchors(*((ZnLeaderAnchors *) valp), buffer);
- break;
- }
- return Tcl_NewStringObj(str, -1);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnQueryAttribute --
- *
- **********************************************************************************
- */
-int
-ZnQueryAttribute(Tcl_Interp *interp,
- void *record,
- ZnAttrConfig *desc_table,
- Tcl_Obj *attr_name)
-{
- ZnAttrConfig *desc = GetAttrDesc(interp, attr_name, desc_table);
-
- if (!desc) {
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, AttributeToObj(interp, record, desc));
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnItemClassList --
- *
- **********************************************************************************
- */
-ZnList
-ZnItemClassList()
-{
- return item_classes;
-}
-
-/*
- **********************************************************************************
- *
- * ZnLookupItemClass --
- *
- **********************************************************************************
- */
-ZnItemClass
-ZnLookupItemClass(char *class_name)
-{
- ZnItemClass *class;
- int i, num_classes;
-
- class = (ZnItemClass *) ZnListArray(item_classes);
- num_classes = ZnListSize(item_classes);
- for (i = 0; i < num_classes; i++) {
- if (strcmp((class[i])->name, class_name) == 0) {
- return class[i];
- }
- }
-
- return NULL;
-}
-
-/*
- **********************************************************************************
- *
- * ZnAddItemClass --
- *
- **********************************************************************************
- */
-void
-ZnAddItemClass(ZnItemClass class)
-{
- if (!ZnLookupItemClass(class->name)) {
- ZnListAdd(item_classes, &class, ZnListTail);
- InitAttrDesc(class->attr_desc);
- }
-}
-
-/*
- **********************************************************************************
- *
- * ZnItemInit --
- * Initialize classes static state.
- *
- **********************************************************************************
- */
-void
-ZnItemInit()
-{
- /* First check if static part already inited */
- if (item_classes == NULL) {
- item_classes = ZnListNew(16, sizeof(ZnItemClass));
-#ifdef ATC
- ZnAddItemClass(ZnTrack);
- ZnAddItemClass(ZnWayPoint);
- ZnAddItemClass(ZnMap);
- ZnAddItemClass(ZnReticle);
-#endif
- ZnAddItemClass(ZnTabular);
- ZnAddItemClass(ZnRectangle);
- ZnAddItemClass(ZnArc);
- ZnAddItemClass(ZnCurve);
- ZnAddItemClass(ZnTriangles);
- ZnAddItemClass(ZnGroup);
- ZnAddItemClass(ZnIcon);
- ZnAddItemClass(ZnText);
- ZnAddItemClass(ZnWindow);
- InitAttrDesc(ZnFIELD.attr_desc);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * UpdateItemDependency -- Method
- * Update the group dependency list following a change in the
- * connection of an item.
- *
- **********************************************************************************
- */
-static void
-UpdateItemDependency(ZnItem item,
- ZnItem old_connection)
-{
- if (old_connection == ZN_NO_ITEM) {
- /* Add a connection */
- ZnInsertDependentItem(item);
- }
- else if (item->connected_item == ZN_NO_ITEM) {
- /* Remove a connection */
- ZnExtractDependentItem(item);
- }
- else {
- /* Move at end to ensure that it will be updated after
- * the (new) item it depends upon.
- */
- ZnExtractDependentItem(item);
- ZnInsertDependentItem(item);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ExtractItem --
- * Extract an item from its context, includes updating graphic
- * state flags.
- *
- **********************************************************************************
- */
-static void
-ExtractItem(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ZnItem group = item->parent;
-
- /* damage bounding boxes */
- if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
- ZnDamage(wi, &item->item_bounding_box);
- }
-
- /*
- * Tell that we need to repick
- */
- if (item->class != ZnGroup) {
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- }
-
- if (group != ZN_NO_ITEM) {
- /* Remove me from dependency list. */
- ZnExtractDependentItem(item);
-
- /* Disconnect all dependents on me. */
- ZnDisconnectDependentItems(item);
- /*
- * Remove me as a clip item.
- */
- ZnGroupRemoveClip(group, item);
- /*
- * Remove me from item list.
- */
- ZnGroupExtractItem(item);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * InsertItem -- Method
- *
- * Insert an item in the display list according to its priority.
- * It is inserted in front of items of lower or same priority. If
- * mark_item is not ZN_NO_ITEM the insertion is done relative
- * to this item, before it if 'before' is True, after it otherwise.
- * mark_item must be in the group 'group'.
- *
- **********************************************************************************
- */
-static void
-InsertItem(ZnItem item,
- ZnItem grp,
- ZnItem mark_item,
- ZnBool before)
-{
- if (!grp) {
- grp = item->wi->top_group;
- }
- item->parent = grp;
-
- if (mark_item && (mark_item->parent != grp)) {
- mark_item = ZN_NO_ITEM;
- }
-
- ZnGroupInsertItem(grp, item, mark_item, before);
-}
-
-
-/*
- **********************************************************************************
- *
- * UpdateItemPriority -- Method
- * Reorder a group's item list following a change in an
- * item priority or a call to lower/raise.
- *
- **********************************************************************************
- */
-static void
-UpdateItemPriority(ZnItem item,
- ZnItem mark_item,
- ZnBool before)
-{
- ZnItem parent = item->parent;
-
- ZnGroupExtractItem(item);
- InsertItem(item, parent, mark_item, before);
- Invalidate(item, ZN_DRAW_FLAG);
- SET(item->wi->flags, ZN_INTERNAL_NEED_REPICK);
-}
-
-
-/*
- **********************************************************************************
- *
- * SetId,
- * FreeId -- Method
- * Get a fresh object id from the widget and enter the new
- * object with this id in the object hash table. The id is
- * incremented. FreeId on the other hand suppress the item
- * from the hash table and set its object id to zero.
- *
- **********************************************************************************
- */
-static void
-SetId(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- Tcl_HashEntry *entry;
- int dummy;
-
- item->id = wi->obj_id;
- wi->obj_id++;
- entry = Tcl_CreateHashEntry(wi->id_table, (char *) item->id, &dummy);
- Tcl_SetHashValue(entry, item);
-}
-
-static void
-FreeId(ZnItem item)
-{
- Tcl_HashEntry *entry;
-
- if (item->id) {
- entry = Tcl_FindHashEntry(item->wi->id_table, (char *) item->id);
- if (entry) {
- Tcl_DeleteHashEntry(entry);
- item->id = 0;
- }
- }
-}
-
-/*
- **********************************************************************************
- *
- * AddTag -- Method
- * Add a tag to the item. If the tag is already on the list it
- * is not added. As a side effect the tag/item pair is added to
- * the tag table of the widget.
- * 'tag' must be a Tk_Uid.
- *
- **********************************************************************************
- */
-static void
-AddTag(ZnItem item,
- Tk_Uid tag)
-{
- int num, i;
- char **ptr;
-
- /*
- * No tags yet.
- */
- if (!item->tags) {
- item->tags = ZnListNew(1, sizeof(char *));
- }
- else {
- /*
- * If the tag is already there, that's done.
- */
- ptr = (char **) ZnListArray(item->tags);
- num = ZnListSize(item->tags);
- for (i = 0; i < num; i++) {
- if (ptr[i] == tag) {
- return;
- }
- }
- }
- /*
- * Add it.
- */
- ZnListAdd(item->tags, (void *) &tag, ZnListTail);
-}
-
-/*
- **********************************************************************************
- *
- * RemoveTag -- Method
- *
- **********************************************************************************
- */
-static void
-RemoveTag(ZnItem item,
- Tk_Uid tag)
-{
- unsigned int indx, num;
- char **ptr;
-
- if (!item->tags) {
- return;
- }
- /*
- * look up the tag in the list.
- */
- ptr = (char **) ZnListArray(item->tags);
- num = ZnListSize(item->tags);
- for (indx = 0; indx < num; indx++) {
- if (ptr[indx] == tag) {
- /* The tag list is not freed when empty to avoid
- * overhead when using tags intensively. */
- ZnListDelete(item->tags, indx);
- return;
- }
- }
-}
-
-/*
- **********************************************************************************
- *
- * FreeTags -- Method
- *
- **********************************************************************************
- */
-static void
-FreeTags(ZnItem item)
-{
- if (!item->tags) {
- return;
- }
- ZnListFree(item->tags);
- item->tags = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * HasTag -- Method
- *
- **********************************************************************************
- */
-static ZnBool
-HasTag(ZnItem item,
- Tk_Uid tag)
-{
- int num;
- Tk_Uid *tags;
-
- if (!item->tags || !ZnListSize(item->tags)) {
- return False;
- }
- else {
- num = ZnListSize(item->tags);
- tags = ZnListArray(item->tags);
- for (tags = ZnListArray(item->tags); num > 0; tags++, num--) {
- if (*tags == tag) {
- return True;
- }
- }
- }
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnCreateItem --
- *
- * InsertItem and ConfigureItem must be called after CreateItem
- * to finalize the setup of a new item. This is so even if
- * there are no attributes to be changed after creation.
- * ConfigureItem must be called in this case with the 'init'
- * parameter set to True.
- *
- **********************************************************************************
- */
-ZnItem
-ZnCreateItem(ZnWInfo *wi,
- ZnItemClass item_class,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnItem item;
-
- item = ZnMalloc(item_class->size);
-
- /* Initialize common state */
- item->class = item_class;
- item->wi = wi;
- item->parent = NULL;
- item->previous = ZN_NO_ITEM;
- item->next = ZN_NO_ITEM;
- CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT);
- item->inv_flags = 0;
- item->transfo = NULL;
- item->parent = NULL;
- item->connected_item = ZN_NO_ITEM;
-#ifdef GL
-#ifdef GL_LIST
- item->gl_list = 0;
-#endif
-#endif
- ZnResetBBox(&item->item_bounding_box);
-
- /* Init item specific attributes */
- if (item_class->Init(item, argc, args) == TCL_ERROR) {
- ZnFree(item);
- return ZN_NO_ITEM;
- }
-
- SetId(item);
- item->tags = NULL;
-
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- wi->num_items++;
-
- return (item);
-}
-
-
-/*
- **********************************************************************************
- *
- * CloneItem -- Method
- * Can't clone the top level group.
- *
- **********************************************************************************
- */
-static ZnItem
-CloneItem(ZnItem model)
-{
- ZnWInfo *wi = model->wi;
- ZnItem item;
- Tk_Uid *tags;
- unsigned int num_tags;
- int i;
-
- if (!model->parent) {
- return ZN_NO_ITEM;
- }
-
- item = ZnMalloc(model->class->size);
- memcpy(item, model, model->class->size);
-
- item->previous = ZN_NO_ITEM;
- item->next = ZN_NO_ITEM;
- item->connected_item = ZN_NO_ITEM;
- CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT);
- item->inv_flags = 0;
- SetId(item);
-
- if (model->tags) {
- item->tags = NULL;
- tags = (Tk_Uid *) ZnListArray(model->tags);
- num_tags = ZnListSize(model->tags);
- for (i = num_tags-1; i >= 0; i--, tags++) {
- AddTag(item, *tags);
- }
- }
-
- if (item->transfo) {
- item->transfo = ZnTransfoDuplicate(item->transfo);
- }
-
- /* Call item's clone to duplicate non shared resources */
- item->class->Clone(item);
-
- SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
- wi->num_items++;
-
- Invalidate(item, ZN_COORDS_FLAG);
-
- return item;
-}
-
-
-/*
- **********************************************************************************
- *
- * ConfigureItem -- Method
- *
- **********************************************************************************
- */
-static int
-ConfigureItem(ZnItem item,
- int field,
- int argc,
- Tcl_Obj *CONST argv[],
- ZnBool init)
-{
- ZnWInfo *wi = item->wi;
- int flags;
- ZnBool previous_visible = init ? False : ISSET(item->flags, ZN_VISIBLE_BIT);
-
- flags = 0;
- ASSIGN(flags, ZN_COORDS_FLAG, init);
- if (argv) {
- if (field < 0){
- if (item->class->Configure(item, argc, argv, &flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (item->class->GetFieldSet && ISSET(flags, ZN_CLFC_FLAG)) {
- ZnFIELD.ClearFieldCache(item->class->GetFieldSet(item), -1);
- }
- }
- else if (item->class->GetFieldSet) {
- if (ZnFIELD.ConfigureField(item->class->GetFieldSet(item),
- field, argc, argv, &flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- else {
- return TCL_ERROR;
- }
- }
-
- if (previous_visible && ISCLEAR(item->flags, ZN_VISIBLE_BIT)) {
- /*
- * Special case when the item has its visibility
- * just turned out.
- */
- ZnDamage(wi, &item->item_bounding_box);
- }
-
- Invalidate(item, flags);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * QueryItem -- Method
- *
- **********************************************************************************
- */
-static int
-QueryItem(ZnItem item,
- int field,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (field < 0) {
- return item->class->Query(item, argc, argv);
- }
- else if (item->class->GetFieldSet) {
- return ZnFIELD.QueryField(item->class->GetFieldSet(item),
- field, argc, argv);
- }
-
- return TCL_ERROR;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComposeTransform --
- * Compose a transform transfo with current_t to new_t.
- *
- **********************************************************************************
- */
-static void
-ComposeTransform(ZnTransfo *transfo,
- ZnPoint *pos,
- ZnTransfo *current_t,
- ZnTransfo *new_t,
- ZnBool compose_scale,
- ZnBool compose_rot)
-{
- ZnBool full;
- ZnTransfo t, t2;
-
- full = compose_scale && compose_rot;
-
- if (!transfo && !pos && full) {
- *new_t = *current_t;
- return;
- }
- if (full) {
- /*
- * Full concatenation.
- */
- /*ZnPrintTransfo(transfo);*/
- if (pos) {
- if (!transfo) {
- ZnTransfoSetIdentity(&t);
- }
- else {
- t = *transfo;
- }
- ZnTranslate(&t, pos->x, pos->y, False);
- ZnTransfoCompose(new_t, &t, current_t);
- }
- else {
- ZnTransfoCompose(new_t, transfo, current_t);
- }
- }
- else {
- ZnPoint scale, trans, local_scale, local_trans, p;
- ZnReal local_rot, rot;
-
- ZnTransfoSetIdentity(new_t);
- ZnTransfoDecompose(transfo, &local_scale, &local_trans, &local_rot, NULL);
- ZnScale(new_t, local_scale.x, local_scale.y);
- ZnRotateRad(new_t, local_rot);
-
- ZnTransfoDecompose(current_t, &scale, &trans, &rot, NULL);
-
- if (pos) {
- ZnTransfoSetIdentity(&t);
- ZnTranslate(&t, pos->x, pos->y, False);
- ZnTransfoCompose(&t2, &t, current_t);
- ZnTransformPoint(&t2, &local_trans, &p);
- }
- else {
- ZnTransformPoint(current_t, &local_trans, &p);
- }
-
- if (compose_scale) {
- ZnScale(new_t, scale.x, scale.y);
- }
- if (compose_rot) {
- ZnRotateRad(new_t, rot);
- }
- ZnTranslate(new_t, p.x, p.y, False);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetItemTransform -- Method
- * Compute the current transform for an item.
- *
- **********************************************************************************
- */
-static void
-GetItemTransform(ZnItem item,
- ZnTransfo *t)
-{
- ZnItem *items;
- int i;
- ZnTransfo t_tmp, *t1, *t2, *swap;
- ZnPoint *pos;
-
- if (item_stack == NULL) {
- item_stack = ZnListNew(16, sizeof(ZnItem));
- }
- else {
- ZnListEmpty(item_stack);
- }
-
- while (item != ZN_NO_ITEM) {
- ZnListAdd(item_stack, &item, ZnListTail);
- item = item->parent;
- }
-
- ZnTransfoSetIdentity(t);
- t1 = t;
- t2 = &t_tmp;
- items = (ZnItem *) ZnListArray(item_stack);
- for (i = ZnListSize(item_stack)-1; i >= 0; i--) {
- pos = NULL;
- if (items[i]->class->pos_offset >= 0) {
- pos = (ZnPoint *) (((char *) items[i]) + items[i]->class->pos_offset);
- if (pos->x == 0 && pos->y == 0) {
- pos = NULL;
- }
- }
- ComposeTransform(items[i]->transfo, pos, t1, t2,
- ISSET(items[i]->flags, ZN_COMPOSE_SCALE_BIT),
- ISSET(items[i]->flags, ZN_COMPOSE_ROTATION_BIT));
- swap = t2;
- t2 = t1;
- t1 = swap;
- }
- if (t1 != t) {
- *t = *t1;
- }
-}
-
-
-
-/*
- **********************************************************************************
- *
- * ZnResetTransformStack
- * ZnInitTransformStack
- * ZnFreeTransformStack
- * ZnCurrentTransform
- * ZnPushTransform
- * ZnPopTransform --
- *
- **********************************************************************************
- */
-void
-ZnResetTransformStack(ZnWInfo *wi)
-{
- ZnListAssertSize(wi->transfo_stack, 1);
- wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, 0);
- ZnTransfoSetIdentity(wi->current_transfo);
-}
-
-void
-ZnInitTransformStack(ZnWInfo *wi)
-{
- wi->transfo_stack = ZnListNew(8, sizeof(ZnTransfo));
- ZnResetTransformStack(wi);
-}
-
-void
-ZnFreeTransformStack(ZnWInfo *wi)
-{
- ZnListFree(wi->transfo_stack);
-}
-
-void
-ZnPushTransform(ZnWInfo *wi,
- ZnTransfo *transfo,
- ZnPoint *pos,
- ZnBool compose_scale,
- ZnBool compose_rot)
-{
- ZnTransfo *next_t;
- unsigned int num_t;
-
- /*
- * Push the current transform and concatenate
- * the new transform taking into account the
- * combination flags.
- */
- num_t = ZnListSize(wi->transfo_stack);
- ZnListAssertSize(wi->transfo_stack, num_t+1);
- next_t = (ZnTransfo *) ZnListAt(wi->transfo_stack, num_t);
- ComposeTransform(transfo, pos, wi->current_transfo, next_t,
- compose_scale, compose_rot);
- wi->current_transfo = next_t;
-}
-
-void
-ZnPopTransform(ZnWInfo *wi)
-{
- /*
- * Restore the previous transform.
- */
- ZnListDelete(wi->transfo_stack, ZnListTail);
- wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, ZnListTail);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnResetClipStack
- * ZnInitClipStack
- * ZnFreeClipStack
- * ZnCurrentClip
- * ZnPushClip
- * ZnPopClip --
- *
- **********************************************************************************
- */
-/*
- * Describe the clipping at a given node
- * of the item hierarchy.
- */
-typedef struct _ClipState {
- ZnBool simple; /* The clip is an aligned rectangle. */
- TkRegion region; /* The region used to draw and to */
- /* probe for picking. */
- ZnBBox clip_box; /* The bounding box of the clip area. */
-} ClipState;
-
-void
-ZnResetClipStack(ZnWInfo *wi)
-{
- int i;
- ClipState *clips = (ClipState *) ZnListArray(wi->clip_stack);
-
- /*
- * Should not happen, clip stack should be
- * empty when this function is called.
- */
- for (i = ZnListSize(wi->clip_stack)-1; i >= 0; i--) {
- TkDestroyRegion(clips[i].region);
- }
- ZnListEmpty(wi->clip_stack);
- wi->current_clip = NULL;
-}
-
-void
-ZnInitClipStack(ZnWInfo *wi)
-{
- wi->clip_stack = ZnListNew(8, sizeof(ClipState));
- ZnResetClipStack(wi);
-}
-
-void
-ZnFreeClipStack(ZnWInfo *wi)
-{
- ZnListFree(wi->clip_stack);
-}
-
-ZnBool
-ZnCurrentClip(ZnWInfo *wi,
- TkRegion *reg,
- ZnBBox **clip_box,
- ZnBool *simple)
-{
- if (wi->current_clip) {
- if (reg) {
- *reg = wi->current_clip->region;
- }
- if (clip_box) {
- *clip_box = &wi->current_clip->clip_box;
- }
- if (simple) {
- *simple = wi->current_clip->simple;
- }
- return True;
- }
-
- return False;
-}
-
-/*
- * If simple is True poly is a pointer to an
- * array of two points. In the other case it
- * is a regular pointer to a multi contour poly.
- */
-void
-ZnPushClip(ZnWInfo *wi,
- ZnTriStrip *tristrip,
- ZnBool simple,
- ZnBool set_gc)
-{
- unsigned int i, j, num_clips;
- unsigned int num_pts, max_num_pts;
- ZnPoint *p;
- ClipState *previous_clip=NULL;
- TkRegion reg, reg_op, reg_to;
- XRectangle rect;
- XPoint xpts[3];
-
- if (tristrip->num_strips == 0) {
- return;
- }
- max_num_pts = tristrip->strips[0].num_points;
- for (j = 0; j < tristrip->num_strips; j++) {
- num_pts = tristrip->strips[j].num_points;
- if (num_pts > max_num_pts) {
- num_pts = max_num_pts;
- }
- }
- if ((simple && (max_num_pts < 2)) ||
- (!simple && (max_num_pts < 3))) {
- return;
- }
-
- num_clips = ZnListSize(wi->clip_stack);
- /* printf("PushClip: num clips %d\n", num_clips);fflush(stdout);*/
- if (num_clips != 0) {
- previous_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
- }
- ZnListAssertSize(wi->clip_stack, num_clips+1);
- wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
- wi->current_clip->simple = simple;
-
- /*
- * Compute the local region.
- */
- if (simple) {
- rect.x = (short) tristrip->strips[0].points[0].x;
- rect.y = (short) tristrip->strips[0].points[0].y;
- rect.width = ((unsigned short) (tristrip->strips[0].points[1].x -
- tristrip->strips[0].points[0].x));
- rect.height = ((unsigned short) (tristrip->strips[0].points[1].y -
- tristrip->strips[0].points[0].y));
- reg = TkCreateRegion();
- TkUnionRectWithRegion(&rect, reg, reg);
- /*printf("Adding a simple clip: %d, %d, %d, %d\n",
- rect.x, rect.y, rect.width, rect.height);*/
- }
- else {
- reg = TkCreateRegion();
- for (j = 0; j < tristrip->num_strips; j++) {
- num_pts = tristrip->strips[j].num_points;
- p = tristrip->strips[j].points;
- if (tristrip->strips[j].fan) {
- xpts[0].x = ZnNearestInt(p->x);
- xpts[0].y = ZnNearestInt(p->y);
- p++;
- xpts[1].x = ZnNearestInt(p->x);
- xpts[1].y = ZnNearestInt(p->y);
- p++;
- for (i = 2; i < num_pts; i++, p++) {
- xpts[2].x = ZnNearestInt(p->x);
- xpts[2].y = ZnNearestInt(p->y);
- reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule);
- reg_to = TkCreateRegion();
- ZnUnionRegion(reg, reg_op, reg_to);
- TkDestroyRegion(reg);
- TkDestroyRegion(reg_op);
- reg = reg_to;
- xpts[1] = xpts[2];
- }
- }
- else {
- xpts[0].x = (short) p->x;
- xpts[0].y = (short) p->y;
- p++;
- xpts[1].x = (short) p->x;
- xpts[1].y = (short) p->y;
- p++;
- for (i = 2 ; i < num_pts; i++, p++) {
- xpts[2].x = (short) p->x;
- xpts[2].y = (short) p->y;
- reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule);
- reg_to = TkCreateRegion();
- ZnUnionRegion(reg, reg_op, reg_to);
- TkDestroyRegion(reg);
- TkDestroyRegion(reg_op);
- reg = reg_to;
- xpts[0] = xpts[1];
- xpts[1] = xpts[2];
- }
- }
- }
- }
-
- /*
- * Combine with previous region if any.
- */
- if (previous_clip) {
- wi->current_clip->region = TkCreateRegion();
- TkIntersectRegion(reg, previous_clip->region, wi->current_clip->region);
- TkDestroyRegion(reg);
- /*printf("Merging with previous clip\n");*/
- }
- else {
- wi->current_clip->region = reg;
- }
- TkClipBox(wi->current_clip->region, &rect);
- wi->current_clip->clip_box.orig.x = rect.x;
- wi->current_clip->clip_box.orig.y = rect.y;
- wi->current_clip->clip_box.corner.x = rect.x + rect.width;
- wi->current_clip->clip_box.corner.y = rect.y + rect.height;
-
- /*
- * Set the clipping in the GC.
- */
- if (set_gc) {
- if (wi->render) {
-#ifdef GL
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF);
- glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- if (simple) {
- /* printf("Clip box is : %d, %d, %d, %d, num_clips : %d\n",
- rect.x, rect.y, rect.width, rect.height, num_clips);*/
- glBegin(GL_QUADS);
- glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y);
- glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y);
- glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y);
- glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y);
- glEnd();
- }
- else {
- for (j = 0; j < tristrip->num_strips; j++) {
- num_pts = tristrip->strips[j].num_points;
- p = tristrip->strips[j].points;
- if (tristrip->strips[j].fan) {
- glBegin(GL_TRIANGLE_FAN);
- }
- else {
- glBegin(GL_TRIANGLE_STRIP);
- }
- for (i = 0; i < num_pts; i++, p++) {
- glVertex2d(p->x, p->y);
- }
- glEnd();
- }
- }
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-#endif
- }
- else {
- TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region);
- }
- }
-}
-
-void
-ZnPopClip(ZnWInfo *wi,
- ZnBool set_gc)
-{
- int num_clips;
-
- if (wi->current_clip == NULL) {
- return;
- }
-
- TkDestroyRegion(wi->current_clip->region);
- ZnListDelete(wi->clip_stack, ZnListTail);
- num_clips = ZnListSize(wi->clip_stack);
-
- if (num_clips != 0) {
- wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
- }
- else {
- wi->current_clip = NULL;
- }
-
- /*
- * Set the clipping in the GC.
- */
- if (set_gc) {
- if (num_clips != 0) {
- if (wi->render) {
-#ifdef GL
- glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF);
- glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-#if 0
- if (wi->current_clip->simple) {
-#endif
- glBegin(GL_QUADS);
- glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y);
- glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y);
- glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y);
- glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y);
- glEnd();
-#if 0
- }
- else {
- }
-#endif
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-#endif
- }
- else {
- TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region);
- }
- }
- else {
- /*printf("resetting clip mask\n");*/
- if (wi->render) {
-#ifdef GL
- glClear(GL_STENCIL_BUFFER_BIT);
- glDisable(GL_STENCIL_TEST);
-#endif
- }
- else {
- XSetClipMask(wi->dpy, wi->gc, None);
- }
- }
- }
- /*printf("PopClip: num clips %d\n", ZnListSize(wi->clip_stack));fflush(stdout);*/
-}
-
-
-/*
- **********************************************************************************
- *
- * Invalidate -- Method
- *
- **********************************************************************************
- */
-static void
-Invalidate(ZnItem item,
- int reason)
-{
- /*
- * Why this test has to be so an abrupt shortcut ?
- * It precludes addition of meaningful reasons
- * by subsequent invalidations .
- *
- if (ISSET(item->inv_flags, ZN_TRANSFO_FLAG)) {
- return;
- }*/
-
- if (ISSET(reason, ZN_COORDS_FLAG) ||
- ISSET(reason, ZN_TRANSFO_FLAG)) {
- ZnItem parent = item->parent;
- while ((parent != NULL) &&
- ISCLEAR(parent->inv_flags, ZN_COORDS_FLAG) &&
- ISCLEAR(parent->inv_flags, ZN_TRANSFO_FLAG)) {
- SET(parent->inv_flags, ZN_COORDS_FLAG);
- /*printf("invalidate coords for parent %d\n", parent->id);*/
- parent = parent->parent;
- }
- /*
- * There is no need to set the DRAW flag to force the invalidation
- * of the current bounding box. This will be done by ComputeCoordinates
- * in Group.
- */
- item->inv_flags |= reason;
- /*printf("invalidate %s for item %d, flags %s\n",
- ISSET(reason, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS", item->id,
- ISSET(item->inv_flags, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS");*/
- ZnNeedRedisplay(item->wi);
- }
- else if (ISSET(reason, ZN_DRAW_FLAG)) {
- if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
- /*printf("invalidate graphics for item %d\n", item->id);*/
- ZnDamage(item->wi, &item->item_bounding_box);
-#ifdef GL
-#ifdef GL_LIST
- /*
- * Remove the item display list so that it will be recreated
- * to reflect the changes.
- */
- if (item->gl_list) {
- glDeleteLists(item->gl_list, 1);
- item->gl_list = 0;
- }
-#endif
-#endif
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * InvalidateItems -- Method
- * Invalidate the geometric state of all items belonging
- * to a given class. The search for items starts at group
- * and proceed depth first.
- *
- **********************************************************************************
- */
-static void
-InvalidateItems(ZnItem group,
- ZnItemClass item_class)
-{
- ZnItem item;
-
- if (group->class != ZnGroup) {
- return;
- }
- item = ZnGroupHead(group);
- while (item != ZN_NO_ITEM) {
- if (item->class == item_class) {
- Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (item->class == ZnGroup) {
- InvalidateItems(item, item_class);
- }
- item = item->next;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ResetTransfo
- * SetTransfo
- * TranslateItem
- * ScaleItem
- * SkewItem
- * RotateItem -- Methods
- * Set of functions that deal with item transform. They take care
- * of all details including managing NULL transforms and invalidating
- * the item hierarchy.
- *
- **********************************************************************************
- */
-static void
-ResetTransfo(ZnItem item)
-{
- if (item->transfo) {
- ZnFree(item->transfo);
- item->transfo = NULL;
- }
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-static void
-SetTransfo(ZnItem item,
- ZnTransfo *t)
-{
- if (item->transfo) {
- ZnFree(item->transfo);
- }
- if (!t || ZnTransfoIsIdentity(t)) {
- item->transfo = NULL;
- }
- else {
- item->transfo = ZnTransfoDuplicate(t);
- }
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-static void
-TranslateItem(ZnItem item,
- ZnReal dx,
- ZnReal dy,
- ZnBool abs)
-{
- if (!item->transfo) {
- item->transfo = ZnTransfoNew();
- }
- ZnTranslate(item->transfo, dx, dy, abs);
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-static void
-ScaleItem(ZnItem item,
- ZnReal sx,
- ZnReal sy,
- ZnPoint *p)
-{
- if (!item->transfo) {
- item->transfo = ZnTransfoNew();
- }
- if (p) {
- ZnTranslate(item->transfo, -p->x, -p->y, False);
- }
- ZnScale(item->transfo, sx, sy);
- if (p) {
- ZnTranslate(item->transfo, p->x, p->y, False);
- }
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-static void
-SkewItem(ZnItem item,
- ZnReal x_skew,
- ZnReal y_skew)
-{
- if (!item->transfo) {
- item->transfo = ZnTransfoNew();
- }
- ZnSkewRad(item->transfo, x_skew, y_skew);
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-static void
-RotateItem(ZnItem item,
- ZnReal angle,
- ZnBool deg,
- ZnPoint *p)
-{
- if (!item->transfo) {
- item->transfo = ZnTransfoNew();
- }
- if (p) {
- ZnTranslate(item->transfo, -p->x, -p->y, False);
- }
- if (deg) {
- ZnRotateDeg(item->transfo, angle);
- }
- else {
- ZnRotateRad(item->transfo, angle);
- }
- if (p) {
- ZnTranslate(item->transfo, p->x, p->y, False);
- }
-
- Invalidate(item, ZN_TRANSFO_FLAG);
-}
-
-
-/*
- **********************************************************************************
- *
- * DestroyItem -- Method
- *
- **********************************************************************************
- */
-static void
-DestroyItem(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
-
- /*
- * Extract it from its group.
- */
- ExtractItem(item);
-
- /*
- * Update state variables to prevent dangling pointers.
- */
- if (wi->current_item == item) {
- wi->current_item = ZN_NO_ITEM;
- wi->current_part = ZN_NO_PART;
- }
- if (wi->new_item == item) {
- wi->new_item = ZN_NO_ITEM;
- wi->new_part = ZN_NO_PART;
- }
- if ((wi->hot_item == item) || (wi->hot_prev) == item) {
- wi->hot_item = ZN_NO_ITEM;
- }
- if (ti->sel_item == item) {
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
- }
- if (ti->anchor_item == item) {
- ti->anchor_item = ZN_NO_ITEM;
- ti->anchor_field = ZN_NO_PART;
- }
- if (wi->focus_item == item) {
- wi->focus_item = ZN_NO_ITEM;
- wi->focus_field = ZN_NO_PART;
- }
-
- /*
- * Call per class removal code.
- */
- (item->class->Destroy)(item);
- /*
- * Free the transform if any.
- */
- if (item->transfo) {
- ZnFree(item->transfo);
- }
- /*
- * Remove the item from the item table and free
- * all its tags.
- */
- FreeId(item);
- FreeTags(item);
- /*
- * Free the item own memory
- */
- ZnFree(item);
- wi->num_items--;
-}
-
-
-/*
- **********************************************************************************
- *
- * Generic methods on items --
- *
- **********************************************************************************
- */
-
-struct _ZnITEM ZnITEM = {
- CloneItem,
- DestroyItem,
- ConfigureItem,
- QueryItem,
- InsertItem,
- UpdateItemPriority,
- UpdateItemDependency,
- ExtractItem,
- SetId,
- FreeId,
- AddTag,
- RemoveTag,
- FreeTags,
- HasTag,
- ResetTransfo,
- SetTransfo,
- TranslateItem,
- ScaleItem,
- SkewItem,
- RotateItem,
- Invalidate,
- InvalidateItems,
- GetItemTransform
-};
diff --git a/generic/Item.h b/generic/Item.h
deleted file mode 100644
index 3871bf8..0000000
--- a/generic/Item.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Item.h -- Header to access items' common state and functions.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1996 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Item_h
-#define _Item_h
-
-
-#include "PostScript.h"
-#include "Attrs.h"
-#include "Types.h"
-#include "List.h"
-#include "Field.h"
-
-#include <X11/Xlib.h>
-#include <tkInt.h>
-
-
-/*
- * Types and constants for attribute processing.
- */
-typedef struct _ZnAttrConfig {
- int type;
- char *name;
- Tk_Uid uid;
- int offset;
- int bool_bit;
- int flags;
- ZnBool read_only;
-} ZnAttrConfig;
-
-/*
- * When adding new type in the following enum
- * do not forget to update attribute_type_strings
- * in Item.c.
- */
-#define ZN_CONFIG_END 0
-#define ZN_CONFIG_BOOL 1
-#define ZN_CONFIG_BITMAP 2
-#define ZN_CONFIG_BITMAP_LIST 3
-#define ZN_CONFIG_STRING 4
-#define ZN_CONFIG_FONT 5
-#define ZN_CONFIG_EDGE_LIST 6
-#define ZN_CONFIG_RELIEF 7
-#define ZN_CONFIG_DIM 8
-#define ZN_CONFIG_PRI 9
-#define ZN_CONFIG_ALIGNMENT 10
-#define ZN_CONFIG_AUTO_ALIGNMENT 11
-#define ZN_CONFIG_LINE_END 12
-#define ZN_CONFIG_LABEL_FORMAT 13
-#define ZN_CONFIG_LINE_STYLE 14
-#define ZN_CONFIG_LINE_SHAPE 15
-#define ZN_CONFIG_ITEM 16
-#define ZN_CONFIG_ANGLE 17
-#define ZN_CONFIG_INT 18
-#define ZN_CONFIG_UINT 19
-#define ZN_CONFIG_POINT 20
-#define ZN_CONFIG_ANCHOR 21
-#define ZN_CONFIG_TAG_LIST 22
-#define ZN_CONFIG_MAP_INFO 23
-#define ZN_CONFIG_IMAGE 24
-#define ZN_CONFIG_LEADER_ANCHORS 25
-#define ZN_CONFIG_JOIN_STYLE 26
-#define ZN_CONFIG_CAP_STYLE 27
-#define ZN_CONFIG_GRADIENT 28
-#define ZN_CONFIG_GRADIENT_LIST 29
-#define ZN_CONFIG_WINDOW 30
-#define ZN_CONFIG_ALPHA 31
-#define ZN_CONFIG_FILL_RULE 32
-#define ZN_CONFIG_SHORT 33
-#define ZN_CONFIG_USHORT 34
-#define ZN_CONFIG_CHAR 35
-#define ZN_CONFIG_UCHAR 36
-
-#define ZN_DRAW_FLAG 1 << 0
-#define ZN_COORDS_FLAG 1 << 1
-#define ZN_TRANSFO_FLAG 1 << 2
-#define ZN_REPICK_FLAG 1 << 3
-#define ZN_BORDER_FLAG 1 << 4
-#define ZN_CLFC_FLAG 1 << 5 /* Clear Label Format Cache. */
-#define ZN_IMAGE_FLAG 1 << 6 /* Update image pointer. */
-#define ZN_VIS_FLAG 1 << 7 /* Visibility has changed. */
-#define ZN_MOVED_FLAG 1 << 8 /* Item has moved. */
-#define ZN_ITEM_FLAG 1 << 9 /* Signal a change in an item type attribute. */
-#define ZN_MAP_INFO_FLAG 1 << 10/* Update mapinfo pointer. */
-#define ZN_LAYOUT_FLAG 1 << 11 /* A layout need update. */
-#define ZN_POLAR_FLAG 1 << 12 /* Signal a cartesian to polar change. */
-#define ZN_CARTESIAN_FLAG 1 << 13 /* Signal a polar to cartesian change. */
-#define ZN_TILE_FLAG 1 << 14 /* Update tile pointer. */
-#define ZN_WINDOW_FLAG 1 << 15 /* Signal a change in a window type attribute. */
-
-
-/*
- * This constant marks a non existant item
-*/
-#define ZN_NO_ITEM NULL
-
-/*
- * Constants for item parts. The item indexable parts (named fields) are coded
- * as positive or null integers. The item specific parts (not indexable) are
- * coded as negatives beginning at -2 up to -9 which is the current limit. The
- * -1 value is reserved to indicate no part.
- */
-#define ZnPartToBit(part) (1 << (ABS(part)-2))
-#define ZN_NO_PART -1
-
-/*
- * Some flags macros.
- */
-#define ISSET(var, mask) ((var) & (mask))
-#define ISCLEAR(var, mask) (((var) & (mask)) == 0)
-#define SET(var,mask) ((var) |= (mask))
-#define CLEAR(var, mask) ((var) &= ~(mask))
-#define ASSIGN(var, mask, bool) ((bool) ? SET((var), (mask)) : CLEAR((var), (mask)))
-
-/*
- * Item flags values.
- */
-#define ZN_VISIBLE_BIT (1<<0)
-#define ZN_SENSITIVE_BIT (1<<1)
-#define ZN_UPDATE_DEPENDENT_BIT (1<<2)
-#define ZN_COMPOSE_SCALE_BIT (1<<3)
-#define ZN_COMPOSE_ROTATION_BIT (1<<4)
-#define ZN_COMPOSE_ALPHA_BIT (1<<5)
-/*
- * Must be kept one greater than the last flag shift count.
- */
-#define ZN_PRIVATE_FLAGS_OFFSET 6
-
-
-/*
- * Operator constants for the coord method.
- */
-#define ZN_COORDS_READ 0
-#define ZN_COORDS_READ_ALL 1
-#define ZN_COORDS_REPLACE 2
-#define ZN_COORDS_REPLACE_ALL 3
-#define ZN_COORDS_ADD 4
-#define ZN_COORDS_ADD_LAST 5
-#define ZN_COORDS_REMOVE 6
-
-
-struct _ZnWInfo;
-struct _ZnTransfo;
-
-/*
- * Item record header --
- */
-typedef struct _ZnItemStruct {
- /* Private data */
- unsigned int id;
- ZnList tags;
- struct _ZnWInfo *wi; /* The widget this item is on */
- struct _ZnItemClassStruct *class; /* item class */
- struct _ZnItemStruct *previous; /* previous item in group list */
- struct _ZnItemStruct *next; /* next item in group list */
- struct _ZnItemStruct *parent;
- ZnBBox item_bounding_box; /* device item bounding box */
-
- /* Common attributes */
- unsigned short flags;
- unsigned short part_sensitive; /* Currently limited to 16 parts per item */
- unsigned short inv_flags;
- unsigned short priority;
- struct _ZnTransfo *transfo;
- struct _ZnItemStruct *connected_item; /* Item this item is connected to */
-#ifdef GL
-#ifdef GL_LIST
- GLuint gl_list; /* Display list storing the item graphics */
-#endif
-#endif
-} ZnItemStruct, *ZnItem;
-
-typedef struct _ZnToAreaStruct {
- Tk_Uid tag_uid;
- ZnBool enclosed;
- ZnItem in_group;
- ZnBool report;
- ZnBool recursive;
- ZnBool override_atomic;
- ZnBBox *area;
-} ZnToAreaStruct, *ZnToArea;
-
-typedef struct _ZnPickStruct {
- int aperture;
- ZnItem in_group;
- ZnItem start_item;
- ZnBool recursive;
- ZnBool override_atomic;
- ZnPoint *point;
- ZnItem a_item;
- int a_part;
-} ZnPickStruct, *ZnPick;
-
-
-/*
- * Item class record --
- */
-typedef int (*ZnItemInitMethod)(ZnItem item, int *argc, Tcl_Obj *CONST *args[]);
-typedef int (*ZnItemConfigureMethod)(ZnItem item, int argc, Tcl_Obj *CONST args[],
- int *flags);
-typedef int (*ZnItemQueryMethod)(ZnItem item, int argc, Tcl_Obj *CONST args[]);
-typedef void (*ZnItemCloneMethod)(ZnItem item);
-typedef void (*ZnItemDestroyMethod)(ZnItem item);
-typedef void (*ZnItemDrawMethod)(ZnItem item);
-typedef void (*ZnItemRenderMethod)(ZnItem item);
-typedef void (*ZnItemComputeCoordinatesMethod)(ZnItem item, ZnBool force);
-typedef int (*ZnItemToAreaMethod)(ZnItem item, ZnToArea ta);
-typedef ZnReal (*ZnItemPickMethod)(ZnItem item, ZnPick ps);
-typedef ZnBool (*ZnItemIsSensitiveMethod)(ZnItem item, int part);
-typedef struct _ZnFieldSetStruct* (*ZnItemGetFieldSetMethod)(ZnItem item);
-typedef int (*ZnItemContourMethod)(ZnItem item, int cmd, int index, ZnPoly *poly);
-typedef void (*ZnItemPickVertexMethod)(ZnItem item, ZnPoint *p, int *contour,
- int *vertex, int *o_vertex);
-typedef void (*ZnItemGetAnchorMethod)(ZnItem item, Tk_Anchor anchor, ZnPoint *p);
-typedef ZnBool (*ZnItemGetClipVerticesMethod)(ZnItem item, ZnTriStrip *tristrip);
-typedef ZnBool (*ZnItemGetContoursMethod)(ZnItem item, ZnPoly *poly);
-typedef int (*ZnItemCoordsMethod)(ZnItem item, int contour, int index, int cmd,
- ZnPoint **points, char **controls, unsigned int *num_points);
-typedef void (*ZnItemInsertCharsMethod)(ZnItem item, int field, int *index,
- char *chars);
-typedef void (*ZnItemDeleteCharsMethod)(ZnItem item, int field, int *first,
- int *last);
-typedef void (*ZnItemCursorMethod)(ZnItem item, int field, int index);
-typedef int (*ZnItemIndexMethod)(ZnItem item, int field, Tcl_Obj *index_spec,
- int *index);
-typedef int (*ZnItemPartMethod)(ZnItem item, Tcl_Obj **part_spec, int *part);
-typedef int (*ZnItemSelectionMethod)(ZnItem item, int field, int offset,
- char *chars, int max_chars);
-typedef int (*ZnItemPostScriptMethod)(ZnItem item, ZnBool prepass, ZnBBox *area);
-
-
-typedef void *ZnItemClassId;
-
-#define ZN_CLASS_HAS_ANCHORS (1<<0)
-#define ZN_CLASS_ONE_COORD (1<<1)
-
-typedef struct _ZnItemClassStruct {
- char *name;
- unsigned int size;
- ZnAttrConfig *attr_desc;
- unsigned int num_parts; /* 0 if no special parts, else
- * gives how many parts exist. */
- int flags; /* HAS_ANCHORS, ONE_COORD */
- int pos_offset; /* Offset of -position attrib, */
- /* if any, -1 otherwise. */
- ZnItemInitMethod Init;
- ZnItemCloneMethod Clone;
- ZnItemDestroyMethod Destroy;
- ZnItemConfigureMethod Configure;
- ZnItemQueryMethod Query;
- ZnItemGetFieldSetMethod GetFieldSet;
- ZnItemGetAnchorMethod GetAnchor;
- ZnItemGetClipVerticesMethod GetClipVertices;
- ZnItemGetContoursMethod GetContours;
- ZnItemCoordsMethod Coords;
- ZnItemInsertCharsMethod InsertChars;
- ZnItemDeleteCharsMethod DeleteChars;
- ZnItemCursorMethod Cursor;
- ZnItemIndexMethod Index;
- ZnItemPartMethod Part;
- ZnItemSelectionMethod Selection;
- ZnItemContourMethod Contour;
- ZnItemComputeCoordinatesMethod ComputeCoordinates;
- ZnItemToAreaMethod ToArea;
- ZnItemDrawMethod Draw;
- ZnItemRenderMethod Render;
- ZnItemIsSensitiveMethod IsSensitive;
- ZnItemPickMethod Pick;
- ZnItemPickVertexMethod PickVertex;
- ZnItemPostScriptMethod PostScript;
-} ZnItemClassStruct, *ZnItemClass;
-
-
-/*
- **********************************************************************************
- *
- * Generic methods for all items.
- *
- **********************************************************************************
- */
-extern struct _ZnITEM {
- ZnItem (*CloneItem)(ZnItem model);
- void (*DestroyItem)(ZnItem item);
- int (*ConfigureItem)(ZnItem item, int field, int argc, Tcl_Obj *CONST args[],
- ZnBool init);
- int (*QueryItem)(ZnItem item, int field, int argc, Tcl_Obj *CONST args[]);
- void (*InsertItem)(ZnItem item, ZnItem group, ZnItem mark_item, ZnBool before);
- void (*UpdateItemPriority)(ZnItem item, ZnItem mark_item, ZnBool before);
- void (*UpdateItemDependency)(ZnItem item, ZnItem old_connection);
- void (*ExtractItem)(ZnItem item);
- void (*SetId)(ZnItem item);
- void (*FreeId)(ZnItem item);
- void (*AddTag)(ZnItem item, Tk_Uid tag);
- void (*RemoveTag)(ZnItem item, Tk_Uid tag);
- void (*FreeTags)(ZnItem item);
- ZnBool (*HasTag)(ZnItem item, Tk_Uid tag);
- void (*ResetTransfo)(ZnItem item);
- void (*SetTransfo)(ZnItem item, struct _ZnTransfo *t);
- void (*TranslateItem)(ZnItem item, ZnReal tx, ZnReal ty, ZnBool abs);
- void (*ScaleItem)(ZnItem item, ZnReal sx, ZnReal sy, ZnPoint *p);
- void (*SkewItem)(ZnItem item, ZnReal x_skew, ZnReal y_skew);
- void (*RotateItem)(ZnItem item, ZnReal angle, ZnBool deg, ZnPoint *p);
- void (*Invalidate)(ZnItem item, int reason);
- void (*InvalidateItems)(ZnItem group, ZnItemClass item_class);
- void (*GetItemTransform)(ZnItem item, struct _ZnTransfo *t);
-} ZnITEM;
-
-
-/*
- **********************************************************************************
- *
- * Methods defined in Item.c useful for writing items.
- *
- **********************************************************************************
- */
-void ZnItemInit();
-ZnItem ZnCreateItem(struct _ZnWInfo *wi, ZnItemClass item_class,
- int *argc, Tcl_Obj *CONST *args[]);
-void ZnAddItemClass(ZnItemClass class);
-ZnItemClass ZnLookupItemClass(char *class_name);
-ZnList ZnItemClassList();
-int ZnConfigureAttributes(struct _ZnWInfo *wi, ZnItem item, void *record,
- ZnAttrConfig *attr_desc, int argc, Tcl_Obj *CONST args[],
- int *flags);
-int ZnAttributesInfo(Tcl_Interp *interp, void *record,
- ZnAttrConfig *attr_desc, int argc, Tcl_Obj *CONST args[]);
-int ZnQueryAttribute(Tcl_Interp *interp, void *record, ZnAttrConfig *attr_desc,
- Tcl_Obj *attr_name);
-void ZnInitTransformStack(struct _ZnWInfo *wi);
-void ZnFreeTransformStack(struct _ZnWInfo *wi);
-void ZnResetTransformStack(struct _ZnWInfo *wi);
-void ZnPushTransform(struct _ZnWInfo *wi, struct _ZnTransfo *transfo,
- ZnPoint *pos, ZnBool compose_scale, ZnBool compose_rot);
-void ZnPopTransform(struct _ZnWInfo *wi);
-void ZnInitClipStack(struct _ZnWInfo *wi);
-void ZnFreeClipStack(struct _ZnWInfo *wi);
-void ZnResetClipStack(struct _ZnWInfo *wi);
-void ZnPushClip(struct _ZnWInfo *wi, ZnTriStrip *tristrip, ZnBool simple,
- ZnBool set_gc);
-void ZnPopClip(struct _ZnWInfo *wi, ZnBool set_gc);
-ZnBool ZnCurrentClip(struct _ZnWInfo *wi, TkRegion *reg, ZnBBox **clip_box,
- ZnBool *simple);
-void ZnUpdateItemImage(void *client_data);
-
-
-extern ZnItemClassId ZnArc;
-extern ZnItemClassId ZnMap;
-extern ZnItemClassId ZnTabular;
-extern ZnItemClassId ZnCurve;
-extern ZnItemClassId ZnBezier;
-extern ZnItemClassId ZnTriangles;
-extern ZnItemClassId ZnRectangle;
-extern ZnItemClassId ZnReticle;
-extern ZnItemClassId ZnTrack;
-extern ZnItemClassId ZnWayPoint;
-extern ZnItemClassId ZnGroup;
-extern ZnItemClassId ZnIcon;
-extern ZnItemClassId ZnText;
-extern ZnItemClassId ZnWindow;
-
-
-#endif /* _Item_h */
diff --git a/generic/List.c b/generic/List.c
deleted file mode 100644
index 99462aa..0000000
--- a/generic/List.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * List.c -- Implementation of list module.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Tue Mar 15 17:18:17 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-/*
- **********************************************************************************
- *
- * This modules exports the following functions:
- * - ZnListNew
- * - ZnListDuplicate
- * - ZnListEmpty
- * - ZnListFromArray
- * - ZnListArray
- * - ZnListFree
- * - ZnListSize
- * - ZnListAssertSize
- * - ZnListAdd
- * - ZnListAt
- * - ZnListAtPut
- * - ZnListDelete
- * - ZnListTruncate
- * - ZnListDetect
- * - ZnListDo
- *
- * To appear soon:
- * - ZnListCollect
- * - ZnListReject
- *
- * And the following variables:
- *
- **********************************************************************************
- */
-
-/*
- **********************************************************************************
- *
- * Included files
- *
- **********************************************************************************
- */
-
-#include "Types.h"
-#include "List.h"
-
-#include <stddef.h>
-#include <memory.h>
-#include <stdlib.h>
-
-
-/*
- **********************************************************************************
- *
- * Constants
- *
- **********************************************************************************
- */
-static const char rcs_id[]="$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-#define MAX_CHUNCK_SIZE 1024
-
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-
-/*
- **********************************************************************************
- *
- * New types
- *
- **********************************************************************************
- */
-
-typedef struct {
- char *list;
- unsigned long elem_size;
- unsigned long alloc_size;
- unsigned long used_size;
-} _ZnList;
-
-
-/*
- **********************************************************************************
- *
- * GrowIfNeeded --
- * Enlarge a list so that it has min_size available. Take care of
- * static storage.
- *
- **********************************************************************************
- */
-
-static void
-GrowIfNeeded(_ZnList *list,
- unsigned int min_size)
-{
- if (list->used_size+min_size <= list->alloc_size) {
- return;
- }
-
- if (list->alloc_size == 0) {
- if (list->list == NULL) {
- /* Normal case if we have created a zero sized list */
- list->alloc_size = min_size;
- list->list = ZnMalloc(list->alloc_size*list->elem_size);
- }
- else {
- /* Case of a list made by ZnListFromArray. If we try to make
- it grow we need to reallocate and copy. */
- char *new_list;
-
- list->alloc_size = list->used_size+min_size;
- new_list = ZnMalloc(list->alloc_size*list->elem_size);
- memcpy(new_list,
- list->list,
- list->used_size*list->elem_size);
- list->list = new_list;
- }
- }
- else {
- list->alloc_size = MAX(MIN(list->alloc_size*2, MAX_CHUNCK_SIZE),
- list->alloc_size+min_size);
-
- list->list = ZnRealloc(list->list,
- list->alloc_size*list->elem_size);
- }
-
- memset(list->list+(list->used_size*list->elem_size),
- 0,
- (list->alloc_size-list->used_size)*list->elem_size);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListNew --
- * Return a new empty list 'initial_size' large.
- *
- **********************************************************************************
- */
-
-ZnList
-ZnListNew(unsigned int initial_size,
- unsigned int element_size)
-{
- _ZnList *new_list;
-
- if (element_size == 0) {
- element_size = 1;
- }
-
- new_list = ZnMalloc(sizeof(_ZnList));
-
- new_list->alloc_size = initial_size;
- new_list->used_size = 0;
- new_list->elem_size = element_size;
-
- if (initial_size) {
- unsigned long size = new_list->alloc_size*new_list->elem_size;
-
- new_list->list = ZnMalloc(size);
- memset(new_list->list, 0, size);
- }
- else {
- new_list->list = NULL;
- }
-
- return (ZnList) new_list;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListDuplicate --
- * Return a copy of the list given as parameter.
- *
- **********************************************************************************
- */
-
-ZnList
-ZnListDuplicate(ZnList list)
-{
- _ZnList *cur_list = (_ZnList *) list;
- _ZnList *new_list;
-
- new_list = ZnMalloc(sizeof(_ZnList));
-
- new_list->alloc_size = cur_list->alloc_size == 0 ? cur_list->used_size :
- cur_list->alloc_size;
- new_list->used_size = cur_list->used_size;
- new_list->elem_size = cur_list->elem_size;
-
- if (new_list->alloc_size) {
- unsigned long used_size = new_list->used_size*new_list->elem_size;
- unsigned long size = new_list->alloc_size*new_list->elem_size;
-
- new_list->list = ZnMalloc(size);
-
- if (used_size) {
- memcpy(new_list->list, cur_list->list, used_size);
- }
-
- memset(new_list->list + used_size, 0, size - used_size);
- }
- else {
- new_list->list = NULL;
- }
-
- return (ZnList) new_list;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListEmpty --
- * Clear out a list, kkeping its allocated size.
- *
- **********************************************************************************
- */
-
-void
-ZnListEmpty(ZnList list)
-{
- _ZnList *cur_list = (_ZnList *) list;
-
- cur_list->used_size = 0;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListFromArray --
- * Return a list filled from the given array.
- *
- **********************************************************************************
- */
-
-ZnList
-ZnListFromArray(void *array,
- unsigned int array_size,
- unsigned int element_size)
-{
- _ZnList *new_list;
-
- new_list = (_ZnList *) ZnListNew(0, element_size);
- new_list->list = array;
- new_list->used_size = array_size;
- return (ZnList) new_list;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListArray --
- * Return a pointer to the array containing the list.
- *
- **********************************************************************************
- */
-
-void *
-ZnListArray(ZnList list)
-{
- _ZnList *cur_list = (_ZnList *) list;
-
- return (void *) cur_list->list;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListFree --
- * Delete a list and free its memory. The entries
- * still in the list are lost but no further deallocation
- * is attempted.
- *
- **********************************************************************************
- */
-
-void
-ZnListFree(ZnList list)
-{
- _ZnList *cur_list = (_ZnList *) list;
-
- if (cur_list->list != NULL && cur_list->alloc_size != 0) {
- ZnFree(cur_list->list);
- }
-
- ZnFree(cur_list);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListSize --
- * Return the current number of entries kept in list.
- *
- **********************************************************************************
- */
-
-unsigned int
-ZnListSize(ZnList list)
-{
- return ((_ZnList *)list)->used_size;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListAssertSize --
- * Set the list length to size.
- *
- **********************************************************************************
- */
-
-void
-ZnListAssertSize(ZnList list,
- unsigned int size)
-{
- _ZnList *cur_list = (_ZnList *) list;
-
- if (cur_list->used_size < size) {
- GrowIfNeeded(cur_list, size - cur_list->used_size);
- }
- cur_list->used_size = size;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListCopy --
- * Destructively copy 'from' into 'to' starting at the first
- * position. It is the same as saying ZnListEmpty and then
- * ZnListAppend.
- *
- **********************************************************************************
- */
-
-void
-ZnListCopy(ZnList to,
- ZnList from)
-{
- _ZnList *to_list = (_ZnList *) to;
- _ZnList *from_list = (_ZnList *) from;
-
- if (from_list->elem_size != to_list->elem_size) {
- return;
- }
-
- to_list->used_size = 0;
- GrowIfNeeded(to_list, from_list->used_size);
- memcpy(to_list->list,
- from_list->list,
- from_list->used_size*from_list->elem_size);
- to_list->used_size = from_list->used_size;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListAppend --
- * Append 'from' at the end of 'to' which is enlarged as needed.
- *
- **********************************************************************************
- */
-
-void
-ZnListAppend(ZnList to,
- ZnList from)
-{
- _ZnList *to_list = (_ZnList *) to;
- _ZnList *from_list = (_ZnList *) from;
-
- if (from_list->elem_size != to_list->elem_size) {
- return;
- }
-
- GrowIfNeeded(to_list, from_list->used_size);
- memcpy(to_list->list+(to_list->used_size*to_list->elem_size),
- from_list->list,
- from_list->used_size*from_list->elem_size);
- to_list->used_size += from_list->used_size;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListAdd --
- * Add a new entry 'value' in the list before
- * 'index'. 'index' can be the position of a
- * previous entry or the special values ZnListHead,
- * ZnListTail. The entries have positions
- * starting at 0.
- *
- **********************************************************************************
- */
-
-void
-ZnListAdd(ZnList list,
- void *value,
- unsigned int index)
-{
- _ZnList *cur_list = (_ZnList *) list;
- int i;
-
- GrowIfNeeded(cur_list, 1);
-
- if (index < cur_list->used_size) {
- for (i = cur_list->used_size-1; i >= (int) index; i--) {
- memcpy(cur_list->list+((i+1)*cur_list->elem_size),
- cur_list->list+(i*cur_list->elem_size),
- cur_list->elem_size);
- }
- }
- else if (index > cur_list->used_size) {
- index = cur_list->used_size;
- }
-
- memcpy(cur_list->list+(index*cur_list->elem_size),
- (char *) value,
- cur_list->elem_size);
-
- (cur_list->used_size)++;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListAt --
- * Return the entry at 'index'. Indices start at 0.
- * Indices out of the current range are constrained
- * to fit in the range.
- *
- **********************************************************************************
- */
-
-void *
-ZnListAt(ZnList list,
- unsigned int index)
-{
- if (!((_ZnList *) list)->used_size) {
- return NULL;
- }
- if (index >= ((_ZnList *) list)->used_size) {
- index = ((_ZnList *) list)->used_size - 1;
- }
-
- return (void *) (((_ZnList *) list)->list+(index*((_ZnList *) list)->elem_size));
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListAtPut --
- * Set the entry at 'index' to 'value'.
- * Indices start at 0. Indices out of the current
- * range are constrained to fit in the range.
- *
- **********************************************************************************
- */
-
-void
-ZnListAtPut(ZnList list,
- void *value,
- unsigned int index)
-{
- if (!((_ZnList *) list)->used_size) {
- return;
- }
- if (index >= ((_ZnList *) list)->used_size) {
- index = ((_ZnList *) list)->used_size - 1;
- }
-
- memcpy(((_ZnList *) list)->list+(index*((_ZnList *) list)->elem_size),
- (char *) value,
- ((_ZnList *) list)->elem_size);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnListDelete --
- * Suppress the entry matching value, searching from position
- * 'index'. If value is NULL suppress entry at index.
- *
- **********************************************************************************
- */
-
-void
-ZnListDelete(ZnList list,
- unsigned int index)
-{
- _ZnList *cur_list = (_ZnList *) list;
- unsigned int i;
-
- if (!((_ZnList *) list)->used_size) {
- return;
- }
- if (index >= ((_ZnList *) list)->used_size) {
- index = ((_ZnList *) list)->used_size - 1;
- }
-
- for (i = index; i < cur_list->used_size-1; i++) {
- memcpy(cur_list->list+(i*cur_list->elem_size),
- cur_list->list+((i+1)*cur_list->elem_size),
- cur_list->elem_size);
- }
- (cur_list->used_size)--;
-}
-
-/*
- **********************************************************************************
- *
- * ZnListTruncate --
- * Suppress the entries from position 'index' inclusive to the end.
- *
- **********************************************************************************
- */
-
-void
-ZnListTruncate(ZnList list,
- unsigned int index)
-{
- _ZnList *cur_list = (_ZnList *) list;
-
- if (index >= ((_ZnList *) list)->used_size) {
- return;
- }
-
- cur_list->used_size = index;
-}
diff --git a/generic/List.h b/generic/List.h
deleted file mode 100644
index 5fdf0bd..0000000
--- a/generic/List.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * List.h -- Header of list module.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Tue Mar 15 17:24:51 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _List_h
-#define _List_h
-
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-
-#define ZnListHead 0
-#define ZnListTail (~(1 << ((8*sizeof(int)) - 1)))
-
-
-typedef void *ZnList;
-
-
-ZnList ZnListNew(unsigned int /* initial_size */,
- unsigned int /* element_size */);
-ZnList ZnListDuplicate(ZnList /* list */);
-void ZnListEmpty(ZnList /* list */);
-ZnList ZnListFromArray(void * /* array */,
- unsigned int /* array_size */,
- unsigned int /* element_size */);
-void *ZnListArray(ZnList /* list */);
-void ZnListFree(ZnList /* list */);
-unsigned int ZnListSize(ZnList /* list */);
-void ZnListAssertSize(ZnList /* list */,
- unsigned int /* size */);
-void ZnListCopy(ZnList /* to */,
- ZnList /* from */);
-void ZnListAppend(ZnList /* to */,
- ZnList /* from */);
-void ZnListAdd(ZnList /* list */,
- void * /* value */,
- unsigned int /* index */);
-void *ZnListAt(ZnList /* list */,
- unsigned int /* index */);
-void ZnListAtPut(ZnList /* list */,
- void * /* value */,
- unsigned int /* index */);
-void ZnListDelete(ZnList /* list */,
- unsigned int /* index */);
-void ZnListTruncate(ZnList /* list */,
- unsigned int /* index */);
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _List_h */
diff --git a/generic/Map.c b/generic/Map.c
deleted file mode 100644
index cba3d14..0000000
--- a/generic/Map.c
+++ /dev/null
@@ -1,1611 +0,0 @@
-/*
- * Map.c -- Implementation of Map item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "MapInfo.h"
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-#include "Image.h"
-
-#include <memory.h>
-#include <stdio.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- **********************************************************************************
- *
- * Specific Map item record
- *
- **********************************************************************************
- */
-
-typedef struct _MapItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnBool filled;
- ZnImage fill_pattern;
- ZnGradient *color;
- Tk_Font text_font; /* null value -> use zn_map_text_font */
- char *map_info_name;
- ZnList symbol_patterns;
-
- /* Private data */
- ZnMapInfoId map_info;
- ZnList vectors;
- ZnList dashed_vectors;
- ZnList dotted_vectors;
- ZnList mixed_vectors;
- ZnList arcs;
- ZnList dashed_arcs;
- ZnList dotted_arcs;
- ZnList mixed_arcs;
- ZnList marks;
- ZnList symbols;
- ZnList texts;
-#ifdef GL
- ZnTexFontInfo *tfi;
-#endif
-} MapItemStruct, *MapItem;
-
-
-static ZnAttrConfig map_attrs[] = {
- { ZN_CONFIG_GRADIENT, "-color", NULL,
- Tk_Offset(MapItemStruct, color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(MapItemStruct, filled), 1, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(MapItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_FONT, "-font", NULL,
- Tk_Offset(MapItemStruct, text_font), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_MAP_INFO, "-mapinfo", NULL,
- Tk_Offset(MapItemStruct, map_info_name), 0,
- ZN_COORDS_FLAG|ZN_MAP_INFO_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(MapItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(MapItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BITMAP_LIST, "-symbols", NULL,
- Tk_Offset(MapItemStruct, symbol_patterns), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(MapItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(MapItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-void
-UpdateMapInfo(ClientData client_data,
- ZnMapInfoId map_info)
-{
- ZnItem item = (ZnItem) client_data;
-
- /*printf("updating a map 'cause of a change in mapinfo\n");*/
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
-}
-
-
-static void
-FreeLists(MapItem map)
-{
- if (map->vectors) {
- ZnListFree(map->vectors);
- }
- map->vectors = NULL;
- if (map->dashed_vectors) {
- ZnListFree(map->dashed_vectors);
- }
- map->dashed_vectors = NULL;
- if (map->dotted_vectors) {
- ZnListFree(map->dotted_vectors);
- }
- map->dotted_vectors = NULL;
- if (map->mixed_vectors) {
- ZnListFree(map->mixed_vectors);
- }
- map->mixed_vectors = NULL;
-
- if (map->arcs) {
- ZnListFree(map->arcs);
- }
- map->arcs = NULL;
- if (map->dashed_arcs) {
- ZnListFree(map->dashed_arcs);
- }
- map->dashed_arcs = NULL;
- if (map->dotted_arcs) {
- ZnListFree(map->dotted_arcs);
- }
- map->dotted_arcs = NULL;
- if (map->mixed_arcs) {
- ZnListFree(map->mixed_arcs);
- }
- map->mixed_arcs = NULL;
-
- if (map->marks) {
- ZnListFree(map->marks);
- }
- map->marks = NULL;
-
- if (map->symbols) {
- ZnListFree(map->symbols);
- }
- map->symbols = NULL;
-
- if (map->texts) {
- ZnListFree(map->texts);
- }
- map->texts = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- MapItem map = (MapItem) item;
- ZnWInfo *wi = item->wi;
-
- SET(item->flags, ZN_VISIBLE_BIT);
- CLEAR(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->part_sensitive = 0;
- item->priority = 0;
- map->filled = False;
- map->fill_pattern = ZnUnspecifiedImage;
- map->symbol_patterns = NULL;
- map->color = ZnGetGradientByValue(wi->fore_color);
- map->text_font = Tk_GetFont(wi->interp, wi->win,
- Tk_NameOfFont(wi->map_text_font));
-#ifdef GL
- map->tfi = NULL;
-#endif
-
- map->map_info_name = NULL;
- map->map_info = NULL;
-
- map->vectors = NULL;
- map->dashed_vectors = NULL;
- map->dotted_vectors = NULL;
- map->mixed_vectors = NULL;
- map->arcs = NULL;
- map->dashed_arcs = NULL;
- map->dotted_arcs = NULL;
- map->mixed_arcs = NULL;
- map->marks = NULL;
- map->symbols = NULL;
- map->texts = NULL;
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-
-static void
-Clone(ZnItem item)
-{
- MapItem map = (MapItem) item;
- ZnWInfo *wi = item->wi;
-
- if (map->vectors) {
- map->vectors = ZnListDuplicate(map->vectors);
- }
- if (map->dashed_vectors) {
- map->dashed_vectors = ZnListDuplicate(map->dashed_vectors);
- }
- if (map->dotted_vectors) {
- map->dotted_vectors = ZnListDuplicate(map->dotted_vectors);
- }
- if (map->mixed_vectors) {
- map->mixed_vectors = ZnListDuplicate(map->mixed_vectors);
- }
-
- if (map->arcs) {
- map->arcs = ZnListDuplicate(map->arcs);
- }
- if (map->dashed_arcs) {
- map->dashed_arcs = ZnListDuplicate(map->dashed_arcs);
- }
- if (map->dotted_arcs) {
- map->dotted_arcs = ZnListDuplicate(map->dotted_arcs);
- }
- if (map->mixed_arcs) {
- map->mixed_arcs = ZnListDuplicate(map->mixed_arcs);
- }
-
- if (map->marks) {
- map->marks = ZnListDuplicate(map->marks);
- }
-
- if (map->symbols) {
- map->symbols = ZnListDuplicate(map->symbols);
- }
-
- if (map->texts) {
- map->texts = ZnListDuplicate(map->texts);
- }
-
- if (map->map_info_name) {
- char *text;
- text = ZnMalloc((strlen(map->map_info_name) + 1) * sizeof(char));
- strcpy(text, map->map_info_name);
- map->map_info_name = text;
- map->map_info = ZnGetMapInfo(wi->interp, map->map_info_name,
- UpdateMapInfo, (ClientData) map);
- }
-
- map->color = ZnGetGradientByValue(map->color);
- map->text_font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(map->text_font));
-#ifdef GL
- map->tfi = NULL;
-#endif
- if (map->fill_pattern != ZnUnspecifiedImage) {
- map->fill_pattern = ZnGetImageByValue(map->fill_pattern, NULL, NULL);
- }
- if (map->symbol_patterns) {
- ZnImage *pats, *new_pats;
- unsigned int i, num_pats;
-
- pats = ZnListArray(map->symbol_patterns);
- num_pats = ZnListSize(map->symbol_patterns);
- map->symbol_patterns = ZnListNew(num_pats, sizeof(ZnImage));
- new_pats = ZnListArray(map->symbol_patterns);
- for (i = 0; i < num_pats; i++) {
- new_pats[i] = ZnGetImageByValue(pats[i], NULL, NULL);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- * Free the Map storage.
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- MapItem map = (MapItem) item;
-
- FreeLists(map);
- ZnFreeGradient(map->color);
- Tk_FreeFont(map->text_font);
-#ifdef GL
- if (map->tfi) {
- ZnFreeTexFont(map->tfi);
- }
-#endif
- if (map->fill_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(map->fill_pattern, NULL, NULL);
- map->fill_pattern = ZnUnspecifiedImage;
- }
- if (map->symbol_patterns) {
- ZnImage *pats;
- int i, num_pats;
-
- pats = ZnListArray(map->symbol_patterns);
- num_pats = ZnListSize(map->symbol_patterns);
- for (i = 0; i < num_pats; i++) {
- if (pats[i] != ZnUnspecifiedImage) {
- ZnFreeImage(pats[i], NULL, NULL);
- }
- }
- ZnListFree(map->symbol_patterns);
- }
- if (map->map_info_name) {
- ZnFree(map->map_info_name);
- }
- if (map->map_info != NULL) {
- ZnFreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ZnWInfo *wi = item->wi;
- MapItem map = (MapItem) item;
-#ifdef GL
- Tk_Font old_font = map->text_font;
-#endif
-
- if (ZnConfigureAttributes(wi, item, item, map_attrs, argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
-#ifdef GL
- if (old_font != map->text_font) {
- if (map->tfi) {
- ZnFreeTexFont(map->tfi);
- map->tfi = NULL;
- }
- }
-#endif
- if (ISSET(*flags, ZN_MAP_INFO_FLAG)) {
- ZnMapInfoId map_info;
- ZnBool error = False;
-
- if (map->map_info_name) {
- map_info = ZnGetMapInfo(wi->interp, map->map_info_name,
- UpdateMapInfo, (ClientData) map);
- if (!map_info) {
- error = True;
- }
- }
- else {
- map_info = NULL;
- }
- if (!error) {
- if (map->map_info != NULL) {
- ZnFreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map);
- }
- map->map_info = map_info;
- }
- else {
- return TCL_ERROR;
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, map_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- MapItem map = (MapItem) item;
- ZnMapInfoId map_info;
- ZnMapInfoLineStyle line_style;
- ZnMapInfoTextStyle text_style;
- char symbol;
- char *text;
- unsigned int i, j, cnt;
- unsigned int num_points;
- unsigned int num_dashed_points;
- unsigned int num_dotted_points;
- unsigned int num_mixed_points;
- unsigned int num_arcs;
- unsigned int num_dashed_arcs;
- unsigned int num_dotted_arcs;
- unsigned int num_mixed_arcs;
- unsigned int num_marks;
- ZnPoint *vectors, *dashed_vectors, *dotted_vectors;
- ZnPoint *mixed_vectors, *marks;
- XArc *arcs, *dashed_arcs, *dotted_arcs, *mixed_arcs;
- ZnPoint *symbols, *texts;
- ZnPoint from, to, center;
- ZnPoint tmp_from, tmp_to;
- XArc arc;
- ZnBBox bbox, bbox_inter, zn_bbox;
- ZnPos x_from_w, y_from_w, x_to_w, y_to_w;
- ZnPos start_angle, extend;
- ZnDim radius_w, line_width;
- int radius;
- ZnPoint *new_marks;
- unsigned int n_new_marks;
- Tk_Font text_font;
- int sym_w2=0, sym_h2=0;
-
- ZnResetBBox(&item->item_bounding_box);
-
- if (map->map_info == NULL) {
- return;
- }
-
- zn_bbox.orig.x = zn_bbox.orig.y = 0;
- zn_bbox.corner.x = wi->width;
- zn_bbox.corner.y = wi->height;
-
- map_info = map->map_info;
-
- num_points = 0;
- num_dashed_points = 0;
- num_dotted_points = 0;
- num_mixed_points = 0;
- num_marks = 0;
- num_arcs = 0;
- num_dashed_arcs = 0;
- num_dotted_arcs = 0;
- num_mixed_arcs = 0;
-
- /*
- * Experimental code to help trap out of bounds
- * errors occuring as the result of improper use
- * of MapInfo/Map (i.e not doing a configure on
- * the MapInfo attribute after a reconfiguration
- * of the MapInfo. This version is more secure
- * but slower than the previous one.
- */
- /*
- * First discover how many component of each kind
- * there is in the MapInfo.
- */
- cnt = ZnMapInfoNumLines(map_info);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetLine(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL);
- switch (line_style) {
- case ZnMapInfoLineSimple:
- num_points += 2;
- break;
- case ZnMapInfoLineDashed:
- num_dashed_points += 2;
- break;
- case ZnMapInfoLineDotted:
- num_dotted_points += 2;
- break;
- case ZnMapInfoLineMixed:
- num_mixed_points += 2;
- break;
- case ZnMapInfoLineMarked:
- num_points += 2;
- ZnMapInfoGetMarks(map_info, i, NULL, &n_new_marks);
- num_marks += n_new_marks;
- break;
- }
- }
-
- cnt = ZnMapInfoNumTexts(map_info);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetText(map_info, i, NULL, &text_style, &line_style, NULL, NULL, NULL);
- if (text_style == ZnMapInfoUnderlinedText) {
- switch (line_style) {
- case ZnMapInfoLineSimple:
- case ZnMapInfoLineMarked:
- num_points += 2;
- break;
- case ZnMapInfoLineDotted:
- num_dotted_points += 2;
- break;
- case ZnMapInfoLineMixed:
- num_mixed_points += 2;
- break;
- case ZnMapInfoLineDashed:
- num_dashed_points += 2;
- break;
- }
- }
- }
-
- cnt = ZnMapInfoNumArcs(map_info);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetArc(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL, NULL);
- switch (line_style) {
- case ZnMapInfoLineSimple:
- case ZnMapInfoLineMarked:
- num_arcs += 2;
- break;
- case ZnMapInfoLineDotted:
- num_dotted_arcs += 2;
- break;
- case ZnMapInfoLineMixed:
- num_mixed_arcs += 2;
- break;
- case ZnMapInfoLineDashed:
- num_dashed_arcs += 2;
- break;
- }
- }
-
- /*
- * Make sure the various lists are large enough
- * to contain the computed amount of points.
- * Later we will cut them to take into account the
- * clipping and the filled attribute.
- */
- if (!map->vectors) {
- map->vectors = ZnListNew(num_points, sizeof(ZnPoint));
- }
- ZnListAssertSize(map->vectors, num_points);
- if (!map->dashed_vectors) {
- map->dashed_vectors = ZnListNew(num_dashed_points, sizeof(ZnPoint));
- }
- ZnListAssertSize(map->dashed_vectors, num_dashed_points);
- if (!map->dotted_vectors) {
- map->dotted_vectors = ZnListNew(num_dotted_points, sizeof(ZnPoint));
- }
- ZnListAssertSize(map->dotted_vectors, num_dotted_points);
- if (!map->mixed_vectors) {
- map->mixed_vectors = ZnListNew(num_mixed_points, sizeof(ZnPoint));
- }
- ZnListAssertSize(map->mixed_vectors, num_mixed_points);
- if (!map->arcs) {
- map->arcs = ZnListNew(num_arcs, sizeof(XArc));
- }
- ZnListAssertSize(map->arcs, num_arcs);
- if (!map->dashed_arcs) {
- map->dashed_arcs = ZnListNew(num_dashed_arcs, sizeof(XArc));
- }
- ZnListAssertSize(map->dashed_arcs, num_dashed_arcs);
- if (!map->dotted_arcs) {
- map->dotted_arcs = ZnListNew(num_dotted_arcs, sizeof(XArc));
- }
- ZnListAssertSize(map->dotted_arcs, num_dotted_arcs);
- if (!map->mixed_arcs) {
- map->mixed_arcs = ZnListNew(num_mixed_arcs, sizeof(XArc));
- }
- ZnListAssertSize(map->mixed_arcs, num_mixed_arcs);
- if (!map->marks) {
- map->marks = ZnListNew(num_marks, sizeof(ZnPoint));
- }
- ZnListAssertSize(map->marks, num_marks);
- if (!map->symbols) {
- map->symbols = ZnListNew(ZnMapInfoNumSymbols(map_info), sizeof(ZnPoint));
- }
- ZnListAssertSize(map->symbols, ZnMapInfoNumSymbols(map_info));
- if (!map->texts) {
- map->texts = ZnListNew(ZnMapInfoNumTexts(map_info), sizeof(ZnPoint));
- }
- ZnListAssertSize(map->texts, ZnMapInfoNumTexts(map_info));
-
- /*
- * Ask the pointers to the actual arrays.
- */
- vectors = (ZnPoint *) ZnListArray(map->vectors);
- dashed_vectors = (ZnPoint *) ZnListArray(map->dashed_vectors);
- dotted_vectors = (ZnPoint *) ZnListArray(map->dotted_vectors);
- mixed_vectors = (ZnPoint *) ZnListArray(map->mixed_vectors);
- arcs = (XArc *) ZnListArray(map->arcs);
- dashed_arcs = (XArc *) ZnListArray(map->dashed_arcs);
- dotted_arcs = (XArc *) ZnListArray(map->dotted_arcs);
- mixed_arcs = (XArc *) ZnListArray(map->mixed_arcs);
- marks = (ZnPoint *) ZnListArray(map->marks);
- symbols = (ZnPoint *) ZnListArray(map->symbols);
- texts = (ZnPoint *) ZnListArray(map->texts);
-
- if (num_marks && (wi->map_distance_symbol != ZnUnspecifiedImage)) {
- ZnSizeOfImage(wi->map_distance_symbol, &sym_w2, &sym_h2);
- sym_w2 = (sym_w2+1)/2;
- sym_h2 = (sym_h2+1)/2;
- }
- /*printf("Map: %d %d %d %d %d, texts: %d, symbols: %d\n", num_points, num_dashed_points, num_dotted_points,
- num_mixed_points, num_marks, ZnMapInfoNumTexts(map_info), ZnMapInfoNumSymbols(map_info));*/
- /*
- * Reset the counts of points to compute the actual
- * counts taking into account the clipping and the
- * filled attribute.
- */
- num_points = 0;
- num_dashed_points = 0;
- num_dotted_points = 0;
- num_mixed_points = 0;
- num_marks = 0;
- num_arcs = 0;
- num_dashed_arcs = 0;
- num_dotted_arcs = 0;
- num_mixed_arcs = 0;
-
- cnt = ZnMapInfoNumLines(map_info);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetLine(map_info, i, NULL, &line_style, &line_width,
- &x_from_w, &y_from_w, &x_to_w, &y_to_w);
-
- tmp_from.x = x_from_w;
- tmp_from.y = y_from_w;
- tmp_to.x = x_to_w;
- tmp_to.y = y_to_w;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &from);
- ZnTransformPoint(wi->current_transfo, &tmp_to, &to);
-
- /*
- * Skip zero length and outside segments.
- */
- if ((from.x == to.x) && (from.y == to.y)) {
- continue;
- }
-
- if (!map->filled) {
- if (ZnLineInBBox(&from, &to, &zn_bbox) < 0) {
- continue;
- }
- }
-
- switch (line_style) {
- case ZnMapInfoLineSimple:
- vectors[num_points] = from;
- num_points++;
- vectors[num_points] = to;
- num_points++;
- break;
- case ZnMapInfoLineDashed:
- if (!map->filled) {
- dashed_vectors[num_dashed_points] = from;
- num_dashed_points++;
- dashed_vectors[num_dashed_points] = to;
- num_dashed_points++;
- }
- break;
- case ZnMapInfoLineDotted:
- if (!map->filled) {
- dotted_vectors[num_dotted_points] = from;
- num_dotted_points++;
- dotted_vectors[num_dotted_points] = to;
- num_dotted_points++;
- }
- break;
- case ZnMapInfoLineMixed:
- if (!map->filled) {
- mixed_vectors[num_mixed_points] = from;
- num_mixed_points++;
- mixed_vectors[num_mixed_points] = to;
- num_mixed_points++;
- }
- break;
- case ZnMapInfoLineMarked:
- if (!map->filled) {
- vectors[num_points] = from;
- num_points++;
- vectors[num_points] = to;
- num_points++;
- if (wi->map_distance_symbol != ZnUnspecifiedImage) {
- ZnMapInfoGetMarks(map_info, i, &new_marks, &n_new_marks);
- for (j = 0; j < n_new_marks; j++) {
- /*
- * The transform can be put outside the loop when
- * MapInfo point type is modified to ZnPoint.
- * Will use then ZnTransformPoints.
- */
- tmp_from.x = new_marks[j].x;
- tmp_from.y = new_marks[j].y;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &marks[num_marks]);
- ZnAddPointToBBox(&item->item_bounding_box,
- marks[num_marks].x-sym_w2, marks[num_marks].y-sym_h2);
- ZnAddPointToBBox(&item->item_bounding_box,
- marks[num_marks].x+sym_w2, marks[num_marks].x+sym_h2);
- num_marks++;
- }
- }
- }
- break;
- }
- }
-
- cnt = ZnMapInfoNumArcs(map_info);
- for (i = 0; i < cnt; i++) {
- ZnPoint xp;
-
- ZnMapInfoGetArc(map_info, i, NULL, &line_style, &line_width,
- &x_from_w, &y_from_w, &radius_w, &start_angle, &extend);
-
- tmp_from.x = x_from_w;
- tmp_from.y = y_from_w;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &center);
- tmp_from.x += radius_w;
- tmp_from.y = 0;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &xp);
- radius = ((int) (xp.x - center.x));
-
- bbox.orig.x = center.x - radius;
- bbox.orig.y = center.y - radius;
- bbox.corner.x = bbox.orig.x + (2 * radius);
- bbox.corner.y = bbox.orig.y + (2 * radius);
-
- /*
- * Skip zero length and outside arcs.
- */
- if (!radius || !extend) {
- continue;
- }
-
- ZnIntersectBBox(&zn_bbox, &bbox, &bbox_inter);
- if (ZnIsEmptyBBox(&bbox_inter)) {
- continue;
- }
-
- arc.x = (int) (center.x - radius);
- arc.y = (int) (center.y - radius);
- arc.width = 2 * radius;
- arc.height = arc.width;
- arc.angle1 = ((unsigned short) start_angle) * 64;
- arc.angle2 = ((unsigned short) extend) * 64;
-
- switch (line_style) {
- case ZnMapInfoLineSimple:
- case ZnMapInfoLineMarked:
- arcs[num_arcs] = arc;
- num_arcs++;
-
- bbox.orig.x = arc.x;
- bbox.orig.y = arc.y;
- bbox.corner.x = bbox.orig.x + arc.width + 1;
- bbox.corner.y = bbox.orig.y + arc.height + 1;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- break;
- case ZnMapInfoLineDashed:
- if (!map->filled) {
- dashed_arcs[num_dashed_arcs] = arc;
- num_dashed_arcs++;
-
- bbox.orig.x = arc.x;
- bbox.orig.y = arc.y;
- bbox.corner.x = bbox.orig.x + arc.width + 1;
- bbox.corner.y = bbox.orig.y + arc.height + 1;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- break;
- case ZnMapInfoLineDotted:
- if (!map->filled) {
- dotted_arcs[num_dotted_arcs] = arc;
- num_dotted_arcs++;
-
- bbox.orig.x = arc.x;
- bbox.orig.y = arc.y;
- bbox.corner.x = bbox.orig.x + arc.width + 1;
- bbox.corner.y = bbox.orig.y + arc.height + 1;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- break;
- case ZnMapInfoLineMixed:
- if (!map->filled) {
- mixed_arcs[num_mixed_arcs] = arc;
- num_mixed_arcs++;
-
- bbox.orig.x = arc.x;
- bbox.orig.y = arc.y;
- bbox.corner.x = bbox.orig.x + arc.width + 1;
- bbox.corner.y = bbox.orig.y + arc.height + 1;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- break;
- }
- }
-
- /*
- * Truncate arc lists to the real size.
- */
- ZnListAssertSize(map->arcs, num_arcs);
- ZnListAssertSize(map->dashed_arcs, num_dashed_arcs);
- ZnListAssertSize(map->dotted_arcs, num_dotted_arcs);
- ZnListAssertSize(map->mixed_arcs, num_mixed_arcs);
-
- /* If map is filled, only the vectors description is valid. */
- if (!map->filled) {
- if (map->symbol_patterns) {
- ZnImage sym, *syms = ZnListArray(map->symbol_patterns);
- int num_syms = ZnListSize(map->symbol_patterns);
-
- cnt = ZnMapInfoNumSymbols(map_info);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetSymbol(map_info, i, NULL, &x_from_w, &y_from_w, &symbol);
- tmp_from.x = x_from_w;
- tmp_from.y = y_from_w;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &symbols[i]);
- sym = syms[symbol%num_syms];
- if (sym != ZnUnspecifiedImage) {
- ZnSizeOfImage(sym, &sym_w2, &sym_h2);
- sym_w2 = (sym_w2+1)/2;
- sym_h2 = (sym_h2+1)/2;
- ZnAddPointToBBox(&item->item_bounding_box,
- symbols[i].x-sym_w2, symbols[i].y-sym_h2);
- ZnAddPointToBBox(&item->item_bounding_box,
- symbols[i].x+sym_w2, symbols[i].y+sym_h2);
- }
- }
- ZnListAssertSize(map->symbols, cnt);
- }
-
- cnt = ZnMapInfoNumTexts(map_info);
- text_font = map->text_font ? map->text_font : wi->map_text_font;
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetText(map_info, i, NULL,
- &text_style, &line_style, &x_from_w, &y_from_w, &text);
- tmp_from.x = x_from_w;
- tmp_from.y = y_from_w;
- ZnTransformPoint(wi->current_transfo, &tmp_from, &texts[i]);
- ZnAddStringToBBox(&item->item_bounding_box, text, text_font,
- texts[i].x, texts[i].y);
-
- if (text_style == ZnMapInfoUnderlinedText) {
- ZnGetStringBBox(text, text_font, texts[i].x, texts[i].y, &bbox);
-
- from.x = bbox.orig.x;
- from.y = bbox.corner.y;
- to.x = bbox.corner.x;
- to.y = bbox.corner.y;
-
- switch (line_style) {
- case ZnMapInfoLineSimple:
- case ZnMapInfoLineMarked:
- vectors[num_points] = from;
- num_points++;
- vectors[num_points] = to;
- num_points++;
- break;
- case ZnMapInfoLineDashed:
- dashed_vectors[num_dashed_points] = from;
- num_dashed_points++;
- dashed_vectors[num_dashed_points] = to;
- num_dashed_points++;
- break;
- case ZnMapInfoLineDotted:
- dotted_vectors[num_dotted_points] = from;
- num_dotted_points++;
- dotted_vectors[num_dotted_points] = to;
- num_dotted_points++;
- break;
- case ZnMapInfoLineMixed:
- mixed_vectors[num_mixed_points] = from;
- num_mixed_points++;
- mixed_vectors[num_mixed_points] = to;
- num_mixed_points++;
- break;
- }
- }
- }
- ZnListAssertSize(map->texts, cnt);
- }
-
- /*
- * Truncate line lists to the real size.
- */
- ZnListAssertSize(map->vectors, num_points);
- ZnListAssertSize(map->dashed_vectors, num_dashed_points);
- ZnListAssertSize(map->dotted_vectors, num_dotted_points);
- ZnListAssertSize(map->mixed_vectors, num_mixed_points);
- ZnListAssertSize(map->marks, num_marks);
-
- ZnAddPointsToBBox(&item->item_bounding_box,
- ZnListArray(map->vectors), ZnListSize(map->vectors));
- ZnAddPointsToBBox(&item->item_bounding_box,
- ZnListArray(map->dashed_vectors), ZnListSize(map->dashed_vectors));
- ZnAddPointsToBBox(&item->item_bounding_box,
- ZnListArray(map->dotted_vectors), ZnListSize(map->dotted_vectors));
- ZnAddPointsToBBox(&item->item_bounding_box,
- ZnListArray(map->mixed_vectors), ZnListSize(map->mixed_vectors));
- item->item_bounding_box.orig.x -= 0.5;
- item->item_bounding_box.orig.y -= 0.5;
- item->item_bounding_box.corner.x += 0.5;
- item->item_bounding_box.corner.y += 0.5;
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- return -1;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- MapItem map = (MapItem) item;
- ZnMapInfoId map_info;
- ZnPoint *points;
- XPoint *xpoints;
- XArc *arcs;
- char *text;
- char tmp_str[] = ".";
- XGCValues values;
- unsigned int i, cnt;
- ZnDim line_width_w;
- int line_width;
-
- if (map->map_info == NULL) {
- return;
- }
-
- map_info = map->map_info;
-
- values.foreground = ZnGetGradientPixel(map->color, 0.0);
-
- if (map->filled) {
- if (ZnListSize(map->vectors) || ZnListSize(map->arcs)) {
- if (map->fill_pattern == ZnUnspecifiedImage) { /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
- }
- else { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(map->fill_pattern, wi->win);
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle | GCStipple | GCForeground, &values);
- }
-
- cnt = ZnListSize(map->vectors);
- if (cnt) {
- ZnListAssertSize(ZnWorkXPoints, cnt);
- xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
- points = (ZnPoint *) ZnListArray(map->vectors);
- for (i = 0; i < cnt; i++) {
- xpoints[i].x = (int) points[i].x;
- xpoints[i].y = (int) points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, (int) cnt,
- Nonconvex, CoordModeOrigin);
- }
-
- if (ZnListSize(map->arcs)) {
- arcs = ZnListArray(map->arcs);
- cnt = ZnListSize(map->arcs);
- for (i = 0; i < cnt; i++, arcs++) {
- XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
- arcs->x, arcs->y, arcs->width, arcs->height,
- arcs->angle1, arcs->angle2);
- }
- }
- }
- }
- else { /* Not filled */
-
- if (ZnListSize(map->vectors)) {
- ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle | GCLineWidth | GCForeground, &values);
-
- /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
- in releases R4 and older */
- /* XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
- (XSegment *) ZnListArray(map->vectors),
- ZnListSize(map->vectors)/2);*/
- cnt = ZnListSize(map->vectors);
- points = (ZnPoint *) ZnListArray(map->vectors);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL,
- NULL, NULL, NULL);
- line_width = (int) line_width_w;
- if (line_width != values.line_width) {
- values.line_width = line_width;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
- }
- /*printf("Dessin d'une ligne de %d %d à %d %d\n",
- (int)points[i].x, (int)points[i].y,
- (int)points[i+1].x, (int)points[i+1].y);*/
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) points[i].x,
- (int) points[i].y,
- (int) points[i+1].x,
- (int) points[i+1].y);
- }
- }
- }
-
- if (ZnListSize(map->dashed_vectors)) {
- ZnSetLineStyle(wi, ZN_LINE_DASHED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
-
- /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
- in releases R4 and older */
-/* XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
- (XSegment *) ZnListArray(map->dashed_vectors), ZnListSize(map->dashed_vectors)/2);*/
- cnt = ZnListSize(map->dashed_vectors);
- points = (ZnPoint *) ZnListArray(map->dashed_vectors);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
- line_width = (int) line_width_w;
- if (line_width != values.line_width) {
- values.line_width = line_width;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
- }
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) points[i].x,
- (int) points[i].y,
- (int) points[i+1].x,
- (int) points[i+1].y);
- }
- }
- }
-
- if (ZnListSize(map->dotted_vectors)) {
- ZnSetLineStyle(wi, ZN_LINE_DOTTED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle | GCLineWidth | GCForeground, &values);
-
- /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
- in releases R4 and older */
-/* XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
- (XSegment *) ZnListArray(map->dotted_vectors), ZnListSize(map->dotted_vectors)/2);*/
- cnt = ZnListSize(map->dotted_vectors);
- points = (ZnPoint *) ZnListArray(map->dotted_vectors);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
- line_width = (int) line_width_w;
- if (line_width != values.line_width) {
- values.line_width = line_width;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
- }
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) points[i].x,
- (int) points[i].y,
- (int) points[i+1].x,
- (int) points[i+1].y);
- }
- }
- }
-
- if (ZnListSize(map->mixed_vectors)) {
- ZnSetLineStyle(wi, ZN_LINE_MIXED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
-
- /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
- in releases R4 and older */
- /*XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
- (XSegment *) ZnListArray(map->mixed_vectors), ZnListSize(map->mixed_vectors)/2);*/
- cnt = ZnListSize(map->mixed_vectors);
- points = (ZnPoint *) ZnListArray(map->mixed_vectors);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
- line_width = (int) line_width_w;
- if (line_width != values.line_width) {
- values.line_width = line_width;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
- }
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) points[i].x,
- (int) points[i].y,
- (int) points[i+1].x,
- (int) points[i+1].y);
- }
- }
- }
-
- if (ZnListSize(map->arcs)) {
-
- ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- arcs = ZnListArray(map->arcs);
- cnt = ZnListSize(map->arcs);
- for (i = 0; i < cnt; i++, arcs++) {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- arcs->x, arcs->y, arcs->width, arcs->height,
- arcs->angle1, arcs->angle2);
- }
- }
-
- if (ZnListSize(map->dashed_arcs)) {
-
- ZnSetLineStyle(wi, ZN_LINE_DASHED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- arcs = ZnListArray(map->arcs);
- cnt = ZnListSize(map->arcs);
- for (i = 0; i < cnt; i++, arcs++) {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- arcs->x, arcs->y, arcs->width, arcs->height,
- arcs->angle1, arcs->angle2);
- }
- }
-
- if (ZnListSize(map->dotted_arcs)) {
-
- ZnSetLineStyle(wi, ZN_LINE_DOTTED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- arcs = ZnListArray(map->arcs);
- cnt = ZnListSize(map->arcs);
- for (i = 0; i < cnt; i++, arcs++) {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- arcs->x, arcs->y, arcs->width, arcs->height,
- arcs->angle1, arcs->angle2);
- }
- }
-
- if (ZnListSize(map->mixed_arcs)) {
-
- ZnSetLineStyle(wi, ZN_LINE_MIXED);
- values.fill_style = FillSolid;
- values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- arcs = ZnListArray(map->arcs);
- cnt = ZnListSize(map->arcs);
- for (i = 0; i < cnt; i++, arcs++) {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- arcs->x, arcs->y, arcs->width, arcs->height,
- arcs->angle1, arcs->angle2);
- }
- }
-
- if (ZnListSize(map->texts)) {
- /* For the Tk widget we don't have to bother with old
- * compatibility issues.
- */
- values.font = Tk_FontId(map->text_font);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle | GCFont | GCForeground, &values);
-
- cnt = ZnListSize(map->texts);
- points = (ZnPoint *) ZnListArray(map->texts);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetText(map_info, i, NULL, NULL, NULL, NULL, NULL, &text);
- Tk_DrawChars(wi->dpy, wi->draw_buffer, wi->gc,
- map->text_font, text, (int) strlen(text),
- (int) points[i].x, (int) points[i].y);
- }
- }
-
- if (ZnListSize(map->symbols) || ZnListSize(map->marks)) {
- int ox, oy;
- unsigned int w, h;
- ZnImage sym;
-
- values.fill_style = FillStippled;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle, &values);
-
- if (map->symbol_patterns) {
- ZnImage *syms = ZnListArray(map->symbol_patterns);
- int num_syms = ZnListSize(map->symbol_patterns);
-
- cnt = ZnListSize(map->symbols);
- points = ZnListArray(map->symbols);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetSymbol(map_info, i, NULL, NULL, NULL, &(tmp_str[0]));
- sym = syms[tmp_str[0]%num_syms];
- if (sym != ZnUnspecifiedImage) {
- ZnSizeOfImage(sym, &w ,&h);
- ox = ((int) points[i].x) - w/2;
- oy = ((int) points[i].y) - h/2;
- values.stipple = ZnImagePixmap(sym, wi->win);
- values.ts_x_origin = ox;
- values.ts_y_origin = oy;
- XChangeGC(wi->dpy, wi->gc,
- GCStipple|GCTileStipXOrigin|GCTileStipYOrigin, &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, ox, oy, w, h);
- }
- }
- }
-
- if (wi->map_distance_symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(wi->map_distance_symbol, &w, &h);
- cnt = ZnListSize(map->marks);
- points = ZnListArray(map->marks);
- values.stipple = ZnImagePixmap(wi->map_distance_symbol, wi->win);
- XChangeGC(wi->dpy, wi->gc, GCStipple, &values);
- for (i = 0; i < cnt; i++) {
- ox = ((int) points[i].x) - w/2;
- oy = ((int) points[i].y) - h/2;
- values.ts_x_origin = ox;
- values.ts_y_origin = oy;
- XChangeGC(wi->dpy, wi->gc, GCTileStipXOrigin|GCTileStipYOrigin, &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, ox, oy, w, h);
- }
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- MapItem map = (MapItem) item;
- ZnMapInfoId map_info;
- ZnPoint *points, p;
- char *text;
- char tmp_str[] = ".";
- unsigned int i, cnt;
- int w, h;
- XColor *color;
- GLfloat line_width;
- ZnDim new_width;
- unsigned short alpha;
-
- if (!map->map_info) {
- return;
- }
-
- map_info = map->map_info;
- color = ZnGetGradientColor(map->color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- if (map->filled) {
- if (ZnListSize(map->vectors) || ZnListSize(map->arcs)) {
- /* TODO_GL: Need to have a tesselated polygon then
- * fill it either using ZnRenderTile or solid.
- */
- if (map->fill_pattern != ZnUnspecifiedImage) {
- /* Fill stippled */
- }
- else {
- }
- }
- }
- else { /* Not filled */
- if (ZnListSize(map->vectors)) {
- line_width = 1.0;
- glLineWidth(line_width);
- ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
- cnt = ZnListSize(map->vectors);
- points = ZnListArray(map->vectors);
- glBegin(GL_LINES);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
- NULL, NULL, NULL);
- if (new_width != line_width) {
- line_width = (GLfloat)new_width;
- glLineWidth(line_width);
- }
- glVertex2d(points[i].x, points[i].y);
- glVertex2d(points[i+1].x, points[i+1].y);
- }
- }
- glEnd();
- }
- if (ZnListSize(map->dashed_vectors)) {
- line_width = 1.0;
- glLineWidth(line_width);
- ZnSetLineStyle(wi, ZN_LINE_DASHED);
- cnt = ZnListSize(map->dashed_vectors);
- points = ZnListArray(map->dashed_vectors);
- glBegin(GL_LINES);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
- NULL, NULL, NULL);
- if (new_width != line_width) {
- line_width = (GLfloat)new_width;
- glLineWidth(line_width);
- }
- glVertex2d(points[i].x, points[i].y);
- glVertex2d(points[i+1].x, points[i+1].y);
- }
- }
- glEnd();
- glDisable(GL_LINE_STIPPLE);
- }
- if (ZnListSize(map->dotted_vectors)) {
- line_width = 1.0;
- glLineWidth(line_width);
- ZnSetLineStyle(wi, ZN_LINE_DOTTED);
- cnt = ZnListSize(map->dotted_vectors);
- points = ZnListArray(map->dotted_vectors);
- glBegin(GL_LINES);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
- NULL, NULL, NULL);
- if (new_width != line_width) {
- line_width = (GLfloat)new_width;
- glLineWidth(line_width);
- }
- glVertex2d(points[i].x, points[i].y);
- glVertex2d(points[i+1].x, points[i+1].y);
- }
- }
- glEnd();
- glDisable(GL_LINE_STIPPLE);
- }
- if (ZnListSize(map->mixed_vectors)) {
- line_width = 1.0;
- glLineWidth(line_width);
- ZnSetLineStyle(wi, ZN_LINE_MIXED);
- cnt = ZnListSize(map->mixed_vectors);
- points = ZnListArray(map->mixed_vectors);
- glBegin(GL_LINES);
- for (i = 0; i < cnt; i += 2) {
- if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
- ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
- NULL, NULL, NULL);
- if (new_width != line_width) {
- line_width = (GLfloat)new_width;
- glLineWidth(line_width);
- }
- glVertex2d(points[i].x, points[i].y);
- glVertex2d(points[i+1].x, points[i+1].y);
- }
- }
- glEnd();
- glDisable(GL_LINE_STIPPLE);
- }
-
- if (ZnListSize(map->arcs)) {
- line_width = 1.0;
- glLineWidth(line_width);
- }
- if (ZnListSize(map->dashed_arcs)) {
- line_width = 1.0;
- glLineWidth(line_width);
- glLineStipple(1, 0xF0F0);
- glEnable(GL_LINE_STIPPLE);
- glDisable(GL_LINE_STIPPLE);
- }
- if (ZnListSize(map->dotted_arcs)) {
- line_width = 1.0;
- glLineWidth(line_width);
- glLineStipple(1, 0x18C3);
- glEnable(GL_LINE_STIPPLE);
- glDisable(GL_LINE_STIPPLE);
- }
- if (ZnListSize(map->mixed_arcs)) {
- line_width = 1.0;
- glLineWidth(line_width);
- glLineStipple(1, 0x27FF);
- glEnable(GL_LINE_STIPPLE);
- glDisable(GL_LINE_STIPPLE);
- }
-
- if (! map->tfi) {
- map->tfi = ZnGetTexFont(wi, map->text_font);
- }
- if (ZnListSize(map->texts) && map->tfi) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(map->tfi));
- cnt = ZnListSize(map->texts);
- points = ZnListArray(map->texts);
- for (i = 0; i < cnt; i++, points++) {
- glPushMatrix();
- ZnMapInfoGetText(map_info, i, NULL, NULL, NULL, NULL, NULL, &text);
- glTranslated(points->x, points->y, 0.0);
- ZnRenderString(map->tfi, text, strlen(text));
- glPopMatrix();
- }
- glDisable(GL_TEXTURE_2D);
- }
-
- if (map->symbol_patterns) {
- ZnImage sym, *syms = ZnListArray(map->symbol_patterns);
- int num_syms = ZnListSize(map->symbol_patterns);
-
- cnt = ZnListSize(map->symbols);
- points = ZnListArray(map->symbols);
- for (i = 0; i < cnt; i++) {
- ZnMapInfoGetSymbol(map_info, i, NULL, NULL, NULL, &(tmp_str[0]));
- sym = syms[tmp_str[0]%num_syms];
- if (sym != ZnUnspecifiedImage) {
- ZnSizeOfImage(sym, &w, &h);
- p.x = points[i].x-(w+1.0)/2.0;
- p.y = points[i].y-(h+1.0)/2.0;
- ZnRenderIcon(wi, sym, map->color, &p, True);
- }
- }
- }
-
- if (wi->map_distance_symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(wi->map_distance_symbol, &w, &h);
- cnt = ZnListSize(map->marks);
- points = ZnListArray(map->marks);
- for (i = 0; i < cnt; i++, points++) {
- p.x = points->x-(w+1)/2;
- p.y = points->y-(h+1)/2;
- ZnRenderIcon(wi, wi->map_distance_symbol, map->color, &p, True);
- }
- }
- }
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- * This is *NOT* correct but for now we will tell that we are
- * transparent even if we are solid filled.
- *
- * !!!! We need to say we are opaque at least if we are solid
- * filled. !!!!
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- return 1e40;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-
-static ZnItemClassStruct MAP_ITEM_CLASS = {
- "map",
- sizeof(MapItemStruct),
- map_attrs,
- 0, /* num_parts */
- 0, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- NULL, /* GetAnchor */
- NULL, /* GetClipVertices */
- NULL, /* GetContours */
- NULL,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnMap = (ZnItemClassId) &MAP_ITEM_CLASS;
diff --git a/generic/MapInfo.c b/generic/MapInfo.c
deleted file mode 100644
index 2af18bd..0000000
--- a/generic/MapInfo.c
+++ /dev/null
@@ -1,2171 +0,0 @@
-/*
- * MapInfo.c -- MapInfo interface.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _WIN32
-#include <sys/param.h>
-#include <netinet/in.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include "MapInfo.h"
-#include "tkZinc.h"
-
-#include <memory.h>
-#include <math.h>
-
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- *-----------------------------------------------------------------------
- *
- * New types
- *
- *-----------------------------------------------------------------------
- */
-typedef struct {
- ZnPtr tag;
- ZnMapInfoLineStyle style;
- int width;
- ZnPoint center;
- unsigned int radius;
- int start_angle;
- int extend;
-} ZnMapInfoArcStruct, *ZnMapInfoArc;
-
-typedef struct {
- ZnPtr tag;
- ZnMapInfoLineStyle style;
- int width;
- ZnPoint from;
- ZnPoint to;
- unsigned int num_marks;
- ZnPoint *marks;
-} ZnMapInfoLineStruct, *ZnMapInfoLine;
-
-typedef struct {
- ZnPtr tag;
- ZnPoint at;
- char symbol[2];
-} ZnMapInfoSymbolStruct, *ZnMapInfoSymbol;
-
-typedef struct {
- ZnPtr tag;
- ZnMapInfoTextStyle text_style;
- ZnMapInfoLineStyle line_style;
- ZnPoint at;
- char *text;
-} ZnMapInfoTextStruct, *ZnMapInfoText;
-
-typedef struct {
- char *name;
- ZnList lines;
- ZnList symbols;
- ZnList texts;
- ZnList arcs;
-} ZnMapInfoStruct, *ZnMapInfo;
-
-
-#define MARKERS_SPACING 80.0 /* 10 nautic miles in 1/8 of a mile */
-#define BASE_ALLOC_SIZE 8
-
-
-/*
- *-----------------------------------------------------------------------
- *
- * Macros.
- *
- *-----------------------------------------------------------------------
- */
-#define NOT_MARKED_STYLE(style) \
-((style) == ZnMapInfoLineMarked ? ZnMapInfoLineSimple : (style));
-
-
-/*
- *-----------------------------------------------------------------------
- *
- * ComputeLineMarks --
- * Add marks to a line in the marks substructure.
- *
- *-----------------------------------------------------------------------
- */
-
-static void
-ComputeLineMarks(ZnMapInfoLine marked_line)
-{
- ZnDim length;
- ZnPos x_from = marked_line->from.x;
- ZnPos y_from = marked_line->from.y;
- ZnPos x_to = marked_line->to.x;
- ZnPos y_to = marked_line->to.y;
- ZnPos delta_x = x_from - x_to;
- ZnPos delta_y = y_from - y_to;
- ZnPos step_x, step_y;
- unsigned int j;
-
- length = sqrt(delta_x * delta_x + delta_y * delta_y);
- step_x = (x_to - x_from) * MARKERS_SPACING / length;
- step_y = (y_to - y_from) * MARKERS_SPACING / length;
- marked_line->num_marks = (int) (length / MARKERS_SPACING);
-
- /* We don't want markers at ends, so we get rid of the last one
- if it is at an end */
- if (fmod(length, MARKERS_SPACING) == 0.0) {
- (marked_line->num_marks)--;
- }
-
- if (marked_line->num_marks) {
- marked_line->marks = ZnMalloc(marked_line->num_marks * sizeof(ZnPoint));
- }
-
- for (j = 0; j < marked_line->num_marks; j++) {
- marked_line->marks[j].x = x_from + ((j + 1) * step_x);
- marked_line->marks[j].y = y_from + ((j + 1) * step_y);
- }
-}
-
-
-static ZnMapInfoId
-ZnMapInfoCreate(char *name)
-{
- ZnMapInfo new_map;
-
- new_map = ZnMalloc(sizeof(ZnMapInfoStruct));
- memset((char *) new_map, 0, sizeof(ZnMapInfoStruct));
- if (!name) {
- name = "";
- }
- new_map->name = (char *) ZnMalloc(strlen(name)+1);
- /*printf("Nouvelle MapInfo: %s\n", name);*/
- strcpy(new_map->name, name);
-
- return((ZnMapInfoId) new_map);
-}
-
-
-static char *
-ZnMapInfoName(ZnMapInfoId map_info)
-{
- if (!map_info) {
- return "";
- }
- return ((ZnMapInfo) map_info)->name;
-}
-
-
-static ZnMapInfoId
-ZnMapInfoDuplicate(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfo new_map;
- unsigned int i, num_lines, num_texts;
- ZnMapInfoText new_texts, cur_texts;
- ZnMapInfoLine new_lines, cur_lines;
-
- if (!cur_map) {
- return ((ZnMapInfoId) NULL);
- }
-
- new_map = ZnMapInfoCreate(cur_map->name);
-
- if (cur_map->lines) {
- new_map->lines = ZnListDuplicate(cur_map->lines);
-
- cur_lines = ZnListArray(cur_map->lines);
- new_lines = ZnListArray(new_map->lines);
- num_lines = ZnListSize(cur_map->lines);
-
- for (i = 0; i < num_lines; i++) {
- if (new_lines[i].style == ZnMapInfoLineMarked) {
- new_lines[i].marks = ZnMalloc(new_lines[i].num_marks * sizeof(ZnPoint));
- memcpy((char *) new_lines[i].marks,
- (char *) cur_lines[i].marks,
- new_lines[i].num_marks * sizeof(ZnPoint));
- }
- }
- }
- if (cur_map->symbols) {
- new_map->symbols = ZnListDuplicate(cur_map->symbols);
- }
- if (cur_map->texts) {
- new_map->texts = ZnListDuplicate(cur_map->texts);
-
- cur_texts = ZnListArray(cur_map->texts);
- new_texts = ZnListArray(new_map->texts);
- num_texts = ZnListSize(cur_map->texts);
-
- for (i = 0; i < num_texts; i++) {
- new_texts[i].text = ZnMalloc(strlen(cur_texts[i].text) + 1);
- strcpy(new_texts[i].text, cur_texts[i].text);
- }
- }
- if (cur_map->arcs) {
- new_map->arcs = ZnListDuplicate(cur_map->arcs);
- }
-
- return((ZnMapInfoId) new_map);
-}
-
-
-static void
-ZnMapInfoDelete(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
- unsigned int i, num_texts, num_lines;
- ZnMapInfoText cur_texts;
- ZnMapInfoLine cur_lines;
-
- if (cur_map) {
- if (cur_map->texts) {
- num_texts = ZnListSize(cur_map->texts);
- cur_texts = ZnListArray(cur_map->texts);
-
- for (i = 0; i < num_texts; i++) {
- ZnFree(cur_texts[i].text);
- }
-
- ZnListFree(cur_map->texts);
- }
-
- if (cur_map->lines) {
- num_lines = ZnListSize(cur_map->lines);
- cur_lines = ZnListArray(cur_map->lines);
-
- for (i = 0; i < num_lines; i++) {
- if (cur_lines[i].style == ZnMapInfoLineMarked) {
- ZnFree(cur_lines[i].marks);
- }
- }
-
- ZnListFree(cur_map->lines);
- }
-
- if (cur_map->symbols) {
- ZnListFree(cur_map->symbols);
- }
-
- if (cur_map->arcs) {
- ZnListFree(cur_map->arcs);
- }
-
- ZnFree(cur_map->name);
- ZnFree(cur_map);
- }
-}
-
-static void
-ZnMapInfoEmpty(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map) {
- if (cur_map->texts) {
- ZnListEmpty(cur_map->texts);
- }
- if (cur_map->lines) {
- ZnListEmpty(cur_map->lines);
- }
- if (cur_map->symbols) {
- ZnListEmpty(cur_map->symbols);
- }
- if (cur_map->arcs) {
- ZnListEmpty(cur_map->arcs);
- }
- }
-}
-
-
-static void
-ZnMapInfoAddLine(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoLineStyle line_style,
- ZnDim line_width,
- ZnPos x_from,
- ZnPos y_from,
- ZnPos x_to,
- ZnPos y_to)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoLineStruct line_struct;
-
- if (cur_map) {
- if (!cur_map->lines) {
- cur_map->lines = ZnListNew(16, sizeof(ZnMapInfoLineStruct));
- }
-
- line_struct.style = line_style;
- if (line_width == 1.0) {
- line_struct.width = 0;
- }
- else {
- line_struct.width = (int) line_width;
- }
- line_struct.tag = tag;
- line_struct.from.x = x_from;
- line_struct.from.y = y_from;
- line_struct.to.x = x_to;
- line_struct.to.y = y_to;
- /*printf("Ajout de la ligne: %d %d %d %d\n", x_from, y_from, x_to, y_to);*/
- if (line_style == ZnMapInfoLineMarked) {
- ComputeLineMarks(&line_struct);
- }
-
- ZnListAdd(cur_map->lines, &line_struct, index);
- }
-}
-
-
-static void
-ZnMapInfoReplaceLine(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoLineStyle line_style,
- ZnDim line_width,
- ZnPos x_from,
- ZnPos y_from,
- ZnPos x_to,
- ZnPos y_to)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoLine line_ptr;
-
- if (cur_map && cur_map->lines) {
- line_ptr = ZnListAt(cur_map->lines, index);
- if (line_ptr) {
- if (line_ptr->style == ZnMapInfoLineMarked) {
- ZnFree(line_ptr->marks);
- }
-
- line_ptr->style = line_style;
- if (line_width == 1.0) {
- line_ptr->width = 0;
- }
- else {
- line_ptr->width = (int) line_width;
- }
- line_ptr->tag = tag;
- line_ptr->from.x = x_from;
- line_ptr->from.y = y_from;
- line_ptr->to.x = x_to;
- line_ptr->to.y = y_to;
-
- if (line_ptr->style == ZnMapInfoLineMarked) {
- ComputeLineMarks(line_ptr);
- }
- }
- }
-}
-
-
-static void
-ZnMapInfoRemoveLine(ZnMapInfoId map_info,
- unsigned int index)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoLine line_ptr;
-
- if (cur_map && cur_map->lines) {
- line_ptr = ZnListAt(cur_map->lines, index);
- if (line_ptr) {
- if (line_ptr->style == ZnMapInfoLineMarked) {
- ZnFree(line_ptr->marks);
- }
-
- ZnListDelete(cur_map->lines, index);
- }
- }
-}
-
-
-void
-ZnMapInfoGetLine(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr *tag,
- ZnMapInfoLineStyle *line_style,
- ZnDim *line_width,
- ZnPos *x_from,
- ZnPos *y_from,
- ZnPos *x_to,
- ZnPos *y_to)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoLine line_ptr;
-
- if (cur_map && cur_map->lines) {
- line_ptr = ZnListAt(cur_map->lines, index);
- if (line_ptr) {
- if (tag) {
- *tag = line_ptr->tag;
- }
- if (line_style) {
- *line_style = line_ptr->style;
- }
- if (line_width) {
- if (line_ptr->width == 1.0) {
- *line_width = 0;
- }
- else {
- *line_width = line_ptr->width;
- }
- }
- if (x_from) {
- *x_from = line_ptr->from.x;
- }
- if (y_from) {
- *y_from = line_ptr->from.y;
- }
- if (x_to) {
- *x_to = line_ptr->to.x;
- }
- if (y_to) {
- *y_to = line_ptr->to.y;
- }
- }
- }
-}
-
-
-void
-ZnMapInfoGetMarks(ZnMapInfoId map_info,
- unsigned int index,
- ZnPoint **marks,
- unsigned int *num_marks)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoLine line_ptr;
-
- if (cur_map && cur_map->lines) {
- line_ptr = ZnListAt(cur_map->lines, index);
- if (line_ptr && line_ptr->style == ZnMapInfoLineMarked) {
- if (marks) {
- *marks = line_ptr->marks;
- }
- if (num_marks) {
- *num_marks = line_ptr->num_marks;
- }
- }
- }
-}
-
-
-unsigned int
-ZnMapInfoNumLines(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map && cur_map->lines) {
- return ZnListSize(cur_map->lines);
- }
- else {
- return 0;
- }
-}
-
-
-static void
-ZnMapInfoAddSymbol(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnPos x,
- ZnPos y,
- int symbol)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoSymbolStruct symbol_struct;
-
- if (cur_map) {
- if (!cur_map->symbols) {
- cur_map->symbols = ZnListNew(16, sizeof(ZnMapInfoSymbolStruct));
- }
-
- symbol_struct.tag = tag;
- symbol_struct.at.x = x;
- symbol_struct.at.y = y;
- symbol_struct.symbol[0] = symbol;
- symbol_struct.symbol[1] = '\0';
-
- ZnListAdd(cur_map->symbols, &symbol_struct, index);
- }
-}
-
-
-static void
-ZnMapInfoReplaceSymbol(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnPos x,
- ZnPos y,
- int symbol)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoSymbolStruct symbol_struct;
-
- if (cur_map && cur_map->symbols) {
- symbol_struct.tag = tag;
- symbol_struct.at.x = x;
- symbol_struct.at.y = y;
- symbol_struct.symbol[0] = symbol;
- symbol_struct.symbol[1] = '\0';
-
- ZnListAtPut(cur_map->symbols, &symbol_struct, index);
- }
-}
-
-
-static void
-ZnMapInfoRemoveSymbol(ZnMapInfoId map_info,
- unsigned int index)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map && cur_map->symbols) {
- ZnListDelete(cur_map->symbols, index);
- }
-}
-
-
-void
-ZnMapInfoGetSymbol(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr *tag,
- ZnPos *x,
- ZnPos *y,
- char *symbol)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoSymbol symbol_ptr;
-
- if (cur_map && cur_map->symbols) {
- symbol_ptr = ZnListAt(cur_map->symbols, index);
- if (symbol_ptr) {
- if (tag) {
- *tag = symbol_ptr->tag;
- }
- if (x) {
- *x = symbol_ptr->at.x;
- }
- if (y) {
- *y = symbol_ptr->at.y;
- }
- if (symbol) {
- *symbol = symbol_ptr->symbol[0];
- }
- }
- }
-}
-
-
-unsigned int
-ZnMapInfoNumSymbols(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map && cur_map->symbols) {
- return ZnListSize(cur_map->symbols);
- }
- else {
- return 0;
- }
-}
-
-
-static void
-ZnMapInfoAddText(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoTextStyle text_style,
- ZnMapInfoLineStyle line_style,
- ZnPos x,
- ZnPos y,
- char *text)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoTextStruct text_struct;
-
- if (cur_map) {
- if (!cur_map->texts) {
- cur_map->texts = ZnListNew(16, sizeof(ZnMapInfoTextStruct));
- }
-
- text_struct.tag = tag;
- text_struct.text_style = text_style;
- text_struct.line_style = NOT_MARKED_STYLE(line_style);
- text_struct.at.x = x;
- text_struct.at.y = y;
- text_struct.text = ZnMalloc(strlen(text) + 1);
- strcpy(text_struct.text, text);
-
- ZnListAdd(cur_map->texts, &text_struct, index);
- }
-}
-
-
-static void
-ZnMapInfoReplaceText(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoTextStyle text_style,
- ZnMapInfoLineStyle line_style,
- ZnPos x,
- ZnPos y,
- char *text)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoText text_ptr;
-
- if (cur_map && cur_map->texts) {
- text_ptr = ZnListAt(cur_map->texts, index);
- if (text_ptr) {
- ZnFree(text_ptr->text);
-
- text_ptr->tag = tag;
- text_ptr->text_style = text_style;
- text_ptr->line_style = NOT_MARKED_STYLE(line_style);
- text_ptr->at.x = x;
- text_ptr->at.y = y;
- text_ptr->text = ZnMalloc(strlen(text) + 1);
- strcpy(text_ptr->text, text);
- }
- }
-}
-
-
-static void
-ZnMapInfoRemoveText(ZnMapInfoId map_info,
- unsigned int index)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoText text_ptr;
-
- if (cur_map && cur_map->texts) {
- text_ptr = ZnListAt(cur_map->texts, index);
- if (text_ptr) {
- ZnFree(text_ptr->text);
-
- ZnListDelete(cur_map->texts, index);
- }
- }
-}
-
-
-void
-ZnMapInfoGetText(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr *tag,
- ZnMapInfoTextStyle *text_style,
- ZnMapInfoLineStyle *line_style,
- ZnPos *x,
- ZnPos *y,
- char **text)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoText text_ptr;
-
- if (cur_map && cur_map->texts) {
- text_ptr = ZnListAt(cur_map->texts, index);
- if (text_ptr) {
- if (tag) {
- *tag = text_ptr->tag;
- }
- if (text_style) {
- *text_style = text_ptr->text_style;
- }
- if (line_style) {
- *line_style = text_ptr->line_style;
- }
- if (x) {
- *x = text_ptr->at.x;
- }
- if (y) {
- *y = text_ptr->at.y;
- }
- if (text) {
- *text = text_ptr->text;
- }
- }
- }
-}
-
-
-unsigned int
-ZnMapInfoNumTexts(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map && cur_map->texts) {
- return ZnListSize(cur_map->texts);
- }
- else {
- return 0;
- }
-}
-
-
-static void
-ZnMapInfoAddArc(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoLineStyle line_style,
- ZnDim line_width,
- ZnPos center_x,
- ZnPos center_y,
- ZnDim radius,
- ZnReal start_angle,
- ZnReal extend)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoArcStruct arc_struct;
-
- if (cur_map) {
- if (!cur_map->arcs) {
- cur_map->arcs = ZnListNew(16, sizeof(ZnMapInfoArcStruct));
- }
-
- arc_struct.style = NOT_MARKED_STYLE(line_style);
- if (line_width == 1.0) {
- arc_struct.width = 0;
- }
- else {
- arc_struct.width = (int) line_width;
- }
- arc_struct.tag = tag;
- arc_struct.center.x = center_x;
- arc_struct.center.y = center_y;
- arc_struct.radius = (int) radius;
- arc_struct.start_angle = (int) start_angle;
- arc_struct.extend = (int) extend;
-
- ZnListAdd(cur_map->arcs, &arc_struct, index);
- }
-}
-
-
-static void
-ZnMapInfoReplaceArc(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr tag,
- ZnMapInfoLineStyle line_style,
- ZnDim line_width,
- ZnPos center_x,
- ZnPos center_y,
- ZnDim radius,
- ZnReal start_angle,
- ZnReal extend)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoArc arc_ptr;
-
- if (cur_map && cur_map->arcs) {
- arc_ptr = ZnListAt(cur_map->arcs, index);
- if (arc_ptr) {
- arc_ptr->style = NOT_MARKED_STYLE(line_style);
- if (line_width == 1.0) {
- arc_ptr->width = 0;
- }
- else {
- arc_ptr->width = (int) line_width;
- }
- arc_ptr->tag = tag;
- arc_ptr->center.x = center_x;
- arc_ptr->center.y = center_y;
- arc_ptr->radius = (int) radius;
- arc_ptr->start_angle = (int) start_angle;
- arc_ptr->extend = (int) extend;
- }
- }
-}
-
-
-static void
-ZnMapInfoRemoveArc(ZnMapInfoId map_info,
- unsigned int index)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoArc arc_ptr;
-
- if (cur_map && cur_map->arcs) {
- arc_ptr = ZnListAt(cur_map->arcs, index);
- if (arc_ptr) {
- ZnListDelete(cur_map->arcs, index);
- }
- }
-}
-
-
-void
-ZnMapInfoGetArc(ZnMapInfoId map_info,
- unsigned int index,
- ZnPtr *tag,
- ZnMapInfoLineStyle *line_style,
- ZnDim *line_width,
- ZnPos *center_x,
- ZnPos *center_y,
- ZnDim *radius,
- ZnReal *start_angle,
- ZnReal *extend)
-{
- ZnMapInfo cur_map = map_info;
- ZnMapInfoArc arc_ptr;
-
- if (cur_map && cur_map->arcs) {
- arc_ptr = ZnListAt(cur_map->arcs, index);
- if (arc_ptr) {
- if (tag) {
- *tag = arc_ptr->tag;
- }
- if (line_style) {
- *line_style = arc_ptr->style;
- }
- if (line_width) {
- if (arc_ptr->width == 1.0) {
- *line_width = 0;
- }
- else {
- *line_width = arc_ptr->width;
- }
- }
- if (center_x) {
- *center_x = arc_ptr->center.x;
- }
- if (center_y) {
- *center_y = arc_ptr->center.y;
- }
- if (radius) {
- *radius = arc_ptr->radius;
- }
- if (start_angle) {
- *start_angle = arc_ptr->start_angle;
- }
- if (extend) {
- *extend = arc_ptr->extend;
- }
- }
- }
-}
-
-unsigned int
-ZnMapInfoNumArcs(ZnMapInfoId map_info)
-{
- ZnMapInfo cur_map = map_info;
-
- if (cur_map && cur_map->arcs) {
- return ZnListSize(cur_map->arcs);
- }
- else {
- return 0;
- }
-}
-
-static void
-ZnMapInfoScale(ZnMapInfoId map_info,
- ZnReal factor)
-{
- ZnMapInfo mp = map_info;
- int i, num;
- ZnMapInfoLine line_ptr;
- ZnMapInfoSymbol sym_ptr;
- ZnMapInfoText text_ptr;
- ZnMapInfoArc arc_ptr;
-
- if (mp && mp->lines) {
- num = ZnListSize(mp->lines);
- line_ptr = ZnListArray(mp->lines);
- for (i = 0; i < num; i++, line_ptr++) {
- line_ptr->from.x *= factor;
- line_ptr->from.y *= factor;
- line_ptr->to.x *= factor;
- line_ptr->to.y *= factor;
- }
- }
- if (mp && mp->symbols) {
- num = ZnListSize(mp->symbols);
- sym_ptr = ZnListArray(mp->symbols);
- for (i = 0; i < num; i++, sym_ptr++) {
- sym_ptr->at.x *= factor;
- sym_ptr->at.y *= factor;
- }
- }
- if (mp && mp->texts) {
- num = ZnListSize(mp->texts);
- text_ptr = ZnListArray(mp->texts);
- for (i = 0; i < num; i++, text_ptr++) {
- text_ptr->at.x *= factor;
- text_ptr->at.y *= factor;
- }
- }
- if (mp && mp->arcs) {
- num = ZnListSize(mp->arcs);
- arc_ptr = ZnListArray(mp->arcs);
- for (i = 0; i < num; i++, arc_ptr++) {
- arc_ptr->center.x *= factor;
- arc_ptr->center.y *= factor;
- arc_ptr->radius = (unsigned int) (arc_ptr->radius * factor);
- }
- }
-}
-
-static void
-ZnMapInfoTranslate(ZnMapInfoId map_info,
- ZnPos x,
- ZnPos y)
-{
- ZnMapInfo mp = map_info;
- int i, num;
- ZnMapInfoLine line_ptr;
- ZnMapInfoSymbol sym_ptr;
- ZnMapInfoText text_ptr;
- ZnMapInfoArc arc_ptr;
-
- if (mp && mp->lines) {
- num = ZnListSize(mp->lines);
- line_ptr = ZnListArray(mp->lines);
- for (i = 0; i < num; i++, line_ptr++) {
- line_ptr->from.x += x;
- line_ptr->from.y += y;
- line_ptr->to.x += x;
- line_ptr->to.y += y;
- }
- }
- if (mp && mp->symbols) {
- num = ZnListSize(mp->symbols);
- sym_ptr = ZnListArray(mp->symbols);
- for (i = 0; i < num; i++, sym_ptr++) {
- sym_ptr->at.x += x;
- sym_ptr->at.y += y;
- }
- }
- if (mp && mp->texts) {
- num = ZnListSize(mp->texts);
- text_ptr = ZnListArray(mp->texts);
- for (i = 0; i < num; i++, text_ptr++) {
- text_ptr->at.x += x;
- text_ptr->at.y += y;
- }
- }
- if (mp && mp->arcs) {
- num = ZnListSize(mp->arcs);
- arc_ptr = ZnListArray(mp->arcs);
- for (i = 0; i < num; i++, arc_ptr++) {
- arc_ptr->center.x += x;
- arc_ptr->center.y += y;
- }
- }
-}
-
-
-
-#define TEXT_SIZE 256
-#define ntohi(n) ntohl((n))
-
-/*
- *-----------------------------------------------------------------------
- *
- * Videomap record definition. Ints are assumed to be 4 bytes.
- *
- *-----------------------------------------------------------------------
- */
-
-typedef struct {
- int id; /* Map id (internal) */
- int dashed; /* Tell if vectors are dashed (exclusive with marked) */
- int expanded; /* Device coordinates or world coordinates (ignored now) */
- int marked; /* Tell if vectors are marked (exclusive with dashed) */
- int color; /* drawing color (ignored now) */
- int elements[50]; /* Element type ('P', 'V', 'T') */
- int x[50]; /* Coordinates if 'P' or 'V' */
- int y[50];
- int symbol[50]; /* Filled if 'P' or 'V' */
- int text[50]; /* Low order byte is ascii char if 'T' */
- int num_elements; /* Number of elements */
-} VideoMap;
-
-/*
- *-----------------------------------------------------------------------
- *
- * ReorderVidomap - reorder integers according to the endianess
- *
- *-----------------------------------------------------------------------
- */
-
-static void
-ReorderVidomap(VideoMap *vm)
-{
- int loop;
-
- vm->id = ntohi((unsigned int) vm->id);
- vm->dashed = ntohi((unsigned int) vm->dashed);
- vm->expanded = ntohi((unsigned int) vm->expanded);
- vm->marked = ntohi((unsigned int) vm->marked);
- vm->color = ntohi((unsigned int) vm->color);
- for (loop = 0; loop < 50; loop++) {
- vm->elements[loop] = ntohi((unsigned int) vm->elements[loop]);
- vm->x[loop] = ntohi((unsigned int) vm->x[loop]);
- vm->y[loop] = ntohi((unsigned int) vm->y[loop]);
- vm->symbol[loop] = ntohi((unsigned int) vm->symbol[loop]);
- vm->text[loop] = ntohi((unsigned int) vm->text[loop]);
- }
- vm->num_elements = ntohi((unsigned int) vm->num_elements);
-}
-
-/*
- *-----------------------------------------------------------------------
- *
- * FillMap - Fill map with data in Videomap record vm.
- *
- *-----------------------------------------------------------------------
- */
-
-static void
-FillMap(ZnMapInfoId map,
- VideoMap *vm)
-{
- int i;
- ZnBool has_start_pos = False;
- ZnPos x_cur=0, y_cur=0;
- char ch;
- ZnPos text_x=0, text_y=0;
- char text[TEXT_SIZE];
- ZnBool in_text = False;
- ZnBool in_mod_text = False;
- unsigned int text_size=0;
-
- for (i = 0; i < vm->num_elements; i++) {
- switch(vm->elements[i] & 0xFF) {
- case 'p':
- case 'P':
- if (in_text) {
- in_text = in_mod_text = False;
- while (text[text_size - 1] == ' ') {
- text_size--;
- }
- text[text_size] = (char) 0;
- ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
- ZnMapInfoLineSimple, text_x, text_y, text);
- }
-
- x_cur = (int) (short) vm->x[i];
- y_cur = (int) (short) vm->y[i];
- has_start_pos = True;
-
- if (vm->symbol[i]) {
- ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
- (char) vm->symbol[i]);
- }
- break;
-
- /* We gather consecutive 'T' elements in a text. We skip
- leading and trailing spaces and mod texts (between '@'
- and now obsolete) */
-
- case 't':
- case 'T':
- if (!has_start_pos) {
- ZnWarning("Bogus map block, it has been discarded\n");
- return;
- }
-
- if (in_text == False) {
- ch = (char) vm->text[i] & 0xFF;
- if (ch == '@') {
- if (in_mod_text == True) {
- in_mod_text = False;
- }
- else {
- in_mod_text = True;
- }
- }
- else if (in_mod_text == False) {
- in_text = True;
- text_size = 0;
- text_x = x_cur;
- text_y = y_cur;
- text[0] = (char) 0;
- }
- }
- if (in_text) {
- text[text_size] = (char) vm->text[i] & 0xFF;
- text_size++;
- }
- break;
-
- case 'v':
- case 'V':
- if (!has_start_pos) {
- ZnWarning("Bogus map block, it has been discarded\n");
- return;
- }
-
- if (in_text) {
- in_text = in_mod_text = False;
- while (text[text_size - 1] == ' ') {
- text_size--;
- }
- text[text_size] = (char) 0;
- ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
- ZnMapInfoLineSimple, text_x, text_y, text);
- }
-
- if (vm->dashed) {
- ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineDashed,
- 0, x_cur, y_cur,
- (int) (short) vm->x[i], (int) (short) vm->y[i]);
- }
- else if (vm->marked) {
- ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineMarked,
- 0, x_cur, y_cur,
- (int) (short) vm->x[i], (int) (short) vm->y[i]);
- }
- else {
- ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineSimple,
- 0, x_cur, y_cur,
- (int) (short) vm->x[i], (int) (short) vm->y[i]);
- }
-
- x_cur = (int) (short) vm->x[i];
- y_cur = (int) (short) vm->y[i];
-
- if (vm->symbol[i]) {
- ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
- (char) vm->symbol[i]);
- }
- break;
- }
- }
-
- if (in_text) {
- in_text = in_mod_text = False;
- while (text[text_size - 1] == ' ') {
- text_size--;
- }
- text[text_size] = (char) 0;
- ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
- ZnMapInfoLineSimple, text_x, text_y, text);
- }
-}
-
-/*
- *-----------------------------------------------------------------------
- *
- * ZnMapInfoGetVideomap - Load a mapinfo with the content of a videomap
- * file named 'filename'. Only the sub map 'index' will be loaded.
- * If successful a new mapinfo is returned, NULL otherwise. The
- * index is zero based.
- *
- *-----------------------------------------------------------------------
- */
-static int
-ZnMapInfoGetVideomap(ZnMapInfoId map,
- char *filename,
- unsigned int index)
-{
- VideoMap current_vm;
- Tcl_Channel chan;
- unsigned int cur_index, cur_id;
-
- /* Open the specified map file. */
- chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
- if (chan == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_SetChannelOption(NULL, chan,
- "-translation", "binary") == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- /* Load the map */
-
- /* First skip the leading maps up to index. */
- cur_index = 0;
- if (Tcl_Read(chan, (char *) &current_vm,
- sizeof(VideoMap)) != sizeof(VideoMap)) {
- goto error;
- }
- cur_id = ntohi((unsigned int) current_vm.id);
- while (cur_index != index) {
- if (Tcl_Read(chan, (char *) &current_vm,
- sizeof(VideoMap)) != sizeof(VideoMap)) {
- goto error;
- }
- if (cur_id != ntohi((unsigned int) current_vm.id)) {
- cur_index++;
- cur_id = ntohi((unsigned int) current_vm.id);
- }
- };
-
- /* Then load all the map modules. */
- do {
- ReorderVidomap(&current_vm);
- FillMap(map, &current_vm);
- if ((Tcl_Read(chan, (char *) &current_vm,
- sizeof(VideoMap)) != sizeof(VideoMap)) &&
- !Tcl_Eof(chan)) {
- goto error;
- }
- }
- while ((cur_id == ntohi((unsigned int) current_vm.id)) &&
- !Tcl_Eof(chan));
-
- Tcl_Close(NULL, chan);
- return TCL_OK;
-
- error:
- Tcl_Close(NULL, chan);
- return TCL_ERROR;
-}
-
-/*
- *-----------------------------------------------------------------------
- *
- * ZnMapInfoVideomapIds - Return the list of sub map ids contained in a
- * videomap file. This makes it possible to iterate through such
- * a file without stumbling on an error, to know how much maps
- * are there and to sort them according to their ids.
- *
- *-----------------------------------------------------------------------
- */
-
-static ZnList
-ZnMapInfoVideomapIds(char *filename)
-{
- Tcl_Channel chan;
- VideoMap current_vm;
- unsigned int cur_id;
- ZnList ids;
-
- /* Open the specified map file. */
- chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
- if (chan == NULL) {
- return NULL;
- }
- if (Tcl_SetChannelOption(NULL, chan,
- "-translation", "binary") == TCL_ERROR) {
- return NULL;
- }
-
- if (Tcl_Read(chan, (char *) &current_vm,
- sizeof(VideoMap)) != sizeof(VideoMap)) {
- error:
- Tcl_Close(NULL, chan);
- return NULL;
- }
- cur_id = ntohi((unsigned int) current_vm.id);
- ids = ZnListNew(16, sizeof(int));
- /*printf("id %d\n", cur_id);*/
- ZnListAdd(ids, &cur_id, ZnListTail);
-
- do {
- if (Tcl_Read(chan, (char *) &current_vm,
- sizeof(VideoMap)) != sizeof(VideoMap)) {
- ZnListFree(ids);
- goto error;
- }
- if (cur_id != ntohi((unsigned int) current_vm.id)) {
- cur_id = ntohi((unsigned int) current_vm.id);
- /*printf("id %d\n", cur_id);*/
- ZnListAdd(ids, &cur_id, ZnListTail);
- }
- }
- while (!Tcl_Eof(chan));
-
- Tcl_Close(NULL, chan);
- return ids;
-}
-
-
-/*
- *--------------------------------------------------------------------------
- *
- * ZnMapInfo and Videomapstuff that should go eventually in its own file.
- *
- *--------------------------------------------------------------------------
- */
-
-static Tcl_HashTable mapInfoTable;
-static ZnBool map_info_inited = False;
-
-typedef struct {
- ClientData client_data;
- ZnMapInfoChangeProc proc;
-} ZnMapInfoClient;
-
-typedef struct {
- ZnMapInfoId map_info;
- ZnBool deleted;
- ZnList clients;
-} ZnMapInfoMaster;
-
-static void
-ZnMapInfoInit()
-{
- Tcl_InitHashTable(&mapInfoTable, TCL_ONE_WORD_KEYS);
-
- map_info_inited = True;
-}
-
-static void
-UpdateMapInfoClients(ZnMapInfoMaster *master)
-{
- int i, num;
- ZnMapInfoClient *client;
-
- num = ZnListSize(master->clients);
- client = ZnListArray(master->clients);
- for (i = 0; i < num; i++, client++) {
- (*client->proc)(client->client_data, master->map_info);
- }
-}
-
-static int
-ZnCreateMapInfo(Tcl_Interp *interp,
- char *name,
- ZnMapInfoId *map_info)
-{
- Tk_Uid uid = Tk_GetUid(name);
- Tcl_HashEntry *entry;
- int new;
- ZnMapInfoMaster *master;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
- if (!new) {
- /*
- * Empty the map info if it is not.
- */
- master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
- if (master->deleted) {
- master->deleted = False;
- }
- else {
- ZnMapInfoEmpty(master->map_info);
- UpdateMapInfoClients(master);
- }
- }
- else {
- master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
- master->map_info = ZnMapInfoCreate(name);
- master->deleted = False;
- master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
- Tcl_SetHashValue(entry, master);
- }
- if (map_info) {
- *map_info = master->map_info;
- }
- return TCL_OK;
-}
-
-static int
-ZnDuplicateZnMapInfo(Tcl_Interp *interp,
- char *name,
- ZnMapInfoId map_info)
-{
- Tk_Uid uid = Tk_GetUid(name);
- Tcl_HashEntry *entry;
- int new;
- ZnMapInfoMaster *master;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
- if (!new) {
- Tcl_AppendResult(interp, "duplicate mapinfo \"", name, "\" already exists", NULL);
- return TCL_ERROR;
- }
- master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
- master->map_info = ZnMapInfoDuplicate(map_info);
- master->deleted = False;
- master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
- Tcl_SetHashValue(entry, master);
-
- return TCL_OK;
-}
-
-static ZnMapInfoMaster *
-LookupMapInfoMaster(Tcl_Interp *interp,
- char *name)
-{
- Tk_Uid uid = Tk_GetUid(name);
- Tcl_HashEntry *entry;
- ZnMapInfoMaster *master;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_FindHashEntry(&mapInfoTable, uid);
- if (entry == NULL) {
- mp_error:
- Tcl_AppendResult(interp, "mapinfo \"", name, "\" doesn't exist", NULL);
- return NULL;
- }
- master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
- if (master->deleted) {
- goto mp_error;
- }
- return master;
-}
-
-static int
-ZnDeleteMapInfo(Tcl_Interp *interp,
- char *name)
-{
- ZnMapInfoMaster *master;
- Tk_Uid uid = Tk_GetUid(name);
- Tcl_HashEntry *entry;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_FindHashEntry(&mapInfoTable, uid);
- if (entry == NULL) {
- return TCL_ERROR;
- }
-
- master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
- if (ZnListSize(master->clients) != 0) {
- master->deleted = True;
- ZnMapInfoEmpty(master->map_info);
- UpdateMapInfoClients(master);
- }
- else {
- ZnMapInfoDelete(master->map_info);
- ZnListFree(master->clients);
- Tcl_DeleteHashEntry(entry);
- ZnFree(master);
- }
-
- return TCL_OK;
-}
-
-ZnMapInfoId
-ZnGetMapInfo(Tcl_Interp *interp,
- char *name,
- ZnMapInfoChangeProc proc,
- ClientData client_data)
-{
- ZnMapInfoMaster *master;
- ZnMapInfoClient client;
-
- master = LookupMapInfoMaster(interp, name);
- if (master == NULL) {
- return NULL;
- }
- client.proc = proc;
- client.client_data = client_data;
- ZnListAdd(master->clients, &client, ZnListTail);
-
- return master->map_info;
-}
-
-void
-ZnFreeMapInfo(ZnMapInfoId map_info,
- ZnMapInfoChangeProc proc,
- ClientData client_data)
-{
- Tk_Uid uid = Tk_GetUid(ZnMapInfoName(map_info));
- Tcl_HashEntry *entry;
- ZnMapInfoMaster *master;
- ZnMapInfoClient *client;
- unsigned int num, i;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_FindHashEntry(&mapInfoTable, uid);
- if (entry == NULL) {
- return;
- }
- master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
- client = ZnListArray(master->clients);
- num = ZnListSize(master->clients);
- for (i = 0; i < num; i++, client++) {
- if ((client->client_data == client_data) &&
- (client->proc == proc)) {
- ZnListDelete(master->clients, i);
- return;
- }
- }
-}
-
-static void
-ZnUpdateMapInfoClients(ZnMapInfoId map_info)
-{
- Tk_Uid uid = Tk_GetUid(ZnMapInfoName(map_info));
- Tcl_HashEntry *entry;
- ZnMapInfoMaster *master;
-
- if (!map_info_inited) {
- ZnMapInfoInit();
- }
-
- entry = Tcl_FindHashEntry(&mapInfoTable, uid);
- if (entry == NULL) {
- return;
- }
- master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
- UpdateMapInfoClients(master);
-}
-
-
-/*
- * These arrays must be kept in sync with the ZnMapInfoLineStyle
- * and ZnMapInfoTextStyle enums.
- */
-static char *line_style_strings[] = {
- "simple",
- "dashed",
- "dotted",
- "mixed",
- "marked",
-};
-
-static char *text_style_strings[] = {
- "normal",
- "underlined"
-};
-
-static char *
-ZnMapInfoLineStyleToString(ZnMapInfoLineStyle line_style)
-{
- return line_style_strings[line_style];
-}
-
-static int
-ZnMapInfoLineStyleFromString(Tcl_Interp *interp,
- char *str,
- ZnMapInfoLineStyle *line_style)
-{
- int i, num = sizeof(line_style_strings)/sizeof(char *);
-
- for (i = 0; i < num; i++) {
- if (strcmp(str, line_style_strings[i]) == 0) {
- *line_style = i;
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, " incorrect mapinfo line style \"",
- str,"\"", NULL);
- return TCL_ERROR;
-}
-
-static char *
-ZnMapInfoTextStyleToString(ZnMapInfoTextStyle text_style)
-{
- return text_style_strings[text_style];
-}
-
-static int
-ZnMapInfoTextStyleFromString(Tcl_Interp *interp,
- char *str,
- ZnMapInfoTextStyle *text_style)
-{
- int i, num = sizeof(text_style_strings)/sizeof(char *);
-
- for (i = 0; i < num; i++) {
- if (strcmp(str, text_style_strings[i]) == 0) {
- *text_style = i;
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, " incorrect mapinfo text style \"",
- str,"\"", NULL);
- return TCL_ERROR;
-}
-
-int
-ZnMapInfoObjCmd(ClientData client_data,
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- Tcl_Obj *CONST args[])
-{
- ZnPos x, y;
- int index, index2, result;
- ZnMapInfoMaster *master;
- Tcl_Obj *l;
-#ifdef PTK_800
- static char *sub_cmd_strings[] =
-#else
- static CONST char *sub_cmd_strings[] =
-#endif
- {
- "add", "count", "create", "delete", "duplicate",
- "get", "remove", "replace", "scale", "translate", NULL
- };
-#ifdef PTK_800
- static char *e_type_strings[] =
-#else
- static CONST char *e_type_strings[] =
-#endif
- {
- "arc", "line", "symbol", "text", NULL
- };
- enum sub_cmds {
- ZN_MI_ADD, ZN_MI_COUNT, ZN_MI_CREATE, ZN_MI_DELETE, ZN_MI_DUPLICATE,
- ZN_MI_GET, ZN_MI_REMOVE, ZN_MI_REPLACE, ZN_MI_SCALE, ZN_MI_TRANSLATE
- };
- enum e_types {
- ZN_E_ARC, ZN_E_LINE, ZN_E_SYMBOL, ZN_E_TEXT
- };
-
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo/name subCmd ?args?");
- return TCL_ERROR;
- }
-
- if (Tcl_GetIndexFromObj(interp, args[2], sub_cmd_strings,
- "subCmd", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- result = TCL_OK;
- /*printf("mapinfo command \"%s\", argc=%d\n",
- Tcl_GetString(args[2]), argc);*/
-
- switch((enum sub_cmds) index) {
- /*
- * create
- */
- case ZN_MI_CREATE:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "name create");
- return TCL_ERROR;
- }
- if (ZnCreateMapInfo(interp, Tcl_GetString(args[1]), NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- break;
- /*
- * delete
- */
- case ZN_MI_DELETE:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo delete");
- return TCL_ERROR;
- }
- if (ZnDeleteMapInfo(interp, Tcl_GetString(args[1])) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- break;
- /*
- * duplicate
- */
- case ZN_MI_DUPLICATE:
- {
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo duplicate name");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (ZnDuplicateZnMapInfo(interp, Tcl_GetString(args[3]),
- master->map_info) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- break;
- /*
- * add/replace
- */
- case ZN_MI_ADD:
- case ZN_MI_REPLACE:
- {
- ZnMapInfoLineStyle line_style;
- ZnMapInfoTextStyle text_style;
- int i, insert, val;
- ZnPos coords[6];
- ZnBool add_cmd = (enum sub_cmds) index == ZN_MI_ADD;
- int num_param = add_cmd ? 4 : 5;
-
- if (argc < num_param) {
- Tcl_WrongNumArgs(interp, 3, args,
- add_cmd ? "elementType ?args?" : "elementType index ?args?");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (!add_cmd) {
- if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
- "elementType", 0, &index2) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum e_types) index2) {
- case ZN_E_LINE:
- {
- if (argc != (num_param+6)) {
- Tcl_WrongNumArgs(interp, 4, args,
- add_cmd ? "style width x1 y1 x2 y2" : "index style width x1 y1 x2 y2");
- return TCL_ERROR;
- }
- if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
- &line_style) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (i = 0; i < 5; i++) {
- if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (coords[0] < 0) {
- coords[0] = 0;
- }
- if (add_cmd) {
- ZnMapInfoAddLine(master->map_info, ZnListTail, NULL, line_style,
- coords[0], coords[1], coords[2], coords[3], coords[4]);
- }
- else {
- ZnMapInfoReplaceLine(master->map_info, insert, NULL, line_style,
- coords[0], coords[1], coords[2], coords[3], coords[4]);
- }
- }
- break;
- case ZN_E_SYMBOL:
- {
- if (argc != (num_param+3)) {
- Tcl_WrongNumArgs(interp, 4, args,
- add_cmd ? "x y intVal" : "index x y intVal");
- return TCL_ERROR;
- }
- for (i = 0; i < 2; i++) {
- if (Tcl_GetDoubleFromObj(interp, args[num_param+i], &coords[i]) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (Tcl_GetIntFromObj(interp, args[num_param+2], &val) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (val < 0) {
- val = 0;
- }
- if (add_cmd) {
- ZnMapInfoAddSymbol(master->map_info, ZnListTail, NULL, coords[0],
- coords[1], (char) val);
- }
- else {
- ZnMapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0],
- coords[1], (char) val);
- }
- }
- break;
- case ZN_E_TEXT:
- {
- if (argc != (num_param+5)) {
- Tcl_WrongNumArgs(interp, 4, args,
- add_cmd ? "textStyle lineStyle x y string" : "index textStyle lineStyle x y string");
- return TCL_ERROR;
- }
- if (ZnMapInfoTextStyleFromString(interp, Tcl_GetString(args[num_param]),
- &text_style) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param+1]),
- &line_style) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (i = 0; i < 2; i++) {
- if (Tcl_GetDoubleFromObj(interp, args[num_param+i+2], &coords[i]) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (add_cmd) {
- ZnMapInfoAddText(master->map_info, ZnListTail, NULL, text_style,
- line_style, coords[0], coords[1],
- Tcl_GetString(args[num_param+4]));
- }
- else {
- /*printf("replace text ts %d ls %d %g %g %s\n", text_style,
- line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4]));*/
- ZnMapInfoReplaceText(master->map_info, insert, NULL, text_style,
- line_style, coords[0], coords[1],
- Tcl_GetString(args[num_param+4]));
- }
- }
- break;
- case ZN_E_ARC:
- {
- if (argc != (num_param+7)) {
- Tcl_WrongNumArgs(interp, 4, args,
- add_cmd ? "style width cx cy radius start extent" : "index style width cx cy radius start extent");
- return TCL_ERROR;
- }
- if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
- &line_style) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (i = 0; i < 6; i++) {
- if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (coords[0] < 0) {
- coords[0] = 0;
- }
- if (coords[3] < 0) {
- coords[3] = 0;
- }
- if (add_cmd) {
- ZnMapInfoAddArc(master->map_info, ZnListTail, NULL, line_style, coords[0],
- coords[1], coords[2], coords[3], coords[4], coords[5]);
- }
- else {
- ZnMapInfoReplaceArc(master->map_info, insert, NULL, line_style, coords[0],
- coords[1], coords[2], coords[3], coords[4], coords[5]);
- }
- }
- break;
- }
- UpdateMapInfoClients(master);
- }
- break;
- /*
- * count
- */
- case ZN_MI_COUNT:
- {
- int count = 0;
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo count type");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
- "elementType", 0, &index2) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum e_types) index2) {
- case ZN_E_LINE:
- count = ZnMapInfoNumLines(master->map_info);
- break;
- case ZN_E_SYMBOL:
- count = ZnMapInfoNumSymbols(master->map_info);
- break;
- case ZN_E_TEXT:
- count = ZnMapInfoNumTexts(master->map_info);
- break;
- case ZN_E_ARC:
- count = ZnMapInfoNumArcs(master->map_info);
- break;
- }
- l = Tcl_NewIntObj(count);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * get
- */
- case ZN_MI_GET:
- {
- int insert;
-
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo get type index");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (insert < 0) {
- insert = 0;
- }
- if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
- "elementType", 0, &index2) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum e_types) index2) {
- case ZN_E_LINE:
- {
- ZnMapInfoLineStyle line_style;
- ZnDim line_width;
- ZnPos x_to, y_to;
- ZnMapInfoGetLine(master->map_info, insert, NULL, &line_style,
- &line_width, &x, &y, &x_to, &y_to);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x_to));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y_to));
- }
- break;
- case ZN_E_SYMBOL:
- {
- char symbol;
- ZnMapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol));
- }
- break;
- case ZN_E_TEXT:
- {
- char *text;
- ZnMapInfoTextStyle text_style;
- ZnMapInfoLineStyle line_style;
- ZnMapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style,
- &x, &y, &text);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoTextStyleToString(text_style), -1));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(text, -1));
- }
- break;
- case ZN_E_ARC:
- {
- ZnMapInfoLineStyle line_style;
- ZnDim line_width, radius;
- ZnPos start, extent;
- ZnMapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width,
- &x, &y, &radius, &start, &extent);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(radius));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(start));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(extent));
- }
- break;
- }
- }
- break;
- /*
- * remove
- */
- case ZN_MI_REMOVE:
- {
- int insert;
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (insert < 0) {
- insert = 0;
- }
- if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
- "elementType", 0, &index2) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum e_types) index2) {
- case ZN_E_LINE:
- ZnMapInfoRemoveLine(master->map_info, insert);
- break;
- case ZN_E_SYMBOL:
- ZnMapInfoRemoveSymbol(master->map_info, insert);
- break;
- case ZN_E_TEXT:
- ZnMapInfoRemoveText(master->map_info, insert);
- break;
- case ZN_E_ARC:
- ZnMapInfoRemoveArc(master->map_info, insert);
- break;
- }
- UpdateMapInfoClients(master);
- }
- break;
- /*
- * scale
- */
- case ZN_MI_SCALE:
- {
- double factor;
-
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo scale factor");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &factor) == TCL_ERROR) {
- return TCL_ERROR;
- }
- ZnMapInfoScale(master->map_info, factor);
- UpdateMapInfoClients(master);
- }
- break;
- /*
- * translate
- */
- case ZN_MI_TRANSLATE:
- {
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "mapInfo translate xAmount yAmount");
- return TCL_ERROR;
- }
- master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
- if (master == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &x) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp, args[4], &y) == TCL_ERROR) {
- return TCL_ERROR;
- }
- ZnMapInfoTranslate(master->map_info, x, y);
- UpdateMapInfoClients(master);
- }
- break;
- }
-
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * VideomapObjCmd --
- *
- *
- *----------------------------------------------------------------------
- */
-int
-ZnVideomapObjCmd(ClientData client_data,
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- Tcl_Obj *CONST args[])
-{
- ZnList ids;
- int index;
- int *id_array, id_num, i;
- Tcl_Obj *l;
-#ifdef PTK_800
- static char *sub_cmd_strings[] =
-#else
- static CONST char *sub_cmd_strings[] =
-#endif
- {
- "ids", "load", NULL
- };
- enum sub_cmds {
- ZN_V_IDS, ZN_V_LOAD
- };
-
-
- if (argc < 2) {
- Tcl_WrongNumArgs(interp, 1, args, "?subCmd? filename $args?");
- return TCL_ERROR;
- }
-
- if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings,
- "subCmd", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-
- switch((enum sub_cmds) index) {
- /*
- * ids
- */
- case ZN_V_IDS:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args,"ids filename");
- return TCL_ERROR;
- }
- ids = ZnMapInfoVideomapIds(Tcl_GetString(args[2]));
- if (ids == NULL) {
- Tcl_AppendResult(interp, "unable to look at videomap file \"",
- Tcl_GetString(args[2]), "\"", NULL);
- return TCL_ERROR;
- }
- id_array = ZnListArray(ids);
- id_num = ZnListSize(ids);
- l = Tcl_GetObjResult(interp);
- for (i = 0; i < id_num; i++) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(id_array[i]));
- }
- ZnListFree(ids);
- }
- break;
- /*
- * load
- */
- case ZN_V_LOAD:
- {
- ZnMapInfoId map_info;
- int insert;
-
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo");
- return TCL_ERROR;
- }
- if (Tcl_GetIntFromObj(interp, args[3], &insert) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (insert < 0) {
- insert = 0;
- }
- if (ZnCreateMapInfo(interp, Tcl_GetString(args[4]), &map_info) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (ZnMapInfoGetVideomap(map_info, Tcl_GetString(args[2]), insert) == TCL_ERROR) {
- Tcl_AppendResult(interp, "unable to load videomap file \"",
- Tcl_GetString(args[2]), ":",
- Tcl_GetString(args[3]), "\"", NULL);
- return TCL_ERROR;
- }
- ZnUpdateMapInfoClients(map_info);
- }
- break;
- }
-
- return TCL_OK;
-}
diff --git a/generic/MapInfo.h b/generic/MapInfo.h
deleted file mode 100644
index edecd4a..0000000
--- a/generic/MapInfo.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * MapInfo.h -- Public include file for MapInfo interface.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _MapInfo_h
-#define _MapInfo_h
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-
-#include "Types.h"
-#include "List.h"
-#include "Geo.h"
-
-
-/*
- *-----------------------------------------------------------------------
- *
- * New types
- *
- *-----------------------------------------------------------------------
- */
-
-typedef void *ZnMapInfoId;
-
-typedef enum {
- ZnMapInfoLineSimple,
- ZnMapInfoLineDashed,
- ZnMapInfoLineDotted,
- ZnMapInfoLineMixed,
- ZnMapInfoLineMarked
-} ZnMapInfoLineStyle;
-
-typedef enum {
- ZnMapInfoNormalText,
- ZnMapInfoUnderlinedText
-} ZnMapInfoTextStyle;
-
-
-void ZnMapInfoGetLine(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
- ZnMapInfoLineStyle *line_style, ZnDim *line_width,
- ZnPos *x_from, ZnPos *y_from,
- ZnPos *x_to, ZnPos *y_to);
-unsigned int ZnMapInfoNumLines(ZnMapInfoId map_info);
-void ZnMapInfoGetMarks(ZnMapInfoId map_info, unsigned int index,
- ZnPoint **marks, unsigned int *num_marks);
-void ZnMapInfoGetSymbol(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
- ZnPos *x, ZnPos *y, char *symbol);
-unsigned int ZnMapInfoNumSymbols(ZnMapInfoId map_info);
-void ZnMapInfoGetText(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
- ZnMapInfoTextStyle *text_style,
- ZnMapInfoLineStyle *line_style,
- ZnPos *x, ZnPos *y, char **text);
-unsigned int ZnMapInfoNumTexts(ZnMapInfoId map_info);
-void ZnMapInfoGetArc(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
- ZnMapInfoLineStyle *line_style, ZnDim *line_width,
- ZnPos *center_x, ZnPos *center_y, ZnDim *radius,
- ZnReal *start_angle, ZnReal *extend);
-unsigned int ZnMapInfoNumArcs(ZnMapInfoId map_info);
-
-
-typedef void (*ZnMapInfoChangeProc)(ClientData client_data, ZnMapInfoId map_info);
-
-ZnMapInfoId ZnGetMapInfo(Tcl_Interp *interp, char *name,
- ZnMapInfoChangeProc proc, ClientData client_data);
-void ZnFreeMapInfo(ZnMapInfoId map_info, ZnMapInfoChangeProc proc,
- ClientData client_data);
-
-int ZnMapInfoObjCmd(ClientData client_data, Tcl_Interp *interp,
- int argc, Tcl_Obj *CONST args[]);
-int ZnVideomapObjCmd(ClientData client_data, Tcl_Interp *interp,
- int argc, Tcl_Obj *CONST args[]);
-
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _MapInfo_h */
diff --git a/generic/OverlapMan.c b/generic/OverlapMan.c
deleted file mode 100644
index d09977f..0000000
--- a/generic/OverlapMan.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * OverlapMan.c -- Track label overlap avoidance manager implementation.
- *
- * Authors :
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * TODO:
- *
- * The tracks should be identified by their ids not their
- * structure pointer. This would enable an easy interface
- * between the overlap manager and the applications when
- * dealing with tracks.
- */
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-#include "OverlapMan.h"
-#if defined(__APPLE__)
-#include <stdlib.h>
-#else
-#include "malloc.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-#ifdef _WIN32
-# ifndef __GNUC__
-# pragma warning(disable : 4996)
-# endif
-#endif
-
-#define signe(a) ((a) < (0) ? (-1) : (1))
-#define abs(a) ((a) < (0) ? -(a) : (a))
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338327
-#endif
-#ifndef M_PI_2
-#define M_PI_2 1.57079632679489661923
-#endif
-#ifndef M_PI_4
-#define M_PI_4 0.78539816339744830962
-#endif
-#define DegreesToRadian(angle) \
- (M_PI * (double) (angle) / 180.0)
-#define RadianToDegrees(angle) \
- (fmod((angle) * 180.0 / M_PI, 360.0))
-#define RadianToDegrees360(angle) \
- (fmod(RadianToDegrees(angle)+360.0,360.0))
-
-
-#define NB_ALLOC 20
-#define COEF1 0.5 /* coef of second repulsion point */
-#define COEF2 0.1 /* coef of second repulsion point */
-
-#define DELTA_T 0.1 /* integration step for Euler method */
-#define FALSE 0
-#define TRUE 1
-
-
-typedef int BOOLEAN;
-
-typedef struct _INFOS {
- void* id;
- int x;
- int y;
- int vv_dx;
- int vv_dy;
- /* Fri Oct 13 15:15:31 2000 int label_x;
- int label_y;
- int label_width;
- int label_height;*/
- int rho;
- int theta;
- int visibility;
- BOOLEAN New_Track;
- int dx;
- int dy;
- double alpha;
- double alpha_point;
- BOOLEAN Refresh;
-} INFOS;
-
-typedef struct _ZINCS {
- void *rw;
- void *(*_next_track)();
- void (*_set_label_angle)();
- INFOS *infos;
- int NBinfos;
- int NBalloc_infos;
-} ZINCS;
-
-/*
- * Definition of tunable parameters
- */
-
-
-/*
- * real parameters adresse
- */
-static double K0 = 2100.0; /* Repulsion factor */
-static double K0min = 500.0;
-static double K0max = 3000.0;
-
-static double n0 = 2.10; /* Repulsion exponent */
-static double n0min = 2.0;
-static double n0max = 3.0;
-
-static double K1 = 6.0; /* Friction factor */
-static double K1min = 1.0;
-static double K1max = 10.0;
-
-static double K2 = 6.0; /* Drawback forces factor */
-static double K2min = 1.0;
-static double K2max = 10.0;
-
-static double K3 = 4.0; /* Keep in view forces factor */
-static double K3min = 1.0;
-static double K3max = 10.0;
-
-/*
- * accessor structure need for generic set/get method
- */
-typedef struct _OMPARAM {
- int type;
- int size;
- char *name;
- void *data;
- BOOLEAN rw; /* 1 means readwrite, 0 means read only */
-} OMPARAM, *pOMPARAM;
-
-/*
- * Global vars.
- *
- */
-static OMPARAM OmParamAccess[] = {
- { OM_PARAM_DOUBLE, sizeof(double), "repulsion", &K0, 1 },
- { OM_PARAM_DOUBLE, sizeof(double), "repulsion_bearing", &n0, 1 },
- { OM_PARAM_DOUBLE, sizeof(double), "friction", &K1, 1 },
- { OM_PARAM_DOUBLE, sizeof(double), "best_position_attraction", &K2, 1 },
- { OM_PARAM_DOUBLE, sizeof(double), "screen_edge_repulsion", &K3, 1 },
- { OM_PARAM_DOUBLE, sizeof(double), "min_repulsion", &K0min, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "min_repulsion_bearing", &n0min, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "min_friction", &K1min, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "min_best_position_attraction", &K2min, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "min_screen_edge_repulsion", &K3min, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "max_repulsion", &K0max, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "max_repulsion_bearing", &n0max, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "max_friction", &K1max, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "max_best_position_attraction", &K2max, 0 },
- { OM_PARAM_DOUBLE, sizeof(double), "max_screen_edge_repulsion", &K3max, 0 },
- { OM_PARAM_END, 0, "", NULL, 0 }
-};
-
-static int NbParam = sizeof(OmParamAccess) / sizeof(OMPARAM) - 1;
-static ZINCS *wr = NULL;
-static int NBzincs=0;
-static int NBalloc_zincs=0;
-static INFOS info1;
-
-
-/*
- * Square of the distance (between two label centers) below which
- * the repulsion is not computed.
- */
-static double limit_distance = 6.0;
-
-/*
- * Square of the minimum distance (between two label centers)
- * considered during initialisation of the leaders.
- */
-static double placing_min_dist = 11000.0;
-
-/*
- * Angle step between two placement trials.
- */
-static double placing_step = M_PI/6.0;
-
-
-/*
- ****************************************************************************
- *
- * FindPosW --
- * Find the zinc position in the database,
- * if not found, gets the positon to insert in.
- *
- ****************************************************************************
- */
-static BOOLEAN
-FindPosW(void *w,
- int *mid)
-{
- int left=0;
- int right=NBzincs-1;
-
- if (w < wr[0].rw) {
- *mid = 0;
- return FALSE;
- }
- if (w > wr[right].rw) {
- *mid = right+1;
- return FALSE;
- }
- if (w == wr[right].rw) {
- *mid = right;
- return TRUE;
- }
-
- *mid = (right + left) / 2;
- while ((right > left+1) && (wr[*mid].rw != w)) {
- if (w > wr[*mid].rw) {
- left = *mid;
- }
- else {
- right = *mid;
- }
- *mid = (right + left) / 2;
- }
- if (wr[*mid].rw == w) {
- return TRUE;
- }
- else {
- (*mid)++;
- return FALSE;
- }
-}
-
-
-/*
- ****************************************************************************
- *
- * AllocW --
- * Allocate cells in database for the specified zinc.
- *
- ****************************************************************************
- */
-static void
-AllocW(void *w,
- int pos)
-{
- int i;
-
- if (NBzincs == NBalloc_zincs) {
- NBalloc_zincs += NB_ALLOC;
- wr = realloc(wr, sizeof(ZINCS) * NBalloc_zincs);
- }
-
- for (i = NBzincs-1; i >= pos; i--) {
- memcpy((char *) &wr[i+1], (char *) &wr[i], sizeof(ZINCS));
- }
- /*memcpy((char *)&wr[pos+1], (char *)&wr[pos], (NBzincs-pos) * sizeof(ZINCS) );*/
-
- NBzincs++;
- wr[pos].rw = w;
- wr[pos].infos = NULL;
- wr[pos].NBinfos = 0;
- wr[pos].NBalloc_infos = 0;
-}
-
-
-/*
- ***************************************************************************
- *
- * ProjToAngle --
- * Compute an angle from dx and dy projections.
- *
- ***************************************************************************
- */
-static double
-ProjToAngle(int dx,
- int dy)
-{
- if (dx == 0) {
- if (dy < 0) {
- return -M_PI_2;
- }
- else {
- if (dy > 0) {
- return M_PI_2;
- }
- else {
- return 0;
- }
- }
- }
- if (dx > 0) {
- return atan((double) (dy) / (double) (dx));
- }
- if (dx < 0) {
- return atan((double) (dy) / (double) (dx)) + M_PI;
- }
-
- return 0.0;
-}
-
-
-/*
- ****************************************************************************
- *
- * OmInit --
- * Called only once to initialize some internal data.
- *
- ****************************************************************************
- */
-void
-OmInit()
-{
- /* printf("OmInit\n");*/
-}
-
-
-/*
- ****************************************************************************
- *
- * OmRegister --
- * Create a database entry for the specified zinc.
- *
- ****************************************************************************
- */
-void
-OmRegister(void *w,
- void *(*_fnext_track)(void *, void *,
- int *, int *,
- int *, int *,
- int *, int *,
- int *, int *,
- int *, int *),
- void (*_fset_label_angle)(void *, void *, int, int),
- void (*_fquery_label_pos)(void *, void *, int,
- int *, int *, int *, int *))
-{
- int iw=0;
- BOOLEAN found=FALSE;
-
- if (NBzincs > 0) {
- found = FindPosW(w, &iw);
- }
- if (found == FALSE) {
- AllocW(w, iw);
- }
- wr[iw]._next_track= _fnext_track;
- wr[iw]._set_label_angle= _fset_label_angle;
-}
-
-
-/*
- ****************************************************************************
- *
- * OmUnregister --
- * Cancel database information about the specified zinc.
- *
- ****************************************************************************
- */
-void
-OmUnregister(void *w)
-{
- int i;
-
- if (FindPosW(w, &i) == TRUE) {
- free(wr[i].infos);
- memcpy((char *) &wr[i], (char *) &wr[i+1], (NBzincs-i-1)*sizeof(ZINCS));
- NBzincs--;
- }
-}
-
-
-/*
- ***************************************************************************
- *
- * FindPosId --
- * Find track position in the database,
- * if not found gets the positon to insert in.
- *
- ***************************************************************************
- */
-static BOOLEAN
-FindPosId(int iw,
- void *id,
- int *mid)
-{
- int left=0;
- int right= wr[iw].NBinfos-1;
-
- if (id < wr[iw].infos[0].id) {
- *mid = 0;
- return FALSE;
- }
- if (id > wr[iw].infos[right].id) {
- *mid = right+1;
- return FALSE;
- }
- if (id == wr[iw].infos[right].id) {
- *mid = right;
- return TRUE;
- }
-
- *mid = (right + left) / 2;
- while ((right > left+1) && (wr[iw].infos[*mid].id != id)) {
- if (id > wr[iw].infos[*mid].id) {
- left = *mid;
- }
- else {
- right = *mid;
- }
- *mid = (right + left) / 2;
- }
- if (wr[iw].infos[*mid].id == id) {
- return TRUE;
- }
- else {
- (*mid)++;
- return FALSE;
- }
-}
-
-
-/*
- ***************************************************************************
- *
- * SetTrackInitValues --
- * Set initial label values for a track.
- *
- ***************************************************************************
- */
-static void
-SetTrackInitValues()
-{
- info1.alpha = ProjToAngle(info1.vv_dx, info1.vv_dy) - 3.0 * M_PI_4;
- info1.dx = (int) (info1.rho * cos(info1.alpha));
- info1.dy = (int) (info1.rho * sin(info1.alpha));
- info1.alpha_point = 0.0;
-}
-
-
-/*
- ***************************************************************************
- * SetTrackCurrentValues --
- * Update label values for a track.
- *
- ***************************************************************************
- */
-static void
-SetTrackCurrentValues(int iw,
- int pos)
-{
- info1.New_Track = FALSE;
- info1.alpha_point = wr[iw].infos[pos].alpha_point;
-}
-
-
-/*
- ***************************************************************************
- *
- * PutTrackLoaded --
- * Put track labels information into database.
- *
- ***************************************************************************
- */
-static void
-PutTrackLoaded(int iw)
-{
- int pos = 0, i;
- BOOLEAN found = FALSE;
-
- if (wr[iw].NBinfos > 0) {
- found = FindPosId(iw, info1.id, &pos);
- }
- if (found == FALSE) {
- /*
- * New track.
- */
- if (wr[iw].NBinfos == wr[iw].NBalloc_infos) {
- wr[iw].NBalloc_infos += NB_ALLOC;
- wr[iw].infos = realloc((void *) wr[iw].infos,
- sizeof(INFOS)*wr[iw].NBalloc_infos);
- }
-
- if (pos < wr[iw].NBinfos) {
- for(i = wr[iw].NBinfos-1; i >= pos; i--) {
- memcpy((char *) &(wr[iw].infos[i+1]), (char *) &(wr[iw].infos[i]),
- sizeof(INFOS));
- }
- /* memcpy((char *) &(wr[iw].infos[pos+1]), (char *) &(wr[iw].infos[pos]),
- (wr[iw].NBinfos-pos)*sizeof(INFOS) );*/
- }
-
- info1.New_Track = TRUE;
- SetTrackInitValues(iw, pos);
-
- wr[iw].NBinfos++;
- }
- else {
- if (info1.visibility == FALSE) {
- SetTrackInitValues( iw, pos);
- }
- else {
- SetTrackCurrentValues(iw, pos);
- }
- }
-
- memcpy((char *) &(wr[iw].infos[pos]), (char *) &info1, sizeof(INFOS));
-}
-
-
-/*
- ***************************************************************************
- *
- * ReadTracks --
- * Get track labels information from zinc.
- *
- ***************************************************************************
- */
-static void
-ReadTracks(int iw)
-{
- int i=0;
- int trash1; /* dummy variable : received unused data */
-
- for (i = 0; i < wr[iw].NBinfos; i++) {
- wr[iw].infos[i].Refresh = FALSE;
- }
-
- info1.id = NULL;
- while ((info1.id = (*wr[iw]._next_track)(wr[iw].rw, info1.id,
- &info1.x, &info1.y,
- &info1.vv_dx, &info1.vv_dy,
- /* Fri Oct 13 15:15:48 2000
- * &info1.label_x, &info1.label_y,
- * &info1.label_width, &info1.label_height,
- */
- &info1.rho, &info1.theta,
- &info1.visibility,
- &trash1,&trash1,&trash1))) {
- info1.alpha = (ProjToAngle(info1.vv_dx, info1.vv_dy ) - M_PI_2 -
- DegreesToRadian(info1.theta));
- info1.dx = (int) (info1.rho * cos(info1.alpha));
- info1.dy = (int) (info1.rho * sin(info1.alpha));
- info1.Refresh = TRUE;
- /* printf("OverlapMan(Om): ReadTracks id[%-10d], x[%4.4i], y[%4.4i], \
- vv_dx[%4.4i], vv_dy[%4.4i], rho[%-3.3d], theta[%-3.3d], visi[%d]\n",
- (int)info1.id,info1.x, info1.y, info1.vv_dx,info1.vv_dy,
- info1.rho,info1.theta,info1.visibility); */
- PutTrackLoaded(iw);
- }
-
- i = 0;
- while (i < wr[iw].NBinfos) {
- /*
- * Delete non refreshed tracks from database.
- */
- if (wr[iw].infos[i].Refresh == FALSE) {
- memcpy((char *) &(wr[iw].infos[i]), (char *) &(wr[iw].infos[i+1]),
- (wr[iw].NBinfos-i-1)*sizeof(INFOS));
- wr[iw].NBinfos--;
- }
- else {
- i++;
- }
- }
-}
-
-/*
- ***************************************************************************
- *
- * OmSetNParam --
- * Return 1 if ok, anything else if nok (non existing parameters,
- * wrong type).
- *
- ***************************************************************************
- */
-int
-OmSetNParam(char *name, /* parameter's name */
- void *value)
-{
- int accessid = 0;
- int status = 0;
-
- while (OmParamAccess[accessid].type != OM_PARAM_END) {
- if (!strcmp(name, OmParamAccess[accessid].name)) {
- /* a parameter named name has been found */
- if (OmParamAccess[accessid].rw) {
- memcpy(OmParamAccess[accessid].data, value,
- (unsigned int) OmParamAccess[accessid].size);
- status = 1;
- break;
- }
- else {
- status = -1 ; /* data is readonly */
- };
- };
- ++accessid;
- };
- return(status);
-}
-
-/*
- ***************************************************************************
- *
- * OmGetNParam --
- * Return 1 if ok, anything else if nok (non existing parameters,
- * wrong type).
- *
- ***************************************************************************
- */
-int
-OmGetNParam(char *name, /* parameter's name */
- void *ptvalue)
-{
- int accessid = 0;
- int status = 0;
-
- while (OmParamAccess[accessid].type != OM_PARAM_END) {
- if (!strcmp(name, OmParamAccess[accessid].name)) {
- /* a parameter named "name" has been found */
- memcpy(ptvalue, OmParamAccess[accessid].data,
- (unsigned int) OmParamAccess[accessid].size);
- status = 1;
- break;
- };
- ++accessid;
- };
- return(status);
-}
-
-/*
- ***************************************************************************
- *
- * OmGetNParamList --
- * Return 1 and next index if remains to read, the current param
- * being written in current_param. Return 0 if end of list.
- *
- ***************************************************************************
- */
-int
-OmGetNParamList(OmParam *current_param, int *idx_next)
-{
- int status = 0 ;
- pOMPARAM cparam ;
- if (*idx_next < NbParam) {
- cparam = &OmParamAccess[*idx_next];
- current_param->type = cparam->type ;
- strcpy(current_param->name, cparam->name);
- /* printf("value of parameter is %f \n", *((double *)(cparam->data)));
- printf("adresse de K0 %x \n", (int)&K0); */
- ++(*idx_next) ;
- status = 1;
- };
- return(status);
-}
-
-void
-OmSetParam(double OmKrepulsion,
- double OmKrepulsionBearing,
- double OmKfriction,
- double OmKbestPositionAttraction,
- double OmKscreenEdgeRepulsion)
-{
- K0 = OmKrepulsion;
- n0 = OmKrepulsionBearing;
- K1 = OmKfriction;
- K2 = OmKbestPositionAttraction;
- K3 = OmKscreenEdgeRepulsion;
-}
-
-void
-OmGetParam(double *OmKrepulsion,
- double *OmKrepulsionBearing,
- double *OmKfriction,
- double *OmKbestPositionAttraction,
- double *OmKscreenEdgeRepulsion)
-{
- *OmKrepulsion = K0;
- *OmKrepulsionBearing = n0;
- *OmKfriction = K1;
- *OmKbestPositionAttraction = K2;
- *OmKscreenEdgeRepulsion = K3;
-}
-
-void
-OmGetMinParam(double *OmKminRepulsion,
- double *OmKminRepulsionBearing,
- double *OmKminFriction,
- double *OmKminBestPositionAttraction,
- double *OmKminScreenEdgeRepulsion)
-{
- *OmKminRepulsion = K0min;
- *OmKminRepulsionBearing = n0min;
- *OmKminFriction = K1min;
- *OmKminBestPositionAttraction = K2min;
- *OmKminScreenEdgeRepulsion = K3min;
-}
-
-void
-OmGetMaxParam(double *OmKmaxRepulsion,
- double *OmKmaxRepulsionBearing,
- double *OmKmaxFriction,
- double *OmKmaxBestPositionAttraction,
- double *OmKmaxScreenEdgeRepulsion)
-{
- *OmKmaxRepulsion = K0max;
- *OmKmaxRepulsionBearing = n0max;
- *OmKmaxFriction = K1max;
- *OmKmaxBestPositionAttraction = K2max;
- *OmKmaxScreenEdgeRepulsion = K3max;
-}
-
-
-/*
- ***************************************************************************
- *
- * SetupLeaderPosition --
- * Setup leader position for new tracks.
- *
- ***************************************************************************
- */
-static void
-SetupLeaderPosition(int iw,
- int ip)
-{
- double X10, Y10, X20, Y20;
- double D, k, Fx0, Fy0;
- int jp;
- double alpha;
- BOOLEAN ok = FALSE;
- double dx = 0, dy = 0;
-
- Fx0 = 0.0;
- Fy0 = 0.0;
-
- for (jp = 0; jp < wr[iw].NBinfos; jp++) {
- if (wr[iw].infos[jp].New_Track == FALSE) {
- X10 = (double) (wr[iw].infos[ip].x - wr[iw].infos[jp].x - wr[iw].infos[jp].dx);
- Y10 = (double) (wr[iw].infos[ip].y - wr[iw].infos[jp].y - wr[iw].infos[jp].dy);
- X20 = ((double) (wr[iw].infos[ip].x - wr[iw].infos[jp].x) -
- (double) (wr[iw].infos[jp].dx) * COEF1 +
- (double) (wr[iw].infos[jp].dy) * COEF2);
- Y20 = ((double) (wr[iw].infos[ip].y - wr[iw].infos[jp].y) -
- (double) (wr[iw].infos[jp].dy) * COEF1 -
- (double) (wr[iw].infos[jp].dx) * COEF2);
-
- D = X10 * X10 + Y10 * Y10;
- if (D > limit_distance) {
- k = K0 / (sqrt(D) * pow(D, n0 - 1.0));
- Fx0 += X10 * k;
- Fy0 += Y10 * k;
- }
- D = X20 * X20 + Y20 * Y20;
- if (D > limit_distance) {
- k = K0 / (sqrt(D) * pow(D, n0 - 1.0));
- Fx0 += X20 * k;
- Fy0 += Y20 * k;
- }
- }
- }
- if ((Fx0 == 0) && (Fy0 == 0)) {
- Fx0 = 1;
- }
-
- k = (double) (wr[iw].infos[ip].rho) / sqrt(Fx0*Fx0 + Fy0*Fy0);
-
- wr[iw].infos[ip].dx = (int) (Fx0 * k);
- wr[iw].infos[ip].dy = (int) (Fy0 * k);
- wr[iw].infos[ip].alpha = ProjToAngle((int) (Fx0*k), (int) (Fy0*k));
-
- alpha = wr[iw].infos[ip].alpha;
- while ((alpha < wr[iw].infos[ip].alpha + 2.0*M_PI) && (ok == FALSE)) {
- dx = (double) (wr[iw].infos[ip].rho) * cos(alpha);
- dy = (double) (wr[iw].infos[ip].rho) * sin(alpha);
- ok = TRUE;
-
- for (jp = 0; jp < wr[iw].NBinfos; jp++) {
- if (wr[iw].infos[jp].New_Track == FALSE) {
- X10 = (double) (wr[iw].infos[ip].x + (int) dx -
- wr[iw].infos[jp].x - wr[iw].infos[jp].dx);
- Y10 = (double) (wr[iw].infos[ip].y + (int) dy -
- wr[iw].infos[jp].y - wr[iw].infos[jp].dy);
- D = X10 * X10 + Y10 * Y10;
- if (D < placing_min_dist) {
- ok = FALSE;
- }
- }
- }
- alpha += placing_step;
- }
- if (ok) {
- wr[iw].infos[ip].dx = (int) dx;
- wr[iw].infos[ip].dy = (int) dy;
- wr[iw].infos[ip].alpha = ProjToAngle((int) dx, (int) dy);
- }
-}
-
-
-/*
- ***************************************************************************
- *
- * ComputeRepulsion --
- * Compute the moment of the repulsion forces of all the other
- * tracks.
- *
- ***************************************************************************
- */
-static double
-ComputeRepulsion(int iw,
- int ip)
-{
- double X10, Y10, X00, Y00, X11, Y11, X01, Y01;
- double D0, D1, k, Fx0, Fy0, Fx1, Fy1;
- int jp;
-
- X00 = (double) (wr[iw].infos[ip].x + wr[iw].infos[ip].dx);
- Y00 = (double) (wr[iw].infos[ip].y + wr[iw].infos[ip].dy);
- X01 = ((double) (wr[iw].infos[ip].x) +
- (double) (wr[iw].infos[ip].dx) * COEF1 -
- (double) (wr[iw].infos[ip].dy) * COEF2);
- Y01 = ((double) (wr[iw].infos[ip].y) +
- (double) (wr[iw].infos[ip].dy) * COEF1 +
- (double) (wr[iw].infos[ip].dx) * COEF2);
- Fx0 = 0.0;
- Fy0 = 0.0;
- Fx1 = 0.0;
- Fy1 = 0.0;
-
- for (jp = 0; jp < wr[iw].NBinfos; jp++) {
- if ( ip != jp ) {
- X10 = (double) (wr[iw].infos[jp].x + wr[iw].infos[jp].dx);
- Y10 = (double) (wr[iw].infos[jp].y + wr[iw].infos[jp].dy);
- X11 = ((double) (wr[iw].infos[jp].x) +
- (double) (wr[iw].infos[jp].dx) * COEF1 -
- (double) (wr[iw].infos[jp].dy) * COEF2);
- Y11 = ((double) (wr[iw].infos[jp].y) +
- (double) (wr[iw].infos[jp].dy) * COEF1 +
- (double) (wr[iw].infos[jp].dx) * COEF2);
-
- D0 = (X10 - X00) * (X10 - X00) + (Y10 - Y00) * (Y10 - Y00);
- if (D0 > limit_distance) {
- k = K0 / (sqrt(D0) * pow(D0, n0 - 1.0));
- Fx0 += (X10 - X00) * k;
- Fy0 += (Y10 - Y00) * k;
- }
- D1 = (X11 - X01) * (X11 - X01) + (Y11 - Y01) * (Y11 - Y01);
- if (D1 > limit_distance) {
- k = K0 / (sqrt(D1) * pow(D1, n0 - 1.0));
- Fx1 += (X11 - X01) * k;
- Fy1 += (Y11 - Y01) * k;
- }
- }
- }
-
- return -((double) (wr[iw].infos[ip].dx) * Fy0 -
- (double) (wr[iw].infos[ip].dy) * Fx0 +
- (double) (wr[iw].infos[ip].dx) * COEF1 * Fy1 -
- (double) (wr[iw].infos[ip].dy) * COEF2 * Fy1 -
- (double) (wr[iw].infos[ip].dy) * COEF1 * Fx1 -
- (double) (wr[iw].infos[ip].dx) * COEF2 * Fx1);
-}
-
-
-/*
- ***************************************************************************
- *
- * ComputeFriction --
- * Compute the moment of the friction force.
- *
- ***************************************************************************
- */
-static double
-ComputeFriction(int iw,
- int ip)
-{
- return (double) (-K1 * wr[iw].infos[ip].alpha_point);
-}
-
-
-/*
- ***************************************************************************
- *
- * ComputeDrawback --
- * Compute the moment of the best positions drawback forces.
- *
- ***************************************************************************
- */
-static double
-ComputeDrawback(int iw,
- int ip)
-{
- int vx, vy, dx, dy;
- double m = 0;
- double nd = 1.0, nv = 1.0;
- double vi;
-
- vx = wr[iw].infos[ip].vv_dx;
- vy = wr[iw].infos[ip].vv_dy;
- dx = wr[iw].infos[ip].dx;
- dy = wr[iw].infos[ip].dy;
-
- if ((vx != 0) || (vy != 0)) {
- nv = sqrt((double)(vx * vx + vy * vy));
- }
- if ((dx != 0) || (dy != 0)) {
- nd = sqrt((double)(dx * dx + dy * dy));
- }
-
- vi = (double) (vx * dx + vy * dy)/(nd * nv);
- vi = vi <= -1.0 ? -1.0 : vi;
- vi = vi >= 1.0 ? 1.0 : vi;
- vi = 3 * M_PI_4 - acos(vi);
-
- if (vy * dx - vx * dy < 0) {
- m = -vi;
- }
- else {
- m = vi;
- }
-
- return (double) (-K2 * m);
-}
-
-
-/*
- ***************************************************************************
- *
- * ComputeDrawbackInView --
- * Compute the moment of the keep in view forces.
- *
- ***************************************************************************
- */
-static double
-DrawbackDirection(int vx,
- int vy,
- int dx,
- int dy)
-{
- double m=0;
- double nd=1.0, nv=1.0;
- double vi;
-
- if ((vx != 0) || (vy != 0)) {
- nv = sqrt((double)(vx * vx + vy * vy));
- }
- if ((dx != 0) || (dy != 0)) {
- nd = sqrt((double)(dx * dx + dy * dy));
- }
-
- vi = (double) (vx * dx + vy * dy)/(nd * nv);
- vi = vi <= -1.0 ? -1.0 : vi;
- vi = vi >= 1.0 ? 1.0 : vi;
- vi = acos(vi);
-
- if (vy * dx - vx * dy < 0) {
- m = vi;
- }
- else {
- m = - vi;
- }
-
- return (double) (-K3 * m);
-}
-
-
-static double
-ComputeDrawbackInView(int iw,
- int ip,
- int width,
- int height)
-{
- int r=50;
- int dx, dy;
- double Gamma=0;
-
- r = wr[iw].infos[ip].rho;
- dx = wr[iw].infos[ip].dx;
- dy = wr[iw].infos[ip].dy;
-
- if (abs(wr[iw].infos[ip].x) < r) {
- Gamma += DrawbackDirection(53, 0, dx, dy);
- }
- if (abs(wr[iw].infos[ip].x - width) < r) {
- Gamma += DrawbackDirection(-53, 0, dx, dy);
- }
- if (abs(wr[iw].infos[ip].y ) < r) {
- Gamma += DrawbackDirection(0, 53, dx, dy);
- }
- if (abs(wr[iw].infos[ip].y - height) < r) {
- Gamma += DrawbackDirection(0,- 53, dx, dy);
- }
-
- return (double) Gamma;
-}
-
-/*
- ***************************************************************************
- *
- * RefineSetup --
- * Refine setup for far spaced tracks.
- *
- ***************************************************************************
- */
-static void
-RefineSetup(int iw,
- int ip)
-{
- double acceleration;
- int i;
-
- for (i = 0; i <= 10; i++) {
- acceleration = ComputeRepulsion(iw, ip) + ComputeDrawback(iw, ip);
-
- if (acceleration > 100) {
- acceleration = 100;
- }
- if (acceleration < -100) {
- acceleration = -100;
- }
-
- wr[iw].infos[ip].alpha_point = acceleration * DELTA_T + wr[iw].infos[ip].alpha_point;
- wr[iw].infos[ip].alpha_point += ComputeFriction(iw, ip) * DELTA_T;
-
- if (wr[iw].infos[ip].alpha_point > 30) {
- wr[iw].infos[ip].alpha_point = 30;
- }
- if (wr[iw].infos[ip].alpha_point < -30) {
- wr[iw].infos[ip].alpha_point = -30;
- }
-
- wr[iw].infos[ip].alpha = wr[iw].infos[ip].alpha_point * DELTA_T + wr[iw].infos[ip].alpha;
- }
-}
-
-
-/*
- ***************************************************************************
- *
- * OmProcessOverlap --
- * Overlap Manager main function.
- *
- ***************************************************************************
- */
-void
-OmProcessOverlap(void *zinc,
- int width,
- int height,
- double scale)
-{
- double acceleration = 0.0;
- int ip, iw;
-
- if (NBzincs != 0 && FindPosW(zinc, &iw) == TRUE) {
- ReadTracks(iw);
-
- for (ip = 0; ip < wr[iw].NBinfos; ip++) {
- if (wr[iw].infos[ip].New_Track == TRUE) {
- SetupLeaderPosition(iw, ip);
- RefineSetup(iw, ip);
- wr[iw].infos[ip].New_Track = FALSE;
- }
- }
-
- for (ip = 0; ip < wr[iw].NBinfos; ip++) {
- acceleration = (ComputeRepulsion(iw, ip) + ComputeDrawback(iw, ip) +
- ComputeDrawbackInView(iw, ip, width, height));
-
- if (acceleration > 100) {
- acceleration = 100;
- }
- if (acceleration < -100) {
- acceleration = -100;
- }
-
- wr[iw].infos[ip].alpha_point += acceleration * DELTA_T ;
- wr[iw].infos[ip].alpha_point += ComputeFriction(iw, ip) * DELTA_T ;
-
- if (wr[iw].infos[ip].alpha_point > 30) {
- wr[iw].infos[ip].alpha_point = 30;
- }
- if (wr[iw].infos[ip].alpha_point < -30) {
- wr[iw].infos[ip].alpha_point = -30;
- }
-
- wr[iw].infos[ip].alpha += wr[iw].infos[ip].alpha_point * DELTA_T ;
- wr[iw].infos[ip].theta = (int) RadianToDegrees360(-wr[iw].infos[ip].alpha +
- ProjToAngle(wr[iw].infos[ip].vv_dx,
- wr[iw].infos[ip].vv_dy)
- - M_PI_2);
-
- /*
- if (wr[iw].infos[ip].theta > 75 && wr[iw].infos[ip].theta < 105) {
- if (wr[iw].infos[ip].alpha_point > 0) {
- wr[iw].infos[ip].theta = 105;
- }
- else {
- wr[iw].infos[ip].theta = 75;
- }
- }
-
- if (wr[iw].infos[ip].theta > 255 && wr[iw].infos[ip].theta < 285) {
- if (wr[iw].infos[ip].alpha_point > 0) {
- wr[iw].infos[ip].theta = 285;
- }
- else {
- wr[iw].infos[ip].theta = 255;
- }
- }
- */
-
- (*wr[iw]._set_label_angle) (wr[iw].rw, wr[iw].infos[ip].id,
- 120, wr[iw].infos[ip].theta);
- /* wr[iw].infos[ip].rho*/
- }
- }
-}
diff --git a/generic/OverlapMan.h b/generic/OverlapMan.h
deleted file mode 100644
index 85d22af..0000000
--- a/generic/OverlapMan.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * OverlapMan.h -- Track label overlap avoidance manager header file
- *
- * Authors :
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _OverlapMan_h
-#define _OverlapMan_h
-
-
-#include <string.h>
-#include <math.h>
-
-/*
- * Init code.
- */
-void
-OmInit();
-
-/*
- * This is the interface with the zinc widget. To substitute
- * a different overlap manager, it is necessary to conform to
- * this API.
- */
-void
-OmRegister(void *w,
- void *(*_fnext_track)(void *ptr,
- void *item,
- int *x, int *y,
- int *sv_dx, int *sv_dy,
- /* Fri Oct 13 15:16:13 2000
- int *label_x, int *label_y,
- int *label_width, int *label_height,
- */
- int *rho, int *theta,
- int *visibility,
- int *locked ,
- int *preferred_angle ,
- int *convergence_style),
- void (*_fset_label_angle)(void *ptr, void *item, int rho, int theta),
- void (*_fquery_label_pos)(void *ptr, void *item, int theta,
- int *x, int *y, int *w, int *h));
-void
-OmUnregister(void *w);
-void
-OmProcessOverlap(void *zinc,
- int width,
- int height,
- double scale);
-
-
-/*
- * Parameter data type which ease exchange of parameters between
- * Radar Image toolkit and Om library
- */
-#define OM_PARAM_END 0
-#define OM_PARAM_INT 1
-#define OM_PARAM_FLOAT 2
-#define OM_PARAM_DOUBLE 3
-#define OM_PARAM_STRING 4
-
-
-typedef struct {
- int type ; /* should be among OM_PARAM_ */
- char name[50] ;
-} OmParam ;
-
-
-/*
- * These are the generic overlap manager public functions used
- * to set/get any parameters that the Om library allow to modify
- * dynamically (tunable parameters)
- */
-
-/* OmSetNParam
- return 1 if ok , anythingelse if nok (non existing parameters ,
- wrong type) */
-int
-OmSetNParam(char *name, /* parameter's name */
- void *value);
-/* OmGetNParam
- return 1 if ok , anythingelse if nok (non existing parameters ,
- wrong type)
- */
-int
-OmGetNParam(char *name, /* parameter's name */
- void *ptvalue);
-
-/* OmGetNParamList
- return 1 and next index if remains to read, the current param
- being written in current_param
- return 0 if end of list and no param */
-int
-OmGetNParamList(OmParam *current_param, int *idx_next);
-
-
-#endif /* _OverlapMan_h */
diff --git a/generic/PostScript.c b/generic/PostScript.c
deleted file mode 100644
index 3465abe..0000000
--- a/generic/PostScript.c
+++ /dev/null
@@ -1,1873 +0,0 @@
-/*
- * PostScript.c -- Implementation of PostScript driver.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Tue Jan 3 13:17:17 1995
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1995 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * This code is based on tkCanvPs.c which is copyright:
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
- */
-
-/*
- **********************************************************************************
- *
- * Included files
- *
- **********************************************************************************
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#include <pwd.h>
-#endif
-#include <stdio.h>
-#include <sys/types.h>
-#include <time.h>
-#include <string.h>
-
-#include "Types.h"
-#include "Item.h"
-#include "Group.h"
-#include "PostScript.h"
-#include "WidgetInfo.h"
-#include "Geo.h"
-
-
-/*
- **********************************************************************************
- *
- * Constants.
- *
- **********************************************************************************
- */
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * One of the following structures is created to keep track of Postscript
- * output being generated. It consists mostly of information provided on
- * the widget command line.
- * WATCH! This structure must be kept in sync with the structure in
- * tkCanvPs.c, we share most of the code for emitting postscript and
- * this rely on sharing the structure.
- */
-typedef struct TkPostscriptInfo {
- int x, y, width, height; /* Area to print, in canvas pixel
- * coordinates. */
- int x2, y2; /* x+width and y+height. */
- char *pageXString; /* String value of "-pagex" option or NULL. */
- char *pageYString; /* String value of "-pagey" option or NULL. */
- double pageX, pageY; /* Postscript coordinates (in points)
- * corresponding to pageXString and
- * pageYString. Don't forget that y-values
- * grow upwards for Postscript! */
- char *pageWidthString; /* Printed width of output. */
- char *pageHeightString; /* Printed height of output. */
- double scale; /* Scale factor for conversion: each pixel
- * maps into this many points. */
- Tk_Anchor pageAnchor; /* How to anchor bbox on Postscript page. */
- int rotate; /* Non-zero means output should be rotated
- * on page (landscape mode). */
- char *fontVar; /* If non-NULL, gives name of global variable
- * containing font mapping information.
- * Malloc'ed. */
- char *colorVar; /* If non-NULL, give name of global variable
- * containing color mapping information.
- * Malloc'ed. */
- char *colorMode; /* Mode for handling colors: "monochrome",
- * "gray", or "color". Malloc'ed. */
- int colorLevel; /* Numeric value corresponding to colorMode:
- * 0 for mono, 1 for gray, 2 for color. */
- char *fileName; /* Name of file in which to write Postscript;
- * NULL means return Postscript info as
- * result. Malloc'ed. */
- char *channelName; /* If -channel is specified, the name of
- * the channel to use. */
- Tcl_Channel chan; /* Open channel corresponding to fileName. */
- Tcl_HashTable fontTable; /* Hash table containing names of all font
- * families used in output. The hash table
- * values are not used. */
- int prepass; /* Non-zero means that we're currently in
- * the pre-pass that collects font information,
- * so the Postscript generated isn't
- * relevant. */
- int prolog; /* Non-zero means output should contain
- * the file prolog.ps in the header. */
- /*
- * Below are extensions for Tkzinc.
- */
- ZnBBox bbox;
-} TkPostscriptInfo;
-
-/*
- * The table below provides a template that's used to process arguments
- * to the "postscript" command and fill in TkPostscriptInfo structures.
- */
-static Tk_ConfigSpec config_specs[] = {
- {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL},
- {TK_CONFIG_STRING, "-colormode", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL},
- {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL},
- {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL},
- {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL},
- {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, height), 0, NULL},
- {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL},
- {TK_CONFIG_STRING, "-pageheight", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL},
- {TK_CONFIG_STRING, "-pagewidth", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL},
- {TK_CONFIG_STRING, "-pagex", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL},
- {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL},
- {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL},
- {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, width), 0, NULL},
- {TK_CONFIG_PIXELS, "-x", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, x), 0, NULL},
- {TK_CONFIG_PIXELS, "-y", (char *) NULL, (char *) NULL,
- "", Tk_Offset(TkPostscriptInfo, y), 0, NULL},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, NULL}
-};
-
-/*
- *--------------------------------------------------------------
- *
- * GetPostscriptPoints --
- *
- * Given a string, returns the number of Postscript points
- * corresponding to that string.
- *
- * Results:
- * The return value is a standard Tcl return result. If
- * TCL_OK is returned, then everything went well and the
- * screen distance is stored at *doublePtr; otherwise
- * TCL_ERROR is returned and an error message is left in
- * the interp's result.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-static int
-GetPostscriptPoints(Tcl_Interp *interp,
- char *string,
- double *double_ptr)
-{
- char *end;
- double d;
-
- d = strtod(string, &end);
- if (end == string) {
- error:
- Tcl_AppendResult(interp, "bad distance \"", string, "\"", (char *) NULL);
- return TCL_ERROR;
- }
- while ((*end != '\0') && isspace(UCHAR(*end))) {
- end++;
- }
- switch (*end) {
- case 'c':
- d *= 72.0/2.54;
- end++;
- break;
- case 'i':
- d *= 72.0;
- end++;
- break;
- case 'm':
- d *= 72.0/25.4;
- end++;
- break;
- case 0:
- break;
- case 'p':
- end++;
- break;
- default:
- goto error;
- }
- while ((*end != '\0') && isspace(UCHAR(*end))) {
- end++;
- }
- if (*end != 0) {
- goto error;
- }
- *double_ptr = d;
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * ZnPostScriptCmd --
- *
- * This procedure is invoked to process the "postscript" options
- * of the widget command for zinc widgets. See the user
- * documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
-int
-ZnPostScriptCmd(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- TkPostscriptInfo ps_info;
- Tk_PostscriptInfo old_info;
- int result;
-#define STRING_LENGTH 400
- char string[STRING_LENGTH+1];
- CONST char *p;
- time_t now;
- size_t length;
- Tk_Window tkwin = wi->win;
- /*
- * Offset of lower-left corner of area to be marked up, measured
- * in canvas units from the positioning point on the page (reflects
- * anchor position). Initial values needed only to stop compiler
- * warnings.
- */
- int delta_x = 0, delta_y = 0;
- Tcl_HashSearch search;
- Tcl_HashEntry *entry;
- Tcl_DString buffer;
- char psenccmd[] = "::tk::ensure_psenc_is_loaded";
-
- /*
- *----------------------------------------------------------------
- * Initialize the data structure describing Postscript generation,
- * then process all the arguments to fill the data structure in.
- *----------------------------------------------------------------
- */
-#ifndef PTK
- result = Tcl_EvalEx(wi->interp, psenccmd, -1, TCL_EVAL_GLOBAL);
-#endif
- if (result != TCL_OK) {
- return result;
- }
- old_info = wi->ps_info;
- wi->ps_info = (Tk_PostscriptInfo) &ps_info;
- ps_info.x = (int) wi->origin.x;
- ps_info.y = (int) wi->origin.y;
- ps_info.width = -1;
- ps_info.height = -1;
- ps_info.pageXString = NULL;
- ps_info.pageYString = NULL;
- ps_info.pageX = 72*4.25;
- ps_info.pageY = 72*5.5;
- ps_info.pageWidthString = NULL;
- ps_info.pageHeightString = NULL;
- ps_info.scale = 1.0;
- ps_info.pageAnchor = TK_ANCHOR_CENTER;
- ps_info.rotate = 0;
- ps_info.fontVar = NULL;
- ps_info.colorVar = NULL;
- ps_info.colorMode = NULL;
- ps_info.colorLevel = 0;
- ps_info.fileName = NULL;
- ps_info.channelName = NULL;
- ps_info.chan = NULL;
- ps_info.prepass = 0;
- ps_info.prolog = 1;
- Tcl_InitHashTable(&ps_info.fontTable, TCL_STRING_KEYS);
- result = Tk_ConfigureWidget(wi->interp, wi->win, config_specs,
- argc-2, (CONST char **) argv+2,
- (char *) &ps_info,
- TK_CONFIG_ARGV_ONLY|TK_CONFIG_OBJS);
- if (result != TCL_OK) {
- goto cleanup;
- }
-
- if (ps_info.width == -1) {
- ps_info.width = Tk_Width(tkwin);
- }
- if (ps_info.height == -1) {
- ps_info.height = Tk_Height(tkwin);
- }
- ps_info.x2 = ps_info.x + ps_info.width;
- ps_info.y2 = ps_info.y + ps_info.height;
- ps_info.bbox.orig.x = ps_info.x;
- ps_info.bbox.orig.y = ps_info.y;
- ps_info.bbox.corner.x = ps_info.x2;
- ps_info.bbox.corner.y = ps_info.y2;
-
- if (ps_info.pageXString != NULL) {
- if (GetPostscriptPoints(wi->interp, ps_info.pageXString, &ps_info.pageX) != TCL_OK) {
- goto cleanup;
- }
- }
- if (ps_info.pageYString != NULL) {
- if (GetPostscriptPoints(wi->interp, ps_info.pageYString, &ps_info.pageY) != TCL_OK) {
- goto cleanup;
- }
- }
- if (ps_info.pageWidthString != NULL) {
- if (GetPostscriptPoints(wi->interp, ps_info.pageWidthString, &ps_info.scale) != TCL_OK) {
- goto cleanup;
- }
- ps_info.scale /= ps_info.width;
- }
- else if (ps_info.pageHeightString != NULL) {
- if (GetPostscriptPoints(wi->interp, ps_info.pageHeightString, &ps_info.scale) != TCL_OK) {
- goto cleanup;
- }
- ps_info.scale /= ps_info.height;
- }
- else {
- ps_info.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));
- ps_info.scale /= WidthOfScreen(Tk_Screen(tkwin));
- }
- switch (ps_info.pageAnchor) {
- case TK_ANCHOR_NW:
- case TK_ANCHOR_W:
- case TK_ANCHOR_SW:
- delta_x = 0;
- break;
- case TK_ANCHOR_N:
- case TK_ANCHOR_CENTER:
- case TK_ANCHOR_S:
- delta_x = -ps_info.width/2;
- break;
- case TK_ANCHOR_NE:
- case TK_ANCHOR_E:
- case TK_ANCHOR_SE:
- delta_x = -ps_info.width;
- break;
- }
- switch (ps_info.pageAnchor) {
- case TK_ANCHOR_NW:
- case TK_ANCHOR_N:
- case TK_ANCHOR_NE:
- delta_y = - ps_info.height;
- break;
- case TK_ANCHOR_W:
- case TK_ANCHOR_CENTER:
- case TK_ANCHOR_E:
- delta_y = -ps_info.height/2;
- break;
- case TK_ANCHOR_SW:
- case TK_ANCHOR_S:
- case TK_ANCHOR_SE:
- delta_y = 0;
- break;
- }
-
- if (ps_info.colorMode == NULL) {
- ps_info.colorLevel = 2;
- }
- else {
- length = strlen(ps_info.colorMode);
- if (strncmp(ps_info.colorMode, "monochrome", length) == 0) {
- ps_info.colorLevel = 0;
- }
- else if (strncmp(ps_info.colorMode, "gray", length) == 0) {
- ps_info.colorLevel = 1;
- }
- else if (strncmp(ps_info.colorMode, "color", length) == 0) {
- ps_info.colorLevel = 2;
- }
- else {
- Tcl_AppendResult(wi->interp, "bad color mode \"", ps_info.colorMode,
- "\": must be monochrome, ", "gray, or color",
- (char *) NULL);
- goto cleanup;
- }
- }
-
- if (ps_info.fileName != NULL) {
- /*
- * Check that -file and -channel are not both specified.
- */
- if (ps_info.channelName != NULL) {
- Tcl_AppendResult(wi->interp, "can't specify both -file", " and -channel",
- (char *) NULL);
- result = TCL_ERROR;
- goto cleanup;
- }
- /*
- * Check that we are not in a safe interpreter. If we are, disallow
- * the -file specification.
- */
- if (Tcl_IsSafe(wi->interp)) {
- Tcl_AppendResult(wi->interp, "can't specify -file in a", " safe interpreter",
- (char *) NULL);
- result = TCL_ERROR;
- goto cleanup;
- }
-
- p = Tcl_TranslateFileName(wi->interp, ps_info.fileName, &buffer);
- if (p == NULL) {
- goto cleanup;
- }
- ps_info.chan = Tcl_OpenFileChannel(wi->interp, p, "w", 0666);
- Tcl_DStringFree(&buffer);
- if (ps_info.chan == NULL) {
- goto cleanup;
- }
- }
-
- if (ps_info.channelName != NULL) {
- int mode;
-
- /*
- * Check that the channel is found in this interpreter and that it
- * is open for writing.
- */
- ps_info.chan = Tcl_GetChannel(wi->interp, ps_info.channelName, &mode);
- if (ps_info.chan == (Tcl_Channel) NULL) {
- result = TCL_ERROR;
- goto cleanup;
- }
- if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendResult(wi->interp, "channel \"", ps_info.channelName,
- "\" wasn't opened for writing", (char *) NULL);
- result = TCL_ERROR;
- goto cleanup;
- }
- }
-
- /*
- *--------------------------------------------------------
- * Make a pre-pass over all of the items, generating Postscript
- * and then throwing it away. The purpose of this pass is just
- * to collect information about all the fonts in use, so that
- * we can output font information in the proper form required
- * by the Document Structuring Conventions.
- *--------------------------------------------------------
- */
- ps_info.prepass = 1;
- result = wi->top_group->class->PostScript(wi->top_group, True, &ps_info.bbox);
- Tcl_ResetResult(wi->interp);
- /*
- * If an error occurred, just proceed with the main pass.
- * There's no need to report the error now; it can be
- * reported later (errors can happen later that don't
- * happen now, so we still have to check for errors later
- * anyway).
- */
- ps_info.prepass = 0;
-
- /*
- *--------------------------------------------------------
- * Generate the header and prolog for the Postscript.
- *--------------------------------------------------------
- */
- if (ps_info.prolog) {
- Tcl_AppendResult(wi->interp, "%!PS-Adobe-3.0 EPSF-3.0\n",
- "%%Creator: Tk Zinc Widget\n", (char *) NULL);
-#ifdef HAVE_PW_GECOS
- if (!Tcl_IsSafe(wi->interp)) {
- struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
- Tcl_AppendResult(wi->interp, "%%For: ",
- (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
- (char *) NULL);
- endpwent();
- }
-#endif /* HAVE_PW_GECOS */
- Tcl_AppendResult(wi->interp, "%%Title: Window ", Tk_PathName(tkwin), "\n",
- (char *) NULL);
- time(&now);
- /* INTL: Native. */
- Tcl_AppendResult(wi->interp, "%%CreationDate: ", ctime(&now), (char *) NULL);
- if (!ps_info.rotate) {
- sprintf(string, "%d %d %d %d", (int) (ps_info.pageX + ps_info.scale*delta_x),
- (int) (ps_info.pageY + ps_info.scale*delta_y),
- (int) (ps_info.pageX + ps_info.scale*(delta_x + ps_info.width) + 1.0),
- (int) (ps_info.pageY + ps_info.scale*(delta_y + ps_info.height) + 1.0));
- }
- else {
- sprintf(string, "%d %d %d %d",
- (int) (ps_info.pageX - ps_info.scale*(delta_y + ps_info.height)),
- (int) (ps_info.pageY + ps_info.scale*delta_x),
- (int) (ps_info.pageX - ps_info.scale*delta_y + 1.0),
- (int) (ps_info.pageY + ps_info.scale*(delta_x + ps_info.width) + 1.0));
- }
- Tcl_AppendResult(wi->interp, "%%BoundingBox: ", string, "\n", (char *) NULL);
- Tcl_AppendResult(wi->interp, "%%Pages: 1\n", "%%DocumentData: Clean7Bit\n",
- (char *) NULL);
- Tcl_AppendResult(wi->interp, "%%Orientation: ",
- ps_info.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL);
- p = "%%DocumentNeededResources: font ";
- for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
- entry = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(wi->interp, p, Tcl_GetHashKey(&ps_info.fontTable, entry),
- "\n", (char *) NULL);
- p = "%%+ font ";
- }
- Tcl_AppendResult(wi->interp, "%%EndComments\n\n", (char *) NULL);
-
- /*
- * Insert the prolog
- */
- Tcl_AppendResult(wi->interp, Tcl_GetVar(wi->interp,"::tk::ps_preamable",
- TCL_GLOBAL_ONLY), (char *) NULL);
-
- if (ps_info.chan != NULL) {
- Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
- Tcl_ResetResult(wi->interp);
- }
-
- /*
- *-----------------------------------------------------------
- * Document setup: set the color level and include fonts.
- *-----------------------------------------------------------
- */
- sprintf(string, "/CL %d def\n", ps_info.colorLevel);
- Tcl_AppendResult(wi->interp, "%%BeginSetup\n", string, (char *) NULL);
- for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
- entry = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(wi->interp, "%%IncludeResource: font ",
- Tcl_GetHashKey(&ps_info.fontTable, entry), "\n", (char *) NULL);
- }
- Tcl_AppendResult(wi->interp, "%%EndSetup\n\n", (char *) NULL);
-
- /*
- *-----------------------------------------------------------
- * Page setup: move to page positioning point, rotate if
- * needed, set scale factor, offset for proper anchor position,
- * and set clip region.
- *-----------------------------------------------------------
- */
- Tcl_AppendResult(wi->interp, "%%Page: 1 1\n", "save\n", (char *) NULL);
- sprintf(string, "%.1f %.1f translate\n", ps_info.pageX, ps_info.pageY);
- Tcl_AppendResult(wi->interp, string, (char *) NULL);
- if (ps_info.rotate) {
- Tcl_AppendResult(wi->interp, "90 rotate\n", (char *) NULL);
- }
- sprintf(string, "%.4g %.4g scale\n", ps_info.scale, -ps_info.scale);
- Tcl_AppendResult(wi->interp, string, (char *) NULL);
- sprintf(string, "%d %d translate\n", delta_x - ps_info.x, delta_y);
- Tcl_AppendResult(wi->interp, string, (char *) NULL);
- /*
- * Save the base matrix for further reference.
- */
- Tcl_AppendResult(wi->interp, "/InitialTransform matrix currentmatrix def\n", NULL);
-
- sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g",
- ps_info.x, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
- ps_info.x2, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
- ps_info.x2, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info),
- ps_info.x, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info));
- Tcl_AppendResult(wi->interp, string, " lineto closepath clip newpath\n", (char *) NULL);
- }
- if (ps_info.chan != NULL) {
- Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
- Tcl_ResetResult(wi->interp);
- }
-
- /*
- *---------------------------------------------------------------------
- * Iterate through all the items, having each relevant one draw itself.
- * Quit if any of the items returns an error.
- *---------------------------------------------------------------------
- */
- result = wi->top_group->class->PostScript(wi->top_group, False, &ps_info.bbox);
- if (result == TCL_ERROR) {
- goto cleanup;
- }
-
- /*
- *---------------------------------------------------------------------
- * Output page-end information, such as commands to print the page
- * and document trailer stuff.
- *---------------------------------------------------------------------
- */
- if (ps_info.prolog) {
- Tcl_AppendResult(wi->interp, "restore showpage\n\n", "%%Trailer\nend\n%%EOF\n",
- (char *) NULL);
- }
- if (ps_info.chan != NULL) {
- Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
- Tcl_ResetResult(wi->interp);
- }
-
- /*
- * Clean up ps_info to release malloc'ed stuff.
- */
- cleanup:
- if (ps_info.pageXString != NULL) {
- ckfree(ps_info.pageXString);
- }
- if (ps_info.pageYString != NULL) {
- ckfree(ps_info.pageYString);
- }
- if (ps_info.pageWidthString != NULL) {
- ckfree(ps_info.pageWidthString);
- }
- if (ps_info.pageHeightString != NULL) {
- ckfree(ps_info.pageHeightString);
- }
- if (ps_info.fontVar != NULL) {
- ckfree(ps_info.fontVar);
- }
- if (ps_info.colorVar != NULL) {
- ckfree(ps_info.colorVar);
- }
- if (ps_info.colorMode != NULL) {
- ckfree(ps_info.colorMode);
- }
- if (ps_info.fileName != NULL) {
- ckfree(ps_info.fileName);
- }
- if ((ps_info.chan != NULL) && (ps_info.channelName == NULL)) {
- Tcl_Close(wi->interp, ps_info.chan);
- }
- if (ps_info.channelName != NULL) {
- ckfree(ps_info.channelName);
- }
- Tcl_DeleteHashTable(&ps_info.fontTable);
- wi->ps_info = (Tk_PostscriptInfo) old_info;
- return result;
-}
-
-void
-ZnFlushPsChan(Tcl_Interp *interp,
- Tk_PostscriptInfo ps_info) {
- TkPostscriptInfo *psi = (TkPostscriptInfo *) ps_info;
- if (psi->chan != NULL) {
- Tcl_Write(psi->chan, Tcl_GetStringResult(interp), -1);
- Tcl_ResetResult(interp);
- }
-}
-
-int
-ZnPostscriptOutline(Tcl_Interp *interp,
- Tk_PostscriptInfo ps_info,
- Tk_Window tkwin,
- ZnDim line_width,
- ZnLineStyle line_style,
- ZnGradient *line_color,
- ZnImage line_pattern)
-{
- char string[41];
- char dashed[] = { 8 };
- char dotted[] = { 2, 5 };
- char mixed[] = { 8, 5, 2, 5 };
- char *pattern = NULL;
- int patlen = 0;
-
- sprintf(string, "%.15g setlinewidth\n", (double) line_width);
- Tcl_AppendResult(interp, string, NULL);
- /*
- * Setup the line style. It is dependent on the line
- * width.
- */
- switch (line_style) {
- case ZN_LINE_DOTTED:
- pattern = dotted;
- patlen = sizeof(dotted)/sizeof(char);
- break;
- case ZN_LINE_DASHED:
- pattern = dashed;
- patlen = sizeof(dashed)/sizeof(char);
- break;
- case ZN_LINE_MIXED:
- pattern = mixed;
- patlen = sizeof(mixed)/sizeof(char);
- break;
- }
- if (pattern) {
- sprintf(string, "[%d", ((*pattern++) * (int) line_width) & 0xff);
- while (--patlen) {
- sprintf(string+strlen(string), " %d", ((*pattern++) * (int) line_width) & 0xff);
- }
- Tcl_AppendResult(interp, string, NULL);
- sprintf(string, "] %d setdash\n", 0 /* dash offset */);
- Tcl_AppendResult(interp, string, NULL);
- }
- if (Tk_PostscriptColor(interp, ps_info,
- ZnGetGradientColor(line_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- if (line_pattern != ZnUnspecifiedImage) {
- Tcl_AppendResult(interp, "StrokeClip ", NULL);
- if (Tk_PostscriptStipple(interp, tkwin, ps_info,
- ZnImagePixmap(line_pattern, tkwin)) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- else {
- Tcl_AppendResult(interp, "stroke\n", NULL);
- }
-
- return TCL_OK;
-}
-
-/*
- * Emit PostScript to describe a bitmap as a string possibly
- * spliting it in parts due to the limited length of PostScript
- * strings.
- * This function emit the common code for ZnPostscriptBitmap and
- * ZnPostscriptStipple.
- */
-static int
-EmitPSBitmap()
-{
-}
-
-int
-ZnPostscriptStipple(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_PostscriptInfo ps_info,
- ZnImage bitmap)
-{
- return TCL_OK;
-}
-
-int
-ZnPostscriptBitmap(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_PostscriptInfo ps_info,
- ZnImage bitmap,
- ZnReal x,
- ZnReal y,
- int width,
- int height)
-{
- char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4];
- int rows_at_once, rows_this_time, cur_row;
-
- if (width > 60000) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "can't generate Postscript",
- " for bitmaps more than 60000 pixels wide", NULL);
- return TCL_ERROR;
- }
- rows_at_once = 60000/width;
- if (rows_at_once < 1) {
- rows_at_once = 1;
- }
- sprintf(buffer, "%.15g %.15g translate\n", x, y + height);
- Tcl_AppendResult(interp, buffer, NULL);
- for (cur_row = 0; cur_row < height; cur_row += rows_at_once) {
- rows_this_time = rows_at_once;
- if (rows_this_time > (height - cur_row)) {
- rows_this_time = height - cur_row;
- }
- sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n",
- (double) rows_this_time, width, rows_this_time);
- Tcl_AppendResult(interp, buffer, NULL);
- if (Tk_PostscriptBitmap(interp, tkwin, ps_info, ZnImagePixmap(bitmap, tkwin),
- 0, cur_row, width, rows_this_time) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL);
- }
-
- return TCL_OK;
-}
-
-void
-ZnPostscriptString(Tcl_Interp *interp,
- char *str,
- int num_bytes)
-{
-#ifndef PTK_800
-
- int used, len, clen;
- int c, bytecount = 0;
- CONST char *p, *last_p, *glyphname;
- Tcl_UniChar ch;
- char charbuf[5];
-#define MAXUSE 500
- char buf[MAXUSE+30];
-
- used = 0;
- buf[used++] = '[';
- buf[used++] = '(';
- len = num_bytes;
- p = str;
- while (len) {
- clen = Tcl_UtfToUniChar(p, &ch);
- last_p = p;
- p += clen;
- len -= clen;
- /*
- * INTL: For now we just treat the characters as binary
- * data and display the lower byte. Eventually this should
- * be revised to handle international postscript fonts.
- */
- Tcl_UtfToExternal(interp, NULL, last_p, clen, 0, NULL,
- charbuf, 4, NULL, &bytecount, NULL);
- if (bytecount == 1) {
- c = UCHAR(charbuf[0]);
- if ((c == '(') || (c == ')') || (c == '\\') ||
- (c < 0x20) || (c >= UCHAR(0x7f))) {
- /*
- * Tricky point: the "03" is necessary in the sprintf
- * below, so that a full three digits of octal are
- * always generated. Without the "03", a number
- * following this sequence could be interpreted by
- * Postscript as part of this sequence.
- */
- sprintf(buf + used, "\\%03o", c);
- used += 4;
- }
- else {
- buf[used++] = c;
- }
- }
- else {
- /* This character doesn't belong to system character set.
- * So, we must use full glyph name */
- sprintf(charbuf, "%04X", ch); /* endianness? */
- if ((glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", charbuf, 0))) {
- if ((used > 0) && (buf[used-1] == '(')) {
- --used;
- }
- else {
- buf[used++] = ')';
- }
- if ((used + strlen(glyphname)) >= MAXUSE) {
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
- used = 0;
- }
- buf[used++] = '/';
- while(*glyphname) {
- buf[used++] = *glyphname++ ;
- }
- buf[used++] = '(';
- }
- }
- if (used >= MAXUSE) {
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
- used = 0;
- }
- }
- buf[used++] = ')';
- buf[used++] = ']';
- buf[used++] = '\n';
- buf[used] = '\0';
- Tcl_AppendResult(interp, buf, NULL);
-
-#endif
-}
-
-int
-ZnPostscriptTile(Tcl_Interp *interp,
- Tk_Window win,
- Tk_PostscriptInfo ps_info,
- ZnImage image)
-{
- char path[150];
- int w, h;
-
- ZnSizeOfImage(image, &w, &h);
- Tcl_AppendResult(interp, "<< /PatternType 1 /PaintType 1 /TilingType 1\n", NULL);
- sprintf(path, " /BBox [%.15g %.15g %.15g %.15g] /XStep %.15g /YStep %.15g\n",
- 0.0, (double) h, (double) w, 0.0, (double) w, (double) h);
- Tcl_AppendResult(interp, path, " /PaintProc { begin\n", NULL);
-
- /*
- * On ne peut pas reprendre le code de Tk_PostscriptImage,
- * il génère une image inline impropre à l'inclusion dans
- * une procedure de tuilage. C'est d'ailleurs un problème :
- * Une string postscript ne doit pas dépasser 65K.
- */
- if (Tk_PostscriptImage(ZnImageTkImage(image), interp, win, ps_info, 0, 0, w, h, 0) != TCL_OK) {
- return TCL_ERROR;
- }
-
- Tcl_AppendResult(interp, "end } bind >> matrix makepattern setpattern fill\n", NULL);
-
- return TCL_OK;
-}
-
-void
-ZnPostscriptTrace(ZnItem item,
- ZnBool enter)
-{
- ZnWInfo *wi = item->wi;
- char buf[100];
-
- if (wi->debug) {
- sprintf(buf, "%%%%%%%% %s for %s %d %%%%%%%%\n",
- enter ? "Code" : "End of code", item->class->name, item->id);
- Tcl_AppendResult(wi->interp, buf, NULL);
- }
-}
-
-int
-ZnPostscriptGradient(Tcl_Interp *interp,
- Tk_PostscriptInfo ps_info,
- ZnGradient *gradient,
- ZnPoint *quad,
- ZnPoly *poly)
-{
- unsigned int i;
- char path[150];
- ZnPoint p, center, extent;
- ZnGradientColor *gc1, *gc2;
-
- if (gradient->type == ZN_CONICAL_GRADIENT || gradient->type == ZN_PATH_GRADIENT) {
- return TCL_OK;
- }
-
- Tcl_AppendResult(interp, "<< /PatternType 2 /Shading\n", NULL);
-
- switch (gradient->type) {
- case ZN_AXIAL_GRADIENT:
- /*
- * Fill the rectangle defined by quad with
- * the axial gradient.
- */
- switch (gradient->angle) {
- case 0:
- center = quad[0];
- extent = quad[1];
- case 90:
- center = quad[0];
- extent = quad[3];
- break;
- case 180:
- center = quad[1];
- extent = quad[0];
- break;
- case 270:
- center = quad[3];
- extent = quad[0];
- break;
- }
- Tcl_AppendResult(interp,
- " << /ShadingType 2 /ColorSpace /DeviceRGB /Extend [true true] ",
- NULL);
- sprintf(path, "/Coords [%.15g %.15g %.15g %.15g]\n",
- quad[0].x, quad[0].y, quad[1].x, quad[1].y);
- Tcl_AppendResult(interp, path, NULL);
- break;
- case ZN_RADIAL_GRADIENT:
- /*
- * On ne peut pas représenter un dégradé radial ou conique
- * anamorphique si on n'inclu pas la transformation dans le
- * PostScript résultant. PostScript ne peut décrire que des
- * dégradés circulaires. La seule solution rapide est d'utiliser
- * comme dans l'item Triangles une trame de triangles (Shading
- * type 4).
- */
- p.x = p.y = 0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &center);
- p.x = 1.0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &extent);
- Tcl_AppendResult(interp,
- " << /ShadingType 3 /ColorSpace /DeviceRGB /Extend [true true] ",
- NULL);
- sprintf(path, "/Coords [%.15g %.15g %.15g %.15g %.15g %.15g]\n",
- center.x, center.y, 0.0, center.x, center.y, ABS(center.x-extent.x));
- printf("center %g %g, radius %g\n", center.x, center.y, ABS(center.x-extent.x));
- Tcl_AppendResult(interp, path, NULL);
- break;
- case ZN_CONICAL_GRADIENT:
- break;
- case ZN_PATH_GRADIENT:
- break;
- }
-
- Tcl_AppendResult(interp, " /Function << ", NULL);
- Tcl_AppendResult(interp, "/FunctionType 3\n", NULL);
- Tcl_AppendResult(interp, " /Domain [0 1] /Bounds [", NULL);
- for (i = 1; i < gradient->num_actual_colors-1; i++) {
- sprintf(path, "%.4g ", gradient->actual_colors[i].position/100.0);
- Tcl_AppendResult(interp, path, NULL);
- }
- Tcl_AppendResult(interp, "] /Encode [", NULL);
- for (i = 0; i < gradient->num_actual_colors-1; i++) {
- Tcl_AppendResult(interp, "0 1 ", NULL);
- }
- Tcl_AppendResult(interp, "]\n /Functions [\n", NULL);
- for (i = 0, gc1 = gradient->actual_colors; i < gradient->num_actual_colors-1; i++) {
- gc2 = gc1 + 1;
- Tcl_AppendResult(interp, " << /FunctionType 2 /Domain [0 1] /N 1 ", NULL);
- sprintf(path, "/C0 [%.8g %.8g %.8g] /C1 [%.8g %.8g %.8g] >>\n",
- gc1->rgb->red/65535.0, gc1->rgb->green/65535.0, gc1->rgb->blue/65535.0,
- gc2->rgb->red/65535.0, gc2->rgb->green/65535.0, gc2->rgb->blue/65535.0);
- Tcl_AppendResult(interp, path, NULL);
- gc1 = gc2;
- }
- Tcl_AppendResult(interp, " ] >>\n", NULL);
- Tcl_AppendResult(interp, " >> >>\n", NULL);
- Tcl_AppendResult(interp, "matrix makepattern setpattern fill\n", NULL);
-
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * TkImageGetColor --
- *
- * This procedure converts a pixel value to three floating
- * point numbers, representing the amount of red, green, and
- * blue in that pixel on the screen. It makes use of colormap
- * data passed as an argument, and should work for all Visual
- * types.
- *
- * This implementation is bogus on Windows because the colormap
- * data is never filled in. Instead all postscript generated
- * data coming through here is expected to be RGB color data.
- * To handle lower bit-depth images properly, XQueryColors
- * must be implemented for Windows.
- *
- * Results:
- * Returns red, green, and blue color values in the range
- * 0 to 1. There are no error returns.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-/*
- * The following definition is used in generating postscript for images
- * and windows.
- */
-typedef struct TkColormapData { /* Hold color information for a window */
- int separated; /* Whether to use separate color bands */
- int color; /* Whether window is color or black/white */
- int ncolors; /* Number of color values stored */
- XColor *colors; /* Pixel value -> RGB mappings */
- int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
- int red_shift, green_shift, blue_shift; /* color band */
-} TkColormapData;
-
-#ifdef WIN32
-#include <windows.h>
-
-/*
- * We could just define these instead of pulling in windows.h.
- #define GetRValue(rgb) ((BYTE)(rgb))
- #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
- #define GetBValue(rgb) ((BYTE)((rgb)>>16))
-*/
-#else
-#define GetRValue(rgb) ((rgb & cdata->red_mask) >> cdata->red_shift)
-#define GetGValue(rgb) ((rgb & cdata->green_mask) >> cdata->green_shift)
-#define GetBValue(rgb) ((rgb & cdata->blue_mask) >> cdata->blue_shift)
-#endif
-
-#if defined(WIN32) || defined(MAC_OSX_TK)
-static void
-TkImageGetColor(cdata, pixel, red, green, blue)
- TkColormapData *cdata; /* Colormap data */
- unsigned long pixel; /* Pixel value to look up */
- double *red, *green, *blue; /* Color data to return */
-{
- *red = (double) GetRValue(pixel) / 255.0;
- *green = (double) GetGValue(pixel) / 255.0;
- *blue = (double) GetBValue(pixel) / 255.0;
-}
-#else
-static void
-TkImageGetColor(cdata, pixel, red, green, blue)
- TkColormapData *cdata; /* Colormap data */
- unsigned long pixel; /* Pixel value to look up */
- double *red, *green, *blue; /* Color data to return */
-{
- if (cdata->separated) {
- int r = GetRValue(pixel);
- int g = GetGValue(pixel);
- int b = GetBValue(pixel);
- *red = cdata->colors[r].red / 65535.0;
- *green = cdata->colors[g].green / 65535.0;
- *blue = cdata->colors[b].blue / 65535.0;
- } else {
- *red = cdata->colors[pixel].red / 65535.0;
- *green = cdata->colors[pixel].green / 65535.0;
- *blue = cdata->colors[pixel].blue / 65535.0;
- }
-}
-#endif
-
-/*
- *--------------------------------------------------------------
- *
- * ZnPostscriptXImage --
- *
- * This procedure is called to output the contents of an
- * XImage in Postscript, using a format appropriate for the
- * current color mode (i.e. one bit per pixel in monochrome,
- * one byte per pixel in gray, and three bytes per pixel in
- * color).
- *
- * Results:
- * Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
- * If no error occurs, then additional Postscript will be
- * appended to interp->result.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-/* TODO beaucoup de code à partager avec photo ci dessous
- * sans compter qu'il faut une autre fonction pour emettre
- * du code pour les tiling patterns.
- * Il faudrait un operateur central qui emette dans une
- * string postscript des bandes d'image afin de respecter
- * la taille max des strings (on peut aussi mettre les
- * bandes dans un tableau au préalable). Cet opérateur
- * gére le niveau de couleur (0, 1, ...) et sait gérer les
- * bits de transparence Postscript 3 en option.
- */
-int
-ZnPostscriptXImage(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_PostscriptInfo psInfo,
- XImage *ximage,
- int x,
- int y,
- int width,
- int height)
-{
- TkPostscriptInfo *psi = (TkPostscriptInfo *) psInfo;
- char buffer[256];
- int xx, yy, band, maxRows;
- double red, green, blue;
- int bytesPerLine=0, maxWidth=0;
- int level = psi->colorLevel;
- Colormap cmap;
- int i, ncolors;
- Visual *visual;
- TkColormapData cdata;
-
- if (psi->prepass) {
- return TCL_OK;
- }
-
- Tcl_AppendResult(interp, "%%%%%% Start of ZnPostscriptXImage\n", NULL);
-
- cmap = Tk_Colormap(tkwin);
- visual = Tk_Visual(tkwin);
-
- /*
- * Obtain information about the colormap, ie the mapping between
- * pixel values and RGB values. The code below should work
- * for all Visual types.
- */
- ncolors = visual->map_entries;
- cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors);
- cdata.ncolors = ncolors;
-
- if ((visual->class == DirectColor) || (visual->class == TrueColor)) {
- cdata.separated = 1;
- cdata.red_mask = visual->red_mask;
- cdata.green_mask = visual->green_mask;
- cdata.blue_mask = visual->blue_mask;
- cdata.red_shift = 0;
- cdata.green_shift = 0;
- cdata.blue_shift = 0;
- while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) {
- cdata.red_shift ++;
- }
- while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) {
- cdata.green_shift ++;
- }
- while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) {
- cdata.blue_shift ++;
- }
- for (i = 0; i < ncolors; i ++) {
- cdata.colors[i].pixel = ((i << cdata.red_shift) & cdata.red_mask) |
- ((i << cdata.green_shift) & cdata.green_mask) |
- ((i << cdata.blue_shift) & cdata.blue_mask);
- }
- }
- else {
- cdata.separated=0;
- for (i = 0; i < ncolors; i ++) {
- cdata.colors[i].pixel = i;
- }
- }
- if ((visual->class == StaticGray) || (visual->class == GrayScale)) {
- cdata.color = 0;
- }
- else {
- cdata.color = 1;
- }
-
- XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);
-
- /*
- * Figure out which color level to use (possibly lower than the
- * one specified by the user). For example, if the user specifies
- * color with monochrome screen, use gray or monochrome mode instead.
- */
-
- if (!cdata.color && level == 2) {
- level = 1;
- }
- if (!cdata.color && cdata.ncolors == 2) {
- level = 0;
- }
-
- /*
- * Check that at least one row of the image can be represented
- * with a string less than 64 KB long (this is a limit in the
- * Postscript interpreter).
- */
- switch (level) {
- case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
- case 1: bytesPerLine = width; maxWidth = 60000; break;
- case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
- }
-
- if (bytesPerLine > 60000) {
- Tcl_ResetResult(interp);
- sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide", maxWidth);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- ckfree((char *) cdata.colors);
- return TCL_ERROR;
- }
-
- maxRows = 60000 / bytesPerLine;
-
- for (band = height-1; band >= 0; band -= maxRows) {
- int rows = (band >= maxRows) ? maxRows : band + 1;
- int lineLen = 0;
- switch (level) {
- case 0:
- sprintf(buffer, "%d %d 1 matrix {\n<", width, rows);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- break;
- case 1:
- sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- break;
- case 2:
- sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- break;
- }
- for (yy = band; yy > band - rows; yy--) {
- switch (level) {
- case 0:
- {
- /*
- * Generate data for image in monochrome mode.
- * No attempt at dithering is made--instead, just
- * set a threshold.
- */
- unsigned char mask=0x80;
- unsigned char data=0x00;
- for (xx = x; xx< x+width; xx++) {
- TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
- &red, &green, &blue);
- if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5)
- data |= mask;
- mask >>= 1;
- if (mask == 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen > 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- mask=0x80;
- data=0x00;
- }
- }
- if ((width % 8) != 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- mask=0x80;
- data=0x00;
- }
- break;
- }
- case 1:
- {
- /*
- * Generate data in gray mode--in this case, take a
- * weighted sum of the red, green, and blue values.
- */
- for (xx = x; xx < x+width; xx ++) {
- TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
- &red, &green, &blue);
- sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 *
- (0.30 * red + 0.59 * green + 0.11 * blue)));
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen > 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
- break;
- }
- case 2:
- {
- /*
- * Finally, color mode. Here, just output the red, green,
- * and blue values directly.
- */
- for (xx = x; xx < x+width; xx++) {
- TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
- &red, &green, &blue);
- sprintf(buffer, "%02X%02X%02X",
- (int) floor(0.5 + 255.0 * red),
- (int) floor(0.5 + 255.0 * green),
- (int) floor(0.5 + 255.0 * blue));
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 6;
- if (lineLen > 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
- break;
- }
- }
- }
- switch (level) {
- case 0: sprintf(buffer, ">\n} image\n"); break;
- case 1: sprintf(buffer, ">\n} image\n"); break;
- case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break;
- }
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- sprintf(buffer, "0 %d translate\n", rows);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- }
- ckfree((char *) cdata.colors);
-
- Tcl_AppendResult(interp, "%%%%%% End of ZnPostscriptXImage\n", NULL);
-
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * ZnPostscriptPhoto --
- *
- * This procedure is called to output the contents of a
- * photo image in Postscript, using a format appropriate for
- * the requested postscript color mode (i.e. one byte per pixel
- * in gray, and three bytes per pixel in color).
- *
- * Results:
- * Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
- * If no error occurs, then additional Postscript will be
- * appended to the interpreter's result.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-int
-ZnPostscriptPhoto(Tcl_Interp *interp,
- Tk_PhotoImageBlock *blockPtr,
- Tk_PostscriptInfo ps_info,
- int width,
- int height)
-{
- TkPostscriptInfo *psi = (TkPostscriptInfo *) ps_info;
- static int codeIncluded = 0;
- unsigned char *pixelPtr;
- char buffer[256], cspace[40], decode[40];
- int bpc;
- int xx, yy, lineLen;
- float red, green, blue;
- int alpha;
- int bytesPerLine=0, maxWidth=0;
- unsigned char opaque = 255;
- unsigned char *alphaPtr;
- int alphaOffset, alphaPitch, alphaIncr;
-
- if (psi->prepass) {
- codeIncluded = 0;
- return TCL_OK;
- }
-
- /*
- * Define the "TkPhoto" function, which is a modified version
- * of the original "transparentimage" function posted
- * by ian@five-d.com (Ian Kemmish) to comp.lang.postscript.
- * For a monochrome colorLevel this is a slightly different
- * version that uses the imagemask command instead of image.
- */
- if( !codeIncluded && (psi->colorLevel != 0) ) {
- /*
- * Color and gray-scale code.
- */
- codeIncluded = !0;
- Tcl_AppendResult(interp,
- "/TkPhoto { \n",
- " gsave \n",
- " 32 dict begin \n",
- " /tinteger exch def \n",
- " /transparent 1 string def \n",
- " transparent 0 tinteger put \n",
- " /olddict exch def \n",
- " olddict /DataSource get dup type /filetype ne { \n",
- " olddict /DataSource 3 -1 roll \n",
- " 0 () /SubFileDecode filter put \n",
- " } { \n",
- " pop \n",
- " } ifelse \n",
- " /newdict olddict maxlength dict def \n",
- " olddict newdict copy pop \n",
- " /w newdict /Width get def \n",
- " /crpp newdict /Decode get length 2 idiv def \n",
- " /str w string def \n",
- " /pix w crpp mul string def \n",
- " /substrlen 2 w log 2 log div floor exp cvi def \n",
- " /substrs [ \n",
- " { \n",
- " substrlen string \n",
- " 0 1 substrlen 1 sub { \n",
- " 1 index exch tinteger put \n",
- " } for \n",
- " /substrlen substrlen 2 idiv def \n",
- " substrlen 0 eq {exit} if \n",
- " } loop \n",
- " ] def \n",
- " /h newdict /Height get def \n",
- " 1 w div 1 h div matrix scale \n",
- " olddict /ImageMatrix get exch matrix concatmatrix \n",
- " matrix invertmatrix concat \n",
- " newdict /Height 1 put \n",
- " newdict /DataSource pix put \n",
- " /mat [w 0 0 h 0 0] def \n",
- " newdict /ImageMatrix mat put \n",
- " 0 1 h 1 sub { \n",
- " mat 5 3 -1 roll neg put \n",
- " olddict /DataSource get str readstring pop pop \n",
- " /tail str def \n",
- " /x 0 def \n",
- " olddict /DataSource get pix readstring pop pop \n",
- " { \n",
- " tail transparent search dup /done exch not def \n",
- " {exch pop exch pop} if \n",
- " /w1 exch length def \n",
- " w1 0 ne { \n",
- " newdict /DataSource ",
- " pix x crpp mul w1 crpp mul getinterval put \n",
- " newdict /Width w1 put \n",
- " mat 4 x neg put \n",
- " /x x w1 add def \n",
- " newdict image \n",
- " /tail tail w1 tail length w1 sub getinterval def \n",
- " } if \n",
- " done {exit} if \n",
- " tail substrs { \n",
- " anchorsearch {pop} if \n",
- " } forall \n",
- " /tail exch def \n",
- " tail length 0 eq {exit} if \n",
- " /x w tail length sub def \n",
- " } loop \n",
- " } for \n",
- " end \n",
- " grestore \n",
- "} bind def \n\n\n", (char *) NULL);
- }
- else if (!codeIncluded && (psi->colorLevel == 0)) {
- /*
- * Monochrome-only code
- */
- codeIncluded = !0;
- Tcl_AppendResult(interp,
- "/TkPhoto { \n",
- " gsave \n",
- " 32 dict begin \n",
- " /dummyInteger exch def \n",
- " /olddict exch def \n",
- " olddict /DataSource get dup type /filetype ne { \n",
- " olddict /DataSource 3 -1 roll \n",
- " 0 () /SubFileDecode filter put \n",
- " } { \n",
- " pop \n",
- " } ifelse \n",
- " /newdict olddict maxlength dict def \n",
- " olddict newdict copy pop \n",
- " /w newdict /Width get def \n",
- " /pix w 7 add 8 idiv string def \n",
- " /h newdict /Height get def \n",
- " 1 w div 1 h div matrix scale \n",
- " olddict /ImageMatrix get exch matrix concatmatrix \n",
- " matrix invertmatrix concat \n",
- " newdict /Height 1 put \n",
- " newdict /DataSource pix put \n",
- " /mat [w 0 0 h 0 0] def \n",
- " newdict /ImageMatrix mat put \n",
- " 0 1 h 1 sub { \n",
- " mat 5 3 -1 roll neg put \n",
- " 0.000 0.000 0.000 setrgbcolor \n",
- " olddict /DataSource get pix readstring pop pop \n",
- " newdict /DataSource pix put \n",
- " newdict imagemask \n",
- " 1.000 1.000 1.000 setrgbcolor \n",
- " olddict /DataSource get pix readstring pop pop \n",
- " newdict /DataSource pix put \n",
- " newdict imagemask \n",
- " } for \n",
- " end \n",
- " grestore \n",
- "} bind def \n\n\n", (char *) NULL);
- }
-
- /*
- * Check that at least one row of the image can be represented
- * with a string less than 64 KB long (this is a limit in the
- * Postscript interpreter).
- */
- switch (psi->colorLevel)
- {
- case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
- case 1: bytesPerLine = width; maxWidth = 60000; break;
- case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
- }
- if (bytesPerLine > 60000) {
- Tcl_ResetResult(interp);
- sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide",
- maxWidth);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Set up the postscript code except for the image-data stream.
- */
- switch (psi->colorLevel) {
- case 0:
- strcpy( cspace, "/DeviceGray");
- strcpy( decode, "[1 0]");
- bpc = 1;
- break;
- case 1:
- strcpy( cspace, "/DeviceGray");
- strcpy( decode, "[0 1]");
- bpc = 8;
- break;
- default:
- strcpy( cspace, "/DeviceRGB");
- strcpy( decode, "[0 1 0 1 0 1]");
- bpc = 8;
- break;
- }
-
- Tcl_AppendResult(interp, cspace, " setcolorspace\n\n", (char *) NULL);
- sprintf(buffer, " /Width %d\n /Height %d\n /BitsPerComponent %d\n",
- width, height, bpc);
- Tcl_AppendResult(interp,
- "<<\n /ImageType 1\n", buffer,
- " /DataSource currentfile /ASCIIHexDecode filter\n", (char *) NULL);
- sprintf(buffer, " /ImageMatrix [1 0 0 -1 0 %d]\n", height);
- Tcl_AppendResult(interp, buffer, " /Decode ", decode, "\n>>\n1 TkPhoto\n", (char *) NULL);
-
- /*
- * Check the PhotoImageBlock information.
- * We assume that:
- * if pixelSize is 1,2 or 4, the image is R,G,B,A;
- * if pixelSize is 3, the image is R,G,B and offset[3] is bogus.
- */
- if (blockPtr->pixelSize == 3) {
- /*
- * No alpha information: the whole image is opaque.
- */
- alphaPtr = &opaque;
- alphaPitch = alphaIncr = alphaOffset = 0;
- }
- else {
- /*
- * Set up alpha handling.
- */
- alphaPtr = blockPtr->pixelPtr;
- alphaPitch = blockPtr->pitch;
- alphaIncr = blockPtr->pixelSize;
- alphaOffset = blockPtr->offset[3];
- }
-
- for (yy = 0, lineLen=0; yy < height; yy++) {
- switch (psi->colorLevel) {
- case 0:
- {
- /*
- * Generate data for image in monochrome mode.
- * No attempt at dithering is made--instead, just
- * set a threshold.
- * To handle transparencies we need to output two lines:
- * one for the black pixels, one for the white ones.
- */
- unsigned char mask=0x80;
- unsigned char data=0x00;
- for (xx = 0; xx< width; xx ++) {
- pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
-
- red = pixelPtr[blockPtr->offset[0]];
- green = pixelPtr[blockPtr->offset[1]];
- blue = pixelPtr[blockPtr->offset[2]];
-
- alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
-
- /*
- * If pixel is less than threshold, then it is black.
- */
- if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue < 128)) {
- data |= mask;
- }
- mask >>= 1;
- if (mask == 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- mask=0x80;
- data=0x00;
- }
- }
- if ((width % 8) != 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- mask=0x80;
- data=0x00;
- }
-
- mask=0x80;
- data=0x00;
- for (xx = 0; xx< width; xx ++) {
- pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
-
- red = pixelPtr[blockPtr->offset[0]];
- green = pixelPtr[blockPtr->offset[1]];
- blue = pixelPtr[blockPtr->offset[2]];
-
- alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
-
- /*
- * If pixel is greater than threshold, then it is white.
- */
- if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue >= 128)) {
- data |= mask;
- }
- mask >>= 1;
- if (mask == 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- mask=0x80;
- data=0x00;
- }
- }
- if ((width % 8) != 0) {
- sprintf(buffer, "%02X", data);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- mask=0x80;
- data=0x00;
- }
- break;
- }
- case 1:
- {
- /*
- * Generate transparency data.
- * We must prevent a transparent value of 0
- * because of a bug in some HP printers.
- */
- for (xx = 0; xx < width; xx ++) {
- alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
- sprintf(buffer, "%02X", alpha | 0x01);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
-
- /*
- * Generate data in gray mode--in this case, take a
- * weighted sum of the red, green, and blue values.
- */
- for (xx = 0; xx < width; xx ++) {
- pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
-
- red = pixelPtr[blockPtr->offset[0]];
- green = pixelPtr[blockPtr->offset[1]];
- blue = pixelPtr[blockPtr->offset[2]];
-
- sprintf(buffer, "%02X",
- (int) floor(0.5 + ( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
- break;
- }
- default:
- {
- /*
- * Generate transparency data.
- * We must prevent a transparent value of 0
- * because of a bug in some HP printers.
- */
- for (xx = 0; xx < width; xx ++) {
- alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
- sprintf(buffer, "%02X", alpha | 0x01);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 2;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
-
- /*
- * Finally, color mode. Here, just output the red, green,
- * and blue values directly.
- */
- for (xx = 0; xx < width; xx ++) {
- pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);
-
- sprintf(buffer, "%02X%02X%02X", pixelPtr[blockPtr->offset[0]],
- pixelPtr[blockPtr->offset[1]], pixelPtr[blockPtr->offset[2]]);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- lineLen += 6;
- if (lineLen >= 60) {
- lineLen = 0;
- Tcl_AppendResult(interp, "\n", (char *) NULL);
- }
- }
- break;
- }
- }
- }
-
- Tcl_AppendResult(interp, ">\n", (char *) NULL);
- return TCL_OK;
-}
-
-int
-ZnPostscriptImage(Tcl_Interp *interp,
- Tk_Window tkwin,
- Tk_PostscriptInfo ps_info,
- ZnImage image,
- int x,
- int y,
- int w,
- int h)
-{
- int result;
- XImage *ximage;
- Tk_PhotoHandle tkphoto;
-
- if (((TkPostscriptInfo *) ps_info)->prepass) {
- return TCL_OK;
- }
-
- tkphoto = ZnImageTkPhoto(image);
- if (tkphoto != NULL) {
- Tk_PhotoImageBlock block;
-
- Tk_PhotoGetImage(tkphoto, &block);
- block.pixelPtr += y * block.pitch + x * block.pixelSize;
-
- return ZnPostscriptPhoto(interp, &block, ps_info, w, h);
- }
- else {
- Pixmap pix = ZnImagePixmap(image, tkwin);
- XGCValues values;
- GC gc;
-
- if (pix == None) {
- /*
- * Pixmap not cached (probably working under GL).
- * Create a temporary pixmap.
- */
- pix = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), w, h, Tk_Depth(tkwin));
- values.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
- gc = Tk_GetGC(tkwin, GCForeground, &values);
- if (gc != None) {
- XFillRectangle(Tk_Display(tkwin), pix, gc, 0, 0, (unsigned int) w, (unsigned int) h);
- Tk_FreeGC(Tk_Display(tkwin), gc);
- }
- Tk_RedrawImage(image, x, y, w, h, pix, 0, 0);
- Tk_FreePixmap(Tk_Display(tkwin), pix);
- }
- else {
- ximage = XGetImage(Tk_Display(tkwin), pix, 0, 0,
- (unsigned int) w, (unsigned int) h, AllPlanes, ZPixmap);
- }
- if (ximage == NULL) {
- /* The XGetImage() function is apparently not
- * implemented on this system. Just ignore it.
- */
- return TCL_OK;
- }
- result = ZnPostscriptXImage(interp, tkwin, ps_info, ximage, x, y, w, h);
- XDestroyImage(ximage);
- }
-
- return result;
-}
-
-void
-EmitPhotoImageData()
-{
-}
-
-
-/*
- * TODO gradients, tuiles, reliefs, flêches, clipping.
- * TODO la fonction DrawText est buggée dans un environnement rotation
- * l'erreur passe par un max autour de modulo 45°
- * TODO Bugs de placement sur le texte et les bordures des fields
- * TODO Problème : Si on utilise les transformations PostScript on
- * génère un code plus concis et le rendu est potentiellement
- * plus beau (on utilise les arcs et les beziers natifs) et on
- * peut générer des dégradés identiques à ceux de zinc mais le
- * tuilage/stencil, les flêches, l'épaisseur des lignes suivent
- * la transformation.
- * TODO Le code gérant les images ne sait pas traiter le canal alpha.
- * TODO Inclure ici le code de gestion des stipples.
- * TODO Pour images et stipples le code doit prendre en compte le contexte
- * X et/ou OpenGL.
- */
diff --git a/generic/PostScript.h b/generic/PostScript.h
deleted file mode 100644
index 5af987e..0000000
--- a/generic/PostScript.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * PostScript.h -- Header to access PostScript driver.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Wed Jan 4 11:30:00 1995
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1995 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _PostScript_h
-#define _PostScript_h
-
-
-#include "List.h"
-#include "Types.h"
-#include "Geo.h"
-#include "Color.h"
-#include "Image.h"
-
-#include <stdio.h>
-#include <X11/Xlib.h>
-
-
-struct _ZnWInfo;
-struct _ZnItemStruct;
-
-
-int ZnPostScriptCmd(struct _ZnWInfo *wi, int argc, Tcl_Obj *CONST *args);
-void ZnFlushPsChan(Tcl_Interp *interp, Tk_PostscriptInfo ps_info);
-int ZnPostscriptOutline(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
- Tk_Window tkwin, ZnDim line_width, ZnLineStyle line_style,
- ZnGradient *line_color, ZnImage line_pattern);
-int ZnPostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
- ZnImage bitmap, ZnReal x, ZnReal y, int width, int height);
-void ZnPostscriptString(Tcl_Interp *interp, char *str, int num_bytes);
-void ZnPostscriptTrace(struct _ZnItemStruct *item, ZnBool enter);
-int ZnPostscriptGradient(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
- ZnGradient *gradient, ZnPoint *quad, ZnPoly *poly);
-int ZnPostscriptXImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo,
- XImage *ximage, int x, int y, int width, int height);
-int ZnPostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
- ZnImage bitmap);
-int ZnPostscriptTile(Tcl_Interp *interp, Tk_Window win, Tk_PostscriptInfo ps_info,
- ZnImage image);
-int ZnPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
- ZnImage image, int x, int y, int width, int height);
-
-#endif /* _PostScript_h */
diff --git a/generic/Rectangle.c b/generic/Rectangle.c
deleted file mode 100644
index 8afb38f..0000000
--- a/generic/Rectangle.c
+++ /dev/null
@@ -1,1026 +0,0 @@
-/*
- * Rectangle.c -- Implementation of rectangle item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Fri Dec 2 14:47:42 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1994 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "Types.h"
-#include "Image.h"
-#include "Color.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-/*
- * Bit offset of flags.
- */
-#define FILLED_BIT 1 /* If the rectangle is filled with color/pattern */
-#define ALIGNED_BIT 2
-
-
-/*
- **********************************************************************************
- *
- * Specific Rectangle item record
- *
- **********************************************************************************
- */
-
-typedef struct _RectangleItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint coords[2];
- unsigned short flags;
- ZnReliefStyle relief;
- ZnLineStyle line_style;
- ZnDim line_width;
- ZnGradient *line_color;
- ZnImage line_pattern;
- ZnGradient *fill_color;
- ZnImage tile;
-
- /* Private data */
- ZnPoint dev[4];
- ZnGradient *gradient;
- ZnPoint *grad_geo;
-} RectangleItemStruct, *RectangleItem;
-
-
-static ZnAttrConfig rect_attrs[] = {
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
- Tk_Offset(RectangleItemStruct, fill_color), 0,
- ZN_COORDS_FLAG|ZN_BORDER_FLAG, False },
- { ZN_CONFIG_BOOL, "-filled", NULL,
- Tk_Offset(RectangleItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(RectangleItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
- Tk_Offset(RectangleItemStruct, line_color), 0,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BITMAP, "-linepattern", NULL,
- Tk_Offset(RectangleItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
- Tk_Offset(RectangleItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-linewidth", NULL,
- Tk_Offset(RectangleItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(RectangleItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(RectangleItemStruct, relief), 0,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(RectangleItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(RectangleItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_IMAGE, "-tile", NULL,
- Tk_Offset(RectangleItemStruct, tile), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(RectangleItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- unsigned int num_points;
- ZnPoint *points;
-
- rect->gradient = NULL;
- rect->grad_geo = NULL;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 1;
-
- if (*argc < 1) {
- Tcl_AppendResult(wi->interp, " rectangle coords expected", NULL);
- return TCL_ERROR;
- }
- if (ZnParseCoordList(wi, (*args)[0], &points,
- NULL, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (num_points != 2) {
- Tcl_AppendResult(wi->interp, " malformed rectangle coords", NULL);
- return TCL_ERROR;
- };
- rect->coords[0] = points[0];
- rect->coords[1] = points[1];
- (*args)++;
- (*argc)--;
-
- CLEAR(rect->flags, FILLED_BIT);
- rect->relief = ZN_RELIEF_FLAT;
- rect->line_style = ZN_LINE_SIMPLE;
- rect->line_width = 1;
- rect->line_pattern = ZnUnspecifiedImage;
- rect->tile = ZnUnspecifiedImage;
- rect->line_color = ZnGetGradientByValue(wi->fore_color);
- rect->fill_color = ZnGetGradientByValue(wi->fore_color);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- RectangleItem rect = (RectangleItem) item;
-
- if (rect->gradient) {
- rect->gradient = ZnGetGradientByValue(rect->gradient);
- }
- if (rect->tile != ZnUnspecifiedImage) {
- rect->tile = ZnGetImageByValue(rect->tile, ZnUpdateItemImage, item);
- }
- if (rect->line_pattern != ZnUnspecifiedImage) {
- rect->line_pattern = ZnGetImageByValue(rect->line_pattern, NULL, NULL);
- }
- rect->line_color = ZnGetGradientByValue(rect->line_color);
- rect->fill_color = ZnGetGradientByValue(rect->fill_color);
- rect->grad_geo = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- RectangleItem rect = (RectangleItem) item;
-
- if (rect->tile != ZnUnspecifiedImage) {
- ZnFreeImage(rect->tile, ZnUpdateItemImage, item);
- rect->tile = ZnUnspecifiedImage;
- }
- if (rect->gradient) {
- ZnFreeGradient(rect->gradient);
- }
- if (rect->line_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(rect->line_pattern, NULL, NULL);
- rect->line_pattern = ZnUnspecifiedImage;
- }
- if (rect->grad_geo) {
- ZnFree(rect->grad_geo);
- }
- ZnFreeGradient(rect->fill_color);
- ZnFreeGradient(rect->line_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- int status = TCL_OK;
- XColor *color;
- unsigned short alpha;
-
- status = ZnConfigureAttributes(wi, item, item, rect_attrs, argc, argv, flags);
-
- if (rect->gradient &&
- (ISSET(*flags, ZN_BORDER_FLAG) || (rect->relief == ZN_RELIEF_FLAT))) {
- ZnFreeGradient(rect->gradient);
- rect->gradient = NULL;
- }
- if ((rect->relief != ZN_RELIEF_FLAT) && !rect->gradient) {
- color = ZnGetGradientColor(rect->line_color, 51.0, &alpha);
- rect->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- Tk_NameOfColor(color), alpha);
- if (rect->gradient == NULL) {
- status = TCL_ERROR;
- }
- }
-
- return status;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, rect_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- ZnPoint p[4];
- int i;
- ZnBool aligned;
- ZnDim delta, lw2;
-
- ZnResetBBox(&item->item_bounding_box);
- if (!rect->line_width && ISCLEAR(rect->flags, FILLED_BIT)) {
- return;
- }
-
- p[0] = rect->coords[0];
- p[2] = rect->coords[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(wi->current_transfo, p, rect->dev, 4);
- for (i = 0; i < 4; i++) {
- rect->dev[i].x = ZnNearestInt(rect->dev[i].x);
- rect->dev[i].y = ZnNearestInt(rect->dev[i].y);
- }
-
- /*
- * Add all points to the bounding box. Then expand by the line
- * width to account for mitered corners. This is an overestimate.
- */
- ZnAddPointsToBBox(&item->item_bounding_box, rect->dev, 4);
- if (rect->line_width > 0) {
- lw2 = rect->line_width/2.0;
- item->item_bounding_box.orig.x -= lw2;
- item->item_bounding_box.orig.y -= lw2;
- item->item_bounding_box.corner.x += lw2;
- item->item_bounding_box.corner.y += lw2;
- }
- item->item_bounding_box.orig.x -= 0.5;
- item->item_bounding_box.orig.y -= 0.5;
- item->item_bounding_box.corner.x += 0.5;
- item->item_bounding_box.corner.y += 0.5;
-
- delta = rect->dev[0].y - rect->dev[1].y;
- delta = ABS(delta);
- aligned = delta < X_PRECISION_LIMIT;
- delta = rect->dev[0].x - rect->dev[3].x;
- delta = ABS(delta);
- aligned &= delta < X_PRECISION_LIMIT;
- ASSIGN(rect->flags, ALIGNED_BIT, aligned);
-
-#ifdef GL
- /*
- * Compute the gradient geometry
- */
- if (!ZnGradientFlat(rect->fill_color)) {
- ZnPoly shape;
-
- if (rect->fill_color->type == ZN_AXIAL_GRADIENT) {
- int angle = rect->fill_color->angle;
-
- if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
- if (!rect->grad_geo) {
- rect->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
- }
- ZnPolyContour1(&shape, p, 4, False);
- ZnComputeGradient(rect->fill_color, wi, &shape, rect->grad_geo);
- }
- else {
- goto free_ggeo;
- }
- }
- else {
- if (!rect->grad_geo) {
- rect->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
- }
- if (rect->fill_color->type == ZN_PATH_GRADIENT) {
- ZnPolyContour1(&shape, rect->coords, 2, False);
- }
- else {
- ZnPolyContour1(&shape, p, 4, False);
- }
- ZnComputeGradient(rect->fill_color, wi, &shape, rect->grad_geo);
- }
- }
- else {
- free_ggeo:
- if (rect->grad_geo) {
- ZnFree(rect->grad_geo);
- rect->grad_geo = NULL;
- }
- }
-#endif
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- RectangleItem rect = (RectangleItem) item;
- int result, result2;
- ZnBBox *area = ta->area;
-
- result = -1;
-
- if (ISSET(rect->flags, FILLED_BIT)) {
- result = ZnPolygonInBBox(rect->dev, 4, area, NULL);
- if (result == 0) {
- return 0;
- }
- }
- if (rect->line_width > 0) {
- int i;
- ZnPoint pts[5];
-
- for (i = 0; i < 4; i++) {
- pts[i] = rect->dev[i];
- }
- pts[4] = pts[0];
- result2 = ZnPolylineInBBox(pts, 5, rect->line_width,
- CapProjecting, JoinMiter, area);
- if (ISCLEAR(rect->flags, FILLED_BIT)) {
- if (result2 == 0) {
- return 0;
- }
- result = result2;
- }
- else if (result2 != result) {
- return 0;
- }
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- XGCValues values;
- unsigned int i, gc_mask;
- XRectangle r;
- XPoint xp[5];
-
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- if (rect->dev[0].x < rect->dev[2].x) {
- r.x = (int) rect->dev[0].x;
- r.width = ((int) rect->dev[2].x) - r.x;
- }
- else {
- r.x = (int) rect->dev[2].x;
- r.width = ((int) rect->dev[0].x) - r.x;
- }
- if (rect->dev[0].y < rect->dev[2].y) {
- r.y = (int) rect->dev[0].y;
- r.height = ((int) rect->dev[2].y) - r.y;
- }
- else {
- r.y = (int) rect->dev[2].y;
- r.height = ((int) rect->dev[0].y) - r.y;
- }
- }
- else {
- for (i = 0; i < 4; i++) {
- xp[i].x = (int) rect->dev[i].x;
- xp[i].y = (int) rect->dev[i].y;
- }
- xp[i] = xp[0];
- }
-
- /*
- * Fill if requested.
- */
- if (ISSET(rect->flags, FILLED_BIT)) {
- values.foreground = ZnGetGradientPixel(rect->fill_color, 0.0);
- if (rect->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(rect->tile)) { /* Fill tiled */
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(rect->tile, wi->win);
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- values.ts_x_origin = (int) r.x;
- values.ts_y_origin = (int) r.y;
- }
- else {
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- }
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile, &values);
- }
- else {
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(rect->tile, wi->win);
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- values.ts_x_origin = (int) r.x;
- values.ts_y_origin = (int) r.y;
- }
- else {
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- }
- XChangeGC(wi->dpy, wi->gc,
- GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground,
- &values);
- }
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle, &values);
- }
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
- r.width, r.height);
- }
- else {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
- }
- }
-
- /* Draw the outline */
- if (rect->line_width) {
- if (rect->relief != ZN_RELIEF_FLAT) {
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- ZnDrawRectangleRelief(wi, rect->relief, rect->gradient,
- &r, rect->line_width);
- }
- else {
- ZnPoint p[5];
- for (i = 0; i < 4; i++) {
- p[4-i].x = rect->dev[i].x;
- p[4-i].y = rect->dev[i].y;
- }
- p[0] = p[4];
- ZnDrawPolygonRelief(wi, rect->relief, rect->gradient,
- p, 5, rect->line_width);
- }
- }
- else {
- ZnSetLineStyle(wi, rect->line_style);
- gc_mask = GCFillStyle|GCLineWidth|GCForeground|GCJoinStyle;
- values.foreground = ZnGetGradientPixel(rect->line_color, 0.0);
- values.line_width = (rect->line_width == 1) ? 0 : (int) rect->line_width;
- values.join_style = JoinMiter;
- if (ISCLEAR(rect->flags, ALIGNED_BIT)) {
- gc_mask |= GCCapStyle;
- values.cap_style = CapProjecting;
- }
- if (rect->line_pattern == ZnUnspecifiedImage) {
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
- }
- else {
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(rect->line_pattern, wi->win);
- gc_mask |= GCStipple;
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
- }
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
- r.width, r.height);
- }
- else {
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xp, 5, CoordModeOrigin);
- }
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-RectRenderCB(void *closure)
-{
- RectangleItem rect = (RectangleItem) closure;
-
- glBegin(GL_TRIANGLE_STRIP);
- glVertex2d(rect->dev[0].x, rect->dev[0].y);
- glVertex2d(rect->dev[3].x, rect->dev[3].y);
- glVertex2d(rect->dev[1].x, rect->dev[1].y);
- glVertex2d(rect->dev[2].x, rect->dev[2].y);
- glEnd();
-}
-#endif
-
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- int i;
-
-#ifdef GL_LIST
- if (!item->gl_list) {
- item->gl_list = glGenLists(1);
- glNewList(item->gl_list, GL_COMPILE);
-#endif
- if (ISSET(rect->flags, FILLED_BIT)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- if (!ZnGradientFlat(rect->fill_color)) {
- ZnBool fast = (rect->fill_color->type == ZN_AXIAL_GRADIENT) && !rect->grad_geo;
- ZnPoly poly;
-
- ZnPolyContour1(&poly, rect->dev, 4, False);
- ZnRenderGradient(wi, rect->fill_color,
- fast ? NULL: RectRenderCB, rect,
- fast ? rect->dev : rect->grad_geo, &poly);
- }
- else if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled/patterned */
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- ZnBBox bbox;
-
- bbox.orig = rect->dev[0];
- bbox.corner = rect->dev[2];
- ZnRenderTile(wi, rect->tile, rect->fill_color, NULL, NULL, (ZnPoint *) &bbox);
- }
- else {
- ZnRenderTile(wi, rect->tile, rect->fill_color, RectRenderCB,
- rect, (ZnPoint *) &item->item_bounding_box);
- }
- }
- else {
- unsigned short alpha;
- XColor *color = ZnGetGradientColor(rect->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- RectRenderCB(rect);
- }
- }
-
- if (rect->line_width) {
- ZnPoint p[5];
- for (i = 0; i < 4; i++) {
- p[4-i].x = rect->dev[i].x;
- p[4-i].y = rect->dev[i].y;
- }
- p[0] = p[4];
- if (rect->relief != ZN_RELIEF_FLAT) {
- ZnRenderPolygonRelief(wi, rect->relief, rect->gradient, False,
- p, 5, rect->line_width);
- }
- else {
- ZnRenderPolyline(wi, p, 5, rect->line_width,
- rect->line_style, CapRound, JoinMiter,
- NULL, NULL, rect->line_color);
- }
- }
-#ifdef GL_LIST
- glEndList();
- }
-
- glCallList(item->gl_list);
-#endif
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- RectangleItem rect = (RectangleItem) item;
- double best_dist;
- ZnPoint *p = ps->point;
-
- best_dist = ZnPolygonToPointDist(rect->dev, 4, p);
-
- if (ISSET(rect->flags, FILLED_BIT)) {
- if (best_dist <= 0.0) {
- return 0.0;
- }
- }
- best_dist = ABS(best_dist);
-
- if (rect->line_width > 1) {
- double dist;
- int i;
- ZnPoint pts[5];
-
- for (i = 0; i < 4; i++) {
- pts[i] = rect->dev[i];
- }
- pts[4] = pts[0];
- dist = ZnPolylineToPointDist(pts, 5, rect->line_width,
- CapProjecting, JoinMiter, p);
- if (dist <= 0.0) {
- return 0.0;
- }
- best_dist = MIN(dist, best_dist);
- }
-
- return best_dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- RectangleItem rect = (RectangleItem) item;
- char path[500];
-
- if (ISCLEAR(rect->flags, FILLED_BIT) && (rect->line_width == 0)) {
- return TCL_OK;
- }
-
- /*
- * Create the rectangle path.
- */
- sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g lineto closepath\n",
- rect->dev[0].x, rect->dev[0].y, rect->dev[1].x, rect->dev[1].y,
- rect->dev[2].x, rect->dev[2].y, rect->dev[3].x, rect->dev[3].y);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- /*
- * Emit code to draw the filled area.
- */
- if (ISSET(rect->flags, FILLED_BIT)) {
- if (rect->line_width) {
- Tcl_AppendResult(wi->interp, "gsave\n", NULL);
- }
- if (!ZnGradientFlat(rect->fill_color)) {
- if (ZnPostscriptGradient(wi->interp, wi->ps_info, rect->fill_color,
- rect->grad_geo ? rect->grad_geo : rect->dev, NULL) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- else if (rect->tile != ZnUnspecifiedImage) {
- if (!ZnImageIsBitmap(rect->tile)) { /* Fill tiled */
- if (ZnPostscriptTile(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- else { /* Fill stippled */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "clip ", NULL);
- if (ZnPostscriptStipple(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- }
- else { /* Fill solid */
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_AppendResult(wi->interp, "fill\n", NULL);
- }
- if (rect->line_width) {
- Tcl_AppendResult(wi->interp, "grestore\n", NULL);
- }
- }
-
- /*
- * Then emit code code to stroke the outline.
- */
- if (rect->line_width) {
- if (rect->relief != ZN_RELIEF_FLAT) {
- /* TODO No support yet */
- }
- else {
- Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
- if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
- rect->line_width, rect->line_style,
- rect->line_color, rect->line_pattern) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- RectangleItem rect = (RectangleItem) item;
- ZnPoint *points;
-
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- ZnListAssertSize(ZnWorkPoints, 2);
- points = ZnListArray(ZnWorkPoints);
- ZnTriStrip1(tristrip, points, 2, False);
- tristrip->strips[0].fan = False;
-
- if (rect->dev[0].x < rect->dev[2].x) {
- points[0].x = rect->dev[0].x;
- points[1].x = rect->dev[2].x+1.0;
- }
- else {
- points[0].x = rect->dev[2].x;
- points[1].x = rect->dev[0].x+1.0;
- }
- if (rect->dev[0].y < rect->dev[2].y) {
- points[0].y = rect->dev[0].y;
- points[1].y = rect->dev[2].y+1.0;
- }
- else {
- points[0].y = rect->dev[2].y;
- points[1].y = rect->dev[0].y+1.0;
- }
- }
- else {
- ZnListAssertSize(ZnWorkPoints, 4);
- points = ZnListArray(ZnWorkPoints);
- points[0] = rect->dev[1];
- points[1] = rect->dev[2];
- points[2] = rect->dev[0];
- points[3] = rect->dev[3];
- ZnTriStrip1(tristrip, points, 4, False);
- }
-
- return ISSET(rect->flags, ALIGNED_BIT);
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item vertices.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- RectangleItem rect = (RectangleItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " rectangles can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if (cmd == ZN_COORDS_REPLACE_ALL) {
- if (*num_pts != 2) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 2 points on rectangles", NULL);
- return TCL_ERROR;
- }
- rect->coords[0] = (*pts)[0];
- rect->coords[1] = (*pts)[1];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == ZN_COORDS_REPLACE) {
- if (*num_pts < 1) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need at least 1 point", NULL);
- return TCL_ERROR;
- }
- if (index < 0) {
- index += 2;
- }
- if ((index < 0) || (index > 1)) {
- range_err:
- Tcl_AppendResult(item->wi->interp,
- " incorrect coord index, should be between -2 and 1", NULL);
- return TCL_ERROR;
- }
- rect->coords[index] = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == ZN_COORDS_READ_ALL) {
- *num_pts = 2;
- *pts = rect->coords;
- }
- else if (cmd == ZN_COORDS_READ) {
- if (index < 0) {
- index += 2;
- }
- if ((index < 0) || (index > 1)) {
- goto range_err;
- }
- *num_pts = 1;
- *pts = &rect->coords[index];
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnBBox *bbox = &item->item_bounding_box;
-
- ZnOrigin2Anchor(&bbox->orig,
- bbox->corner.x - bbox->orig.x,
- bbox->corner.y - bbox->orig.y,
- anchor, p);
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct RECTANGLE_ITEM_CLASS = {
- "rectangle",
- sizeof(RectangleItemStruct),
- rect_attrs,
- 0, /* num_parts */
- 0, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- NULL, /* GetContours */
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnRectangle = (ZnItemClassId) &RECTANGLE_ITEM_CLASS;
diff --git a/generic/Reticle.c b/generic/Reticle.c
deleted file mode 100644
index cebeb98..0000000
--- a/generic/Reticle.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Reticle.c -- Implementation of Reticle item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Mon Feb 1 12:13:24 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-
-#include <math.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * Draw as many circles as visible.
- */
-#define ANY_CIRCLES -1
-
-/*
- * Some default values.
- */
-#define DEFAULT_RETICLE_STEP_SIZE 80
-#define DEFAULT_RETICLE_PERIOD 5
-
-/*
- **********************************************************************************
- *
- * Specific Reticle item record
- *
- **********************************************************************************
- */
-
-typedef struct _ReticleItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint pos; /* Origin world coordinates */
- ZnGradient *line_color; /* circle color */
- ZnGradient *bright_line_color; /* intermediate circle color */
- ZnDim first_radius; /* first world radius */
- ZnDim step_size; /* step world size */
- int period; /* bright circle period */
- int num_circles; /* num cercles max */
- ZnLineStyle line_style; /* circles lines styles */
- ZnLineStyle bright_line_style;
-
- /* Private data */
- ZnPoint dev; /* item device coordinate */
- ZnDim first_radius_dev; /* first device radius */
- ZnDim step_size_dev; /* steps device size */
-} ReticleItemStruct, *ReticleItem;
-
-
-static ZnAttrConfig reticle_attrs[] = {
- { ZN_CONFIG_GRADIENT, "-brightlinecolor", NULL,
- Tk_Offset(ReticleItemStruct, bright_line_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-brightlinestyle", NULL,
- Tk_Offset(ReticleItemStruct, bright_line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_DIM, "-stepsize", NULL,
- Tk_Offset(ReticleItemStruct, step_size), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_DIM, "-firstradius", NULL,
- Tk_Offset(ReticleItemStruct, first_radius), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
- Tk_Offset(ReticleItemStruct, line_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
- Tk_Offset(ReticleItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_UINT, "-numcircles", NULL,
- Tk_Offset(ReticleItemStruct, num_circles), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_UINT, "-period", NULL,
- Tk_Offset(ReticleItemStruct, period), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_POINT, "-position", NULL,
- Tk_Offset(ReticleItemStruct, pos), 0,
- ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(ReticleItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(ReticleItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(ReticleItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(ReticleItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ReticleItem reticle = (ReticleItem) item;
- ZnWInfo *wi = item->wi;
-
- SET(item->flags, ZN_VISIBLE_BIT);
- CLEAR(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 0;
- item->part_sensitive = 0;
- reticle->line_color = ZnGetGradientByValue(wi->fore_color);
- reticle->bright_line_color = ZnGetGradientByValue(wi->fore_color);
- reticle->first_radius = DEFAULT_RETICLE_STEP_SIZE;
- reticle->step_size = DEFAULT_RETICLE_STEP_SIZE;
- reticle->period = DEFAULT_RETICLE_PERIOD;
- reticle->num_circles = ANY_CIRCLES;
- reticle->line_style = ZN_LINE_SIMPLE;
- reticle->bright_line_style = ZN_LINE_SIMPLE;
- reticle->pos.x = 0;
- reticle->pos.y = 0;
- reticle->dev.x = 0;
- reticle->dev.y = 0;
- reticle->first_radius_dev = 0;
- reticle->step_size_dev = 0;
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- ReticleItem reticle = (ReticleItem) item;
-
- reticle->line_color = ZnGetGradientByValue(reticle->line_color);
- reticle->bright_line_color = ZnGetGradientByValue(reticle->bright_line_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- ReticleItem reticle = (ReticleItem) item;
-
- ZnFreeGradient(reticle->line_color);
- ZnFreeGradient(reticle->bright_line_color);
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- if (ZnConfigureAttributes(item->wi, item, item, reticle_attrs,
- argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, reticle_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- ReticleItem reticle = (ReticleItem) item;
- ZnDim half_width;
- ZnPoint p, xp;
-
- /* Compute center device coordinates */
- p.x = p.y = 0;
- ZnTransformPoint(wi->current_transfo, &p, &reticle->dev);
- p.x = reticle->step_size;
- ZnTransformPoint(wi->current_transfo, &p, &xp);
- reticle->step_size_dev = hypot(xp.x - reticle->dev.x, xp.y - reticle->dev.y);
- p.x = reticle->first_radius;
- ZnTransformPoint(wi->current_transfo, &p, &xp);
- reticle->first_radius_dev = hypot(xp.x - reticle->dev.x, xp.y - reticle->dev.y);
- if (reticle->first_radius_dev < 1.0) {
- reticle->first_radius_dev = 1.0;
- }
- if (reticle->step_size_dev < 1.0) {
- reticle->step_size_dev = 1.0;
- }
-
- /* Reticle bounding box is zn bounding box or depends on num_circles */
- if (reticle->num_circles == ANY_CIRCLES) {
- item->item_bounding_box.orig.x = 0;
- item->item_bounding_box.orig.y = 0;
- item->item_bounding_box.corner.x = wi->width;
- item->item_bounding_box.corner.y = wi->height;
- }
- else {
- half_width = reticle->first_radius_dev +
- (reticle->num_circles - 1) * reticle->step_size_dev;
- item->item_bounding_box.orig.x = reticle->dev.x - half_width;
- item->item_bounding_box.orig.y = reticle->dev.y - half_width;
- item->item_bounding_box.corner.x = item->item_bounding_box.orig.y + (2 * half_width);
- item->item_bounding_box.corner.y = item->item_bounding_box.orig.y + (2 * half_width);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- return -1;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ReticleItem reticle = (ReticleItem) item;
- ZnDim radius = reticle->first_radius_dev;
- ZnDim radius_max_dev;
- XGCValues values;
- int i;
- ZnDim l1, l2, l3, l4;
-/* int count = 0;*/
-
- /* Compute radius max */
- l1 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x,
- wi->damaged_area.orig.y - reticle->dev.y);
- l2 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x,
- wi->damaged_area.orig.y - reticle->dev.y);
- l3 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x,
- wi->damaged_area.corner.y - reticle->dev.y);
- l4 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x,
- wi->damaged_area.corner.y - reticle->dev.y);
- radius_max_dev = MAX(MAX(l1,l2), MAX(l3, l4));
-
- if (reticle->num_circles > 0) {
- radius_max_dev = MIN(radius_max_dev, reticle->first_radius_dev +
- (reticle->num_circles - 1) * reticle->step_size_dev);
- }
-
- while (radius <= radius_max_dev) {
- ZnSetLineStyle(wi, reticle->line_style);
- values.foreground = ZnGetGradientPixel(reticle->line_color, 0.0);
- values.line_width = 0;
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values);
- for (i = 1; ((radius <= radius_max_dev) && (i < reticle->period)); i++) {
- if ((reticle->dev.x >= wi->damaged_area.orig.x - radius) &&
- (reticle->dev.x <= wi->damaged_area.corner.x + radius) &&
- (reticle->dev.y >= wi->damaged_area.orig.y - radius) &&
- (reticle->dev.y <= wi->damaged_area.corner.y + radius)) {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- (int) (reticle->dev.x - radius),
- (int) (reticle->dev.y - radius),
- (unsigned int) (radius * 2 - 1),
- (unsigned int) (radius * 2 - 1),
- 0, 360 * 64);
-/* count++;*/
- }
- radius += (reticle->step_size_dev);
- }
- if ((radius <= radius_max_dev) &&
- (reticle->dev.x >= wi->damaged_area.orig.x - radius) &&
- (reticle->dev.x <= wi->damaged_area.corner.x + radius) &&
- (reticle->dev.y >= wi->damaged_area.orig.y - radius) &&
- (reticle->dev.y <= wi->damaged_area.corner.y + radius)) {
- ZnSetLineStyle(wi, reticle->bright_line_style);
- values.foreground = ZnGetGradientPixel(reticle->bright_line_color, 0.0);
- values.line_width = 0;
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values);
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- (int) (reticle->dev.x - radius),
- (int) (reticle->dev.y - radius),
- (unsigned int) (radius * 2 - 1),
- (unsigned int) (radius * 2 - 1),
- 0, 360 * 64);
- /*count++;*/
- }
- radius += (reticle->step_size_dev);
- }
-/*printf("# circles drawn: %d\n", count);*/
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- ReticleItem reticle = (ReticleItem) item;
- ZnDim radius = reticle->first_radius_dev;
- ZnDim radius_max_dev, new, x, y, xo, yo;
- int i, j;
- ZnPoint *genarc;
- int num_p;
- unsigned short alpha;
- XColor *color;
-
- xo = reticle->dev.x;
- yo = reticle->dev.y;
- /* Compute radius max */
- radius_max_dev = 0;
- x = wi->damaged_area.orig.x - xo;
- y = wi->damaged_area.orig.y - yo;
- new = x*x + y*y;
- if (new > radius_max_dev) {
- radius_max_dev = new;
- }
- x = wi->damaged_area.corner.x - xo;
- y = wi->damaged_area.orig.y - yo;
- new = x*x + y*y;
- if (new > radius_max_dev) {
- radius_max_dev = new;
- }
- x = wi->damaged_area.orig.x - xo;
- y = wi->damaged_area.corner.y - yo;
- new = x*x + y*y;
- if (new > radius_max_dev) {
- radius_max_dev = new;
- }
- x = wi->damaged_area.corner.x - xo;
- y = wi->damaged_area.corner.y - yo;
- new = x*x + y*y;
- if (new > radius_max_dev) {
- radius_max_dev = new;
- }
- radius_max_dev = sqrt(radius_max_dev);
-
- if (reticle->num_circles > 0) {
- radius_max_dev = MIN(radius_max_dev, reticle->first_radius_dev +
- (reticle->num_circles - 1) * reticle->step_size_dev);
- }
-
- genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINER, 0.0, 2*M_PI, &num_p, NULL);
- glLineWidth(1.0);
- while (radius <= radius_max_dev) {
- ZnSetLineStyle(wi, reticle->line_style);
- color = ZnGetGradientColor(reticle->line_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- for (i = 1; ((radius <= radius_max_dev) && (i < reticle->period)); i++) {
- if ((xo >= wi->damaged_area.orig.x - radius) &&
- (xo <= wi->damaged_area.corner.x + radius) &&
- (yo >= wi->damaged_area.orig.y - radius) &&
- (yo <= wi->damaged_area.corner.y + radius)) {
- glBegin(GL_LINE_LOOP);
- for (j = 0; j < num_p; j++) {
- x = xo + genarc[j].x * radius;
- y = yo + genarc[j].y * radius;
- glVertex2d(x, y);
- }
- glEnd();
- }
- radius += (reticle->step_size_dev);
- }
- if ((radius <= radius_max_dev) &&
- (xo >= wi->damaged_area.orig.x - radius) &&
- (xo <= wi->damaged_area.corner.x + radius) &&
- (yo >= wi->damaged_area.orig.y - radius) &&
- (yo <= wi->damaged_area.corner.y + radius)) {
- ZnSetLineStyle(wi, reticle->bright_line_style);
- color = ZnGetGradientColor(reticle->bright_line_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glBegin(GL_LINE_LOOP);
- for (j = 0; j < num_p; j++) {
- x = xo + genarc[j].x * radius;
- y = yo + genarc[j].y * radius;
- glVertex2d(x, y);
- }
- glEnd();
- }
- radius += (reticle->step_size_dev);
- }
- glDisable(GL_LINE_STIPPLE);
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- * Nothing to pick, we are almost transparent.
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- return 1e40;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item center.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- ReticleItem reticle = (ReticleItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " reticles can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on reticles", NULL);
- return TCL_ERROR;
- }
- reticle->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &reticle->pos;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct RETICLE_ITEM_CLASS = {
- "reticle",
- sizeof(ReticleItemStruct),
- reticle_attrs,
- 0, /* num_parts */
- ZN_CLASS_ONE_COORD, /* flags */
- Tk_Offset(ReticleItemStruct, pos),
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- NULL, /* GetAnchor */
- NULL, /* GetClipVertices */
- NULL, /* GetContours */
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnReticle = (ZnItemClassId) &RETICLE_ITEM_CLASS;
diff --git a/generic/Tabular.c b/generic/Tabular.c
deleted file mode 100644
index c0d9886..0000000
--- a/generic/Tabular.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * Tabular.c -- Implementation of Tabular item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "Item.h"
-#include "Geo.h"
-#include "tkZinc.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- **********************************************************************************
- *
- * Specific Tabular item record
- *
- **********************************************************************************
- */
-typedef struct _TabularItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint pos;
- Tk_Anchor anchor;
- Tk_Anchor connection_anchor;
-
- /* Private data */
- ZnFieldSetStruct field_set;
-} TabularItemStruct, *TabularItem;
-
-
-static ZnAttrConfig tabular_attrs[] = {
- { ZN_CONFIG_ANCHOR, "-anchor", NULL,
- Tk_Offset(TabularItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(TabularItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
- Tk_Offset(TabularItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
- Tk_Offset(TabularItemStruct, field_set.label_format), 0,
- ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_UINT, "-numfields", NULL,
- Tk_Offset(TabularItemStruct, field_set.num_fields), 0, 0, True },
- { ZN_CONFIG_POINT, "-position", NULL,
- Tk_Offset(TabularItemStruct, pos), 0, ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(TabularItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(TabularItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(TabularItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(TabularItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- TabularItem tab = (TabularItem) item;
- ZnFieldSet field_set = &tab->field_set;
- int num_fields;
-
- item->priority = 1;
-
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
-
- tab->anchor = TK_ANCHOR_NW;
- tab->connection_anchor = TK_ANCHOR_SW;
- tab->pos.x = tab->pos.y = 0.0;
-
- field_set->item = item;
- field_set->label_format = NULL;
-
- /*
- * Then try to see if some fields are needed.
- */
- if ((*argc > 0) && (Tcl_GetString((*args)[0])[0] != '-') &&
- (Tcl_GetIntFromObj(wi->interp, (*args)[0], &num_fields) != TCL_ERROR)) {
- field_set->num_fields = num_fields;
- *args += 1;
- *argc -= 1;
- ZnFIELD.InitFields(field_set);
- }
- else {
- Tcl_AppendResult(wi->interp, " number of fields expected", NULL);
- return TCL_ERROR;
- }
-
- item->part_sensitive = 0;
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- ZnFieldSet fs = &((TabularItem) item)->field_set;
-
- ZnFIELD.CloneFields(fs);
- fs->item = item;
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- ZnFIELD.FreeFields(&((TabularItem) item)->field_set);
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- ZnItem old_connected;
-
- old_connected = item->connected_item;
- if (ZnConfigureAttributes(item->wi, item, item, tabular_attrs,
- argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- /*
- * If the new connected item is not appropriate back up
- * to the old one.
- */
- if ((item->connected_item == ZN_NO_ITEM) ||
- (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
- (item->parent == item->connected_item->parent))) {
- ZnITEM.UpdateItemDependency(item, old_connected);
- }
- else {
- item->connected_item = old_connected;
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, tabular_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- TabularItem tab = (TabularItem) item;
- ZnWInfo *wi = item->wi;
- ZnFieldSet field_set = &tab->field_set;
- ZnDim width, height;
-
- ZnResetBBox(&item->item_bounding_box);
- if (field_set->label_format && field_set->num_fields) {
- ZnFIELD.GetLabelBBox(field_set, &width, &height);
-
- /*
- * The connected item support anchors, this is checked by
- * configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- item->connected_item->class->GetAnchor(item->connected_item,
- tab->connection_anchor,
- &field_set->label_pos);
- }
- else {
- ZnPoint pos;
- pos.x = pos.y = 0;
- ZnTransformPoint(wi->current_transfo, &pos,
- &field_set->label_pos);
- }
-
- ZnAnchor2Origin(&field_set->label_pos, width, height, tab->anchor,
- &field_set->label_pos);
-
- /*
- * Setup the item bounding box.
- */
- item->item_bounding_box.orig = field_set->label_pos;
- item->item_bounding_box.corner.x = field_set->label_pos.x + width;
- item->item_bounding_box.corner.y = field_set->label_pos.y + height;
- /*
- * Need to slightly increase the bbox for GL thick lines
- */
-#ifdef GL
- 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;
-#endif
-
- /*
- * Update connected items.
- */
- SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- return ZnFIELD.FieldsToArea(&((TabularItem) item)->field_set, ta->area);
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnFIELD.DrawFields(&((TabularItem) item)->field_set);
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-static void
-Render(ZnItem item)
-{
- ZnFIELD.RenderFields(&((TabularItem) item)->field_set);
-}
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- if (ISCLEAR(item->flags, ZN_SENSITIVE_BIT) ||
- !item->parent->class->IsSensitive(item->parent, ZN_NO_PART)) {
- return False;
- }
- if (item_part == ZN_NO_PART) {
- return ISSET(item->flags, ZN_SENSITIVE_BIT);
- }
- else {
- return ZnFIELD.IsFieldSensitive(&((TabularItem) item)->field_set, item_part);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- * We tell what our label tells.
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- int best_part;
- double dist;
-
- dist = ZnFIELD.FieldsPick(&((TabularItem) item)->field_set, ps->point, &best_part);
- /*printf("tabular %d reporting part %d, distance %lf\n",
- item->id, best_part, dist);*/
- if (dist <= 0.0) {
- dist = 0.0;
- }
-
- ps->a_part = best_part;
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- return ZnFIELD.PostScriptFields(&((TabularItem) item)->field_set, prepass, area);
-}
-
-
-/*
- **********************************************************************************
- *
- * GetFieldSet --
- *
- **********************************************************************************
- */
-static ZnFieldSet
-GetFieldSet(ZnItem item)
-{
- return &((TabularItem) item)->field_set;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnFieldSet field_set = &((TabularItem) item)->field_set;
- ZnDim width, height;
-
- if (field_set->label_format) {
- ZnFIELD.GetLabelBBox(field_set, &width, &height);
- ZnOrigin2Anchor(&field_set->label_pos, width, height, anchor, p);
- }
- else {
- p->x = p->y = 0.0;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- ZnFieldSet field_set = &((TabularItem) item)->field_set;
- ZnDim width, height;
- ZnPoint *points;
-
- if (field_set->label_format) {
- ZnFIELD.GetLabelBBox(field_set, &width, &height);
- ZnListAssertSize(ZnWorkPoints, 2);
- points = (ZnPoint *) ZnListArray(ZnWorkPoints);
- ZnTriStrip1(tristrip, points, 2, False);
- points[0] = field_set->label_pos;
- points[1].x = points[0].x + width;
- points[1].y = points[0].y + height;
- }
-
- return True;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item origin. This doesn't take care of
- * the possible attachment. The change will be effective at the
- * end of the attachment.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- TabularItem tabular = (TabularItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " tabulars can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on tabulars", NULL);
- return TCL_ERROR;
- }
- tabular->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &tabular->pos;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Part --
- * Convert a private part from/to symbolic representation.
- *
- **********************************************************************************
- */
-static int
-Part(ZnItem item,
- Tcl_Obj **part_spec,
- int *part)
-{
- char *part_str;
- char *end;
-
- if (*part_spec) {
- part_str = Tcl_GetString(*part_spec);
- if (strlen(part_str) == 0) {
- *part = ZN_NO_PART;
- }
- else if (isdigit(part_str[0])) {
- *part = strtol(part_str, &end, 0);
- if ((*end != 0) || (*part < 0) ||
- ((unsigned int) *part >= ((TabularItem) item)->field_set.num_fields)) {
- goto part_error;
- }
- }
- else {
- part_error:
- Tcl_AppendResult(item->wi->interp, " invalid item part specification", NULL);
- return TCL_ERROR;
- }
- }
- else {
- if (*part >= 0) {
- *part_spec = Tcl_NewIntObj(*part);
- }
- else {
- *part_spec = Tcl_NewStringObj("", -1);
- }
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Index --
- * Parse a text index and return its value and aa
- * error status (standard Tcl result).
- *
- **********************************************************************************
- */
-static int
-Index(ZnItem item,
- int field,
- Tcl_Obj *index_spec,
- int *index)
-{
- return ZnFIELD.FieldIndex(&((TabularItem) item)->field_set, field,
- index_spec, index);
-}
-
-
-/*
- **********************************************************************************
- *
- * InsertChars --
- *
- **********************************************************************************
- */
-static void
-InsertChars(ZnItem item,
- int field,
- int *index,
- char *chars)
-{
- if (ZnFIELD.FieldInsertChars(&((TabularItem) item)->field_set,
- field, index, chars)) {
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * DeleteChars --
- *
- **********************************************************************************
- */
-static void
-DeleteChars(ZnItem item,
- int field,
- int *first,
- int *last)
-{
- if (ZnFIELD.FieldDeleteChars(&((TabularItem) item)->field_set,
- field, first, last)) {
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Cursor --
- *
- **********************************************************************************
- */
-static void
-TabularCursor(ZnItem item,
- int field,
- int index)
-{
- ZnFIELD.FieldCursor(&((TabularItem) item)->field_set, field, index);
-}
-
-
-/*
- **********************************************************************************
- *
- * Selection --
- *
- **********************************************************************************
- */
-static int
-Selection(ZnItem item,
- int field,
- int offset,
- char *chars,
- int max_chars)
-{
- return ZnFIELD.FieldSelection(&((TabularItem) item)->field_set, field,
- offset, chars, max_chars);
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions structs --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct TABULAR_ITEM_CLASS = {
- "tabular",
- sizeof(TabularItemStruct),
- tabular_attrs,
- 0,
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- Tk_Offset(TabularItemStruct, pos),
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- GetFieldSet,
- GetAnchor,
- GetClipVertices,
- NULL, /* GetContours */
- Coords,
- InsertChars,
- DeleteChars,
- TabularCursor,
- Index,
- Part,
- Selection,
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnTabular = (ZnItemClassId) &TABULAR_ITEM_CLASS;
diff --git a/generic/Text.c b/generic/Text.c
deleted file mode 100644
index b2e83f8..0000000
--- a/generic/Text.c
+++ /dev/null
@@ -1,2061 +0,0 @@
-/*
- * Text.c -- Implementation of Text item.
- *
- * Authors : Patrick LECOANET
- * Creation date : Sat Mar 25 13:58:39 1995
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * Some functions in this file are derived from tkCanvText.c and thus
- * copyrighted:
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
- *
- */
-
-#include <math.h>
-#include <ctype.h>
-#include <X11/Xatom.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "Item.h"
-#include "Geo.h"
-#include "Draw.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-#include "Image.h"
-
-
-static const char rcsid[] = "$Imagine: Text.c,v 1.13 1997/05/15 11:35:46 lecoanet Exp $";
-static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * Bit offset of flags.
- */
-#define UNDERLINED 1
-#define OVERSTRIKED 2
-
-
-/*
- **********************************************************************************
- *
- * Specific Text item record
- *
- **********************************************************************************
- */
-typedef struct _TextLineInfo
-{
- char *start; /* Index of first char in line */
- unsigned short num_bytes; /* Number of displayed bytes in line (NOT chars)*/
- unsigned short width; /* Line width in pixels */
- unsigned short origin_x; /* X pos for drawing the line */
- unsigned short origin_y;
-} TextLineInfoStruct, *TextLineInfo;
-
-typedef struct _TextItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint pos; /* Position at anchor */
- ZnGradient *color;
- char *text;
- ZnImage fill_pattern;
- Tk_Font font;
- unsigned short width;
- short spacing;
- unsigned short flags;
- Tk_Anchor anchor;
- Tk_Anchor connection_anchor;
- Tk_Justify alignment;
-
- /* Private data */
- unsigned short num_chars;
- unsigned short insert_index;
- ZnList text_info;
- unsigned short max_width;
- unsigned short height;
- ZnPoint poly[4];
-#ifdef GL
- ZnTexFontInfo *tfi;
-#endif
-} TextItemStruct, *TextItem;
-
-
-static ZnAttrConfig text_attrs[] = {
- { ZN_CONFIG_ALIGNMENT, "-alignment", NULL,
- Tk_Offset(TextItemStruct, alignment), 0,
- ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-anchor", NULL,
- Tk_Offset(TextItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-color", NULL,
- Tk_Offset(TextItemStruct, color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(TextItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
- Tk_Offset(TextItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
- Tk_Offset(TextItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_FONT, "-font", NULL,
- Tk_Offset(TextItemStruct, font), 0,
- ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
- { ZN_CONFIG_BOOL, "-overstriked", NULL,
- Tk_Offset(TextItemStruct, flags), OVERSTRIKED, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TextItemStruct, pos), 0,
- ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(TextItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(TextItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_SHORT, "-spacing", NULL,
- Tk_Offset(TextItemStruct, spacing), 0,
- ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(TextItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_STRING, "-text", NULL,
- Tk_Offset(TextItemStruct, text), 0,
- ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
- { ZN_CONFIG_BOOL, "-underlined", NULL,
- Tk_Offset(TextItemStruct, flags), UNDERLINED, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(TextItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
- { ZN_CONFIG_USHORT, "-width", NULL,
- Tk_Offset(TextItemStruct, width), 0,
- ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- TextItem text = (TextItem) item;
-
- /*printf("size of a text(header) = %d(%d) %d\n",
- sizeof(TextItemStruct), sizeof(ZnItemStruct), sizeof(TextLineInfoStruct));*/
-
- text->text_info = NULL;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- CLEAR(item->flags, ZN_COMPOSE_ROTATION_BIT);
- CLEAR(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 1;
-
- text->pos.x = text->pos.y = 0.0;
- text->text = NULL;
- text->num_chars = 0;
- text->fill_pattern = ZnUnspecifiedImage;
- text->anchor = TK_ANCHOR_NW;
- text->connection_anchor = TK_ANCHOR_SW;
- text->color = ZnGetGradientByValue(wi->fore_color);
- text->alignment = TK_JUSTIFY_LEFT;
- text->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(wi->font));
-#ifdef GL
- text->tfi = ZnGetTexFont(wi, text->font);
-#endif
- text->width = 0;
- text->spacing = 0;
- text->insert_index = 0;
- CLEAR(text->flags, UNDERLINED);
- CLEAR(text->flags, OVERSTRIKED);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- char *str;
-
- if (text->text) {
- str = ZnMalloc((strlen(text->text) + 1) * sizeof(char));
- strcpy(str, text->text);
- text->text = str;
- }
- if (text->fill_pattern != ZnUnspecifiedImage) {
- text->fill_pattern = ZnGetImageByValue(text->fill_pattern, NULL, NULL);
- }
- text->color = ZnGetGradientByValue(text->color);
- text->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(text->font));
-#ifdef GL
- text->tfi = ZnGetTexFont(wi, text->font);
-#endif
-
- /*
- * We always need to invalidate, either because the model
- * has not done its layout (text_info == NULL) or because
- * we must unshare the pointers to the text that are in
- * text_info.
- */
- text->text_info = NULL;
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- TextItem text = (TextItem) item;
-
- if (text->text) {
- ZnFree(text->text);
- }
- if (text->fill_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(text->fill_pattern, NULL, NULL);
- text->fill_pattern = ZnUnspecifiedImage;
- }
- ZnFreeGradient(text->color);
- Tk_FreeFont(text->font);
-#ifdef GL
- if (text->tfi) {
- ZnFreeTexFont(text->tfi);
- }
-#endif
-
- if (text->text_info) {
- ZnListFree(text->text_info);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- TextItem text = (TextItem) item;
- ZnItem old_connected = item->connected_item;
- unsigned int num_chars;
-#ifdef GL
- Tk_Font old_font = text->font;
-#endif
-
- if (ZnConfigureAttributes(item->wi, item, item, text_attrs,
- argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
-#ifdef GL
- if (old_font != text->font) {
- if (text->tfi) {
- ZnFreeTexFont(text->tfi);
- text->tfi = ZnGetTexFont(item->wi, text->font);
- }
- }
-#endif
- num_chars = 0;
- if (text->text) {
- num_chars = Tcl_NumUtfChars(text->text, (int) strlen(text->text));
- }
- if (text->num_chars != num_chars) {
- ZnTextInfo *ti = &item->wi->text_info;
- /*
- * The text has changed, update the selection and
- * insertion pos to keep them valid.
- */
- if (item == ti->sel_item) {
- if (ti->sel_last > (int) num_chars) {
- ti->sel_last = num_chars;
- }
- if (ti->sel_first >= ti->sel_last) {
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
- }
- if ((ti->anchor_item == item) && (ti->sel_anchor > (int) num_chars)) {
- ti->sel_anchor = num_chars;
- }
- }
- if (text->insert_index > num_chars) {
- text->insert_index = num_chars;
- }
- text->num_chars = num_chars;
- }
-
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- /*
- * If the new connected item is not appropriate back up
- * to the old one.
- */
- if ((item->connected_item == ZN_NO_ITEM) ||
- (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
- (item->parent == item->connected_item->parent))) {
- ZnITEM.UpdateItemDependency(item, old_connected);
- }
- else {
- item->connected_item = old_connected;
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, text_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- * Compute the transformation to be used and the origin
- * of the text (upper left point in item coordinates).
- */
-static ZnTransfo *
-ComputeTransfoAndOrigin(ZnItem item,
- ZnPoint *origin)
-{
- TextItem text = (TextItem) item;
-
- /*
- * The connected item support anchors, this is checked by configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- ZnTransfo inv;
-
- item->connected_item->class->GetAnchor(item->connected_item,
- text->connection_anchor,
- origin);
-
- /* GetAnchor return a position in device coordinates not in
- * the item coordinate space. To compute the text origin
- * (upper left corner), we must apply the inverse transform
- * to the ref point before calling anchor2origin.
- */
- ZnTransfoInvert(item->transfo, &inv);
- ZnTransformPoint(&inv, origin, origin);
- ZnAnchor2Origin(origin, (ZnReal) text->max_width,
- (ZnReal) text->height, text->anchor, origin);
- origin->x = ZnNearestInt(origin->x);
- origin->y = ZnNearestInt(origin->y);
- /*
- * The relevant transform in case of an attachment is the item
- * transform alone. This is case of local coordinate space where
- * only the translation is a function of the whole transform
- * stack, scale and rotation are reset.
- */
- return item->transfo;
- }
- else {
- ZnPoint p;
- p.x = p.y = 0;
- ZnAnchor2Origin(&p, (ZnReal) text->max_width,
- (ZnReal) text->height, text->anchor, origin);
- origin->x = ZnNearestInt(origin->x);
- origin->y = ZnNearestInt(origin->y);
-
- return item->wi->current_transfo;
- }
-}
-
-
-/*
- * Compute the selection and the cursor geometry.
- */
-void
-ComputeCursor(ZnItem item,
- int *cursor_line,
- unsigned int *cursor_offset)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- TextLineInfo lines, lines_ptr;
- unsigned int i, line_index, insert_index, num_lines;
-
- num_lines = ZnListSize(text->text_info);
- if (num_lines == 0) {
- *cursor_line = 0;
- }
-
- lines = ZnListArray(text->text_info);
- if ((wi->focus_item == item) && ISSET(wi->flags, ZN_GOT_FOCUS) && ti->cursor_on) {
- insert_index = Tcl_UtfAtIndex(text->text, (int) text->insert_index)-text->text;
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- /*
- * Mark the line with the cursor and compute its
- * position along the X axis.
- */
- line_index = lines_ptr->start - text->text;
- if ((insert_index >= line_index) &&
- (insert_index <= line_index + lines_ptr->num_bytes)) {
- *cursor_line = i;
- *cursor_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- insert_index - line_index);
- }
- }
- }
-
-}
-
-static void
-ComputeSelection(ZnItem item,
- int *sel_first_line,
- int *sel_last_line,
- unsigned int *sel_start_offset,
- unsigned int *sel_stop_offset)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- TextLineInfo lines_ptr, lines;
- int i, num_lines, byte_index;
- unsigned int line_index;
- unsigned int sel_first, sel_last;
-
- num_lines = ZnListSize(text->text_info);
-
- if ((ti->sel_item != item) || !num_lines) {
- return;
- }
-
- lines = ZnListArray(text->text_info);
-
- sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first)-text->text;
- sel_last = Tcl_UtfAtIndex(text->text, ti->sel_last+1)-text->text;
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- /*
- * Compute the selection first and last line as well as
- * the positions along the X axis.
- */
- line_index = lines_ptr->start - text->text;
- if ((sel_last >= line_index) &&
- (sel_first <= (line_index + lines_ptr->num_bytes))) {
- if (*sel_first_line < 0) {
- byte_index = sel_first - line_index;
- if (byte_index <= 0) {
- *sel_first_line = i;
- *sel_start_offset = 0;
- /*printf("sel_start_offset 1 : %d\n", *sel_start_offset);*/
- }
- else if (byte_index <= lines_ptr->num_bytes) {
- *sel_first_line = i;
- *sel_start_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- byte_index);
- /*printf("sel_start_offset 2 : %d\n", *sel_start_offset);*/
- }
- }
- byte_index = ti->sel_last+1 - line_index;
- *sel_last_line = i;
- if (byte_index == lines_ptr->num_bytes+1)
- *sel_stop_offset = lines_ptr->width;
- else if (byte_index <= lines_ptr->num_bytes)
- *sel_stop_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- byte_index);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- TextItem text = (TextItem) item;
- TextLineInfo infos;
- Tk_FontMetrics fm;
- ZnTransfo *transfo;
- int i, num_lines, cur_dy, font_height;
-
- ZnResetBBox(&item->item_bounding_box);
-
- Tk_GetFontMetrics(text->font, &fm);
- font_height = fm.ascent+fm.descent;
-
- /*
- * The layout need not be done each time the item is moved, scaled
- * or rotated.
- */
- if (ISSET(item->inv_flags, ZN_LAYOUT_FLAG)) {
- char *scan;
- int wrap, prev_num_lines;
-
- text->max_width = 0;
- if (text->text_info != NULL) {
- prev_num_lines = ZnListSize(text->text_info);
- ZnListEmpty(text->text_info);
- }
- else {
- prev_num_lines = 0;
- text->text_info = ZnListNew(1, sizeof(TextLineInfoStruct));
- }
-
- if (text->width > 0) {
- wrap = text->width;
- }
- else {
- wrap = 100000;
- }
-
- if ((scan = text->text) != NULL) {
- TextLineInfoStruct info;
-
- while (*scan) {
- char *special;
- int num, w;
-
- /*
- * Limit the excursion of Tk_MeasureChars to the end
- * of the line. Do not include \n in the measure done.
- */
- num = strcspn(scan, "\r\n");
- special = scan + num;
- info.num_bytes = Tk_MeasureChars(text->font, scan, num, wrap,
- TK_WHOLE_WORDS|TK_AT_LEAST_ONE, &w);
-
- info.width = w;
- info.start = scan;
- text->max_width = MAX(info.width, text->max_width);
-
- scan += info.num_bytes;
-
- /*
- * Skip the newline line character.
- */
- if ((*scan == '\r') || (*scan == '\n')) {
- scan++;
- }
- else {
- /*
- * Skip white spaces occuring after an
- * automatic line break.
- */
- while (*scan == ' ') {
- scan++;
- }
- }
-
- ZnListAdd(text->text_info, &info, ZnListTail);
- /*printf("adding a text info : %s, num_bytes : %d, width : %d\n",
- info.start, info.num_bytes, info.width);*/
- }
- if (*text->text && ((scan[-1] == '\r') || (scan[-1] == '\n'))) {
- /* Build a text info even for an empty line
- * at the end of text or for an empty text.
- * It is needed to enable selection and cursor
- * insertion to behave correctly.
- */
- info.num_bytes = 0;
- info.width = 0;
- info.start = scan;
- ZnListAdd(text->text_info, &info, ZnListTail);
- }
- }
-
- /*
- * Compute x & y positions for all lines in text_info. The coordinates are
- * in text natural units NOT transformed units.
- */
- cur_dy = fm.ascent;
- num_lines = ZnListSize(text->text_info);
- infos = (TextLineInfo) ZnListArray(text->text_info);
-
- for (i = 0; i < num_lines; i++) {
- switch (text->alignment) {
- case TK_JUSTIFY_LEFT:
- infos[i].origin_x = 0;
- break;
- case TK_JUSTIFY_CENTER:
- infos[i].origin_x = (text->max_width + 1 - infos[i].width)/2;
- break;
- case TK_JUSTIFY_RIGHT:
- infos[i].origin_x = text->max_width + 1 - infos[i].width;
- break;
- }
- infos[i].origin_y = cur_dy;
- cur_dy += font_height + text->spacing;
- /*printf("fixing line %d x : %d, y : %d\n", i, infos[i].origin_x,
- infos[i].origin_y);*/
- }
- } /* ISSET(item->inv_flags, INV_TEXT_LAYOUT) */
-
- text->height = font_height;
- if (text->text_info && text->max_width) {
- unsigned int h, cursor_offset;
- int cursor_line;
- ZnPoint origin, box[4];
-
- num_lines = ZnListSize(text->text_info);
- infos = ZnListArray(text->text_info);
- h = num_lines * font_height + (num_lines-1) * text->spacing;
- text->height = MAX(text->height, h);
-
- transfo = ComputeTransfoAndOrigin(item, &origin);
-
- text->poly[0].x = origin.x;
- text->poly[0].y = origin.y;
- text->poly[3].x = text->poly[0].x + text->max_width;
- text->poly[3].y = text->poly[0].y + text->height;
- text->poly[1].x = text->poly[0].x;
- text->poly[1].y = text->poly[3].y;
- text->poly[2].x = text->poly[3].x;
- text->poly[2].y = text->poly[0].y;
- ZnTransformPoints(transfo, text->poly, text->poly, 4);
-
- /*
- * Add to the bounding box.
- */
- ZnAddPointsToBBox(&item->item_bounding_box, text->poly, 4);
-
- /*
- * Add the cursor shape to the bbox.
- */
- cursor_line = -1;
- ComputeCursor(item, &cursor_line, &cursor_offset);
- if (cursor_line >= 0) {
- if (num_lines) {
- box[0].x = origin.x + infos[cursor_line].origin_x + cursor_offset -
- wi->text_info.insert_width/2;
- box[0].y = origin.y + infos[cursor_line].origin_y - fm.ascent + 1;
- }
- else {
- box[0].x = origin.x;
- box[0].y = origin.y;
- }
- box[2].x = box[0].x + wi->text_info.insert_width;
- box[2].y = box[0].y + font_height - 1;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- ZnAddPointsToBBox(&item->item_bounding_box, box, 4);
- }
- }
-
- /*printf("bbox origin: %g %g corner %g %g\n",
- item->item_bounding_box.orig.x, item->item_bounding_box.orig.y,
- item->item_bounding_box.corner.x, item->item_bounding_box.corner.y);*/
- /*
- * Update connected items.
- */
- SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- TextItem text = (TextItem) item;
- int inside = -1;
- ZnBool first_done = False;
- int num_lines, i;
- TextLineInfo lines, lines_ptr;
- Tk_FontMetrics fm;
- int font_height;
- ZnBBox line_bbox, *area = ta->area;
- ZnPoint box[4], p, origin;
- ZnTransfo inv, *transfo;
-
- if (!text->text_info || !text->text) {
- return -1;
- }
-
- transfo = ComputeTransfoAndOrigin(item, &origin);
- box[0] = area->orig;
- box[2] = area->corner;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransfoInvert(transfo, &inv);
- ZnTransformPoints(&inv, box, box, 4);
-
- lines = (TextLineInfo) ZnListArray(text->text_info);
- num_lines = ZnListSize(text->text_info);
- Tk_GetFontMetrics(text->font, &fm);
- font_height = fm.descent + fm.ascent;
- if (text->spacing > 0) {
- font_height += text->spacing;
- }
-
- /*printf("text %d, num lines=%d\n", item->id, num_lines);*/
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- ZnResetBBox(&line_bbox);
- p.x = origin.x + lines_ptr->origin_x;
- p.y = origin.y + lines_ptr->origin_y - fm.ascent;
- ZnAddPointToBBox(&line_bbox, p.x, p.y);
- ZnAddPointToBBox(&line_bbox, p.x + lines_ptr->width, p.y + font_height);
- if (!first_done) {
- first_done = True;
- inside = ZnPolygonInBBox(box, 4, &line_bbox, NULL);
- if (inside == 0) {
- return 0;
- }
- }
- else {
- if (ZnPolygonInBBox(box, 4, &line_bbox, NULL) == 0) {
- return 0;
- }
- }
- }
-
- return inside;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TextItem text = (TextItem) item;
- XGCValues values;
- ZnPoint pos, box[4], origin;
- ZnTransfo *transfo;
- Drawable drw;
- GC gc;
- XImage *src_im, *dest_im=NULL;
- unsigned int dest_im_width=0, dest_im_height=0;
- unsigned int gc_mask = 0;
- Tk_FontMetrics fm;
- unsigned int font_height;
- int num_lines, i;
- TextLineInfo lines, lines_ptr;
- ZnTextInfo *ti = &wi->text_info;
- unsigned int underline_thickness, underline_pos=0, overstrike_pos=0;
- int sel_first_line=-1, sel_last_line=-1, cursor_line=-1;
- unsigned int sel_start_offset=0, sel_stop_offset=0, cursor_offset=0;
-
- if (!text->text_info/* || !text->text*/) {
- return;
- }
-
- lines = (TextLineInfo) ZnListArray(text->text_info);
- num_lines = ZnListSize(text->text_info);
- Tk_GetFontMetrics(text->font, &fm);
- font_height = fm.ascent+fm.descent;
-
- transfo = ComputeTransfoAndOrigin(item, &origin);
-
- /*
- * Compute the selection and the cursor geometry.
- */
- ComputeCursor(item, &cursor_line, &cursor_offset);
- ComputeSelection(item, &sel_first_line, &sel_last_line,
- &sel_start_offset, &sel_stop_offset);
-
-
- ZnTransformPoint(transfo, &origin, &pos);
-
- /*printf("sel 1st : %d offset : %d, sel last : %d offset : %d\n",
- sel_first_line, sel_start_offset, sel_last_line, sel_stop_offset);*/
- /*
- * Setup the gc for the selection and fill the selection.
- */
- if ((ti->sel_item == item) && (sel_first_line >= 0)) {
- XPoint xp[4];
-
- values.foreground = ZnGetGradientPixel(ti->sel_color, 0.0);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
-
- if (sel_first_line == sel_last_line) {
- box[0].x = origin.x +
- lines[sel_first_line].origin_x + sel_start_offset;
- box[0].y = origin.y +
- lines[sel_first_line].origin_y - fm.ascent;
- box[2].x = box[0].x + sel_stop_offset - sel_start_offset;
- box[2].y = box[0].y + font_height;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- for (i = 0; i < 4; i++) {
- xp[i].x = (short) box[i].x;
- xp[i].y = (short) box[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
- }
- else {
- box[0].x = origin.x +
- lines[sel_first_line].origin_x + sel_start_offset;
- box[0].y = origin.y +
- lines[sel_first_line].origin_y - fm.ascent;
- box[2].x = box[0].x +
- text->max_width-lines[sel_first_line].origin_x-sel_start_offset;
- box[2].y = box[0].y + font_height;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- for (i = 0; i < 4; i++) {
- xp[i].x = (short) box[i].x;
- xp[i].y = (short) box[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
- for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
- i < sel_last_line; i++, lines_ptr++) {
- box[0].x = origin.x;
- box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
- box[2].x = box[0].x + text->max_width;
- box[2].y = box[0].y + font_height;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- for (i = 0; i < 4; i++) {
- xp[i].x = (short) box[i].x;
- xp[i].y = (short) box[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
- }
- box[0].x = origin.x;
- box[0].y = origin.y + lines[sel_last_line].origin_y - fm.ascent;
- box[2].x = box[0].x + lines[sel_last_line].origin_x + sel_stop_offset;
- box[2].y = box[0].y + font_height;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- for (i = 0; i < 4; i++) {
- xp[i].x = (short) box[i].x;
- xp[i].y = (short) box[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
- }
- }
-
- /*printf("cursor line : %d, cursor offset : %d\n", cursor_line, cursor_offset);*/
- /*
- * Setup the gc for the cursor and draw it.
- */
- if (cursor_line >= 0 &&
- (wi->focus_item == item) && ti->cursor_on) {
- values.fill_style = FillSolid;
- values.line_width = ti->insert_width;
- values.foreground = ZnGetGradientPixel(ti->insert_color, 0.0);
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCLineWidth, &values);
-
- box[0].x = origin.x + lines[cursor_line].origin_x + cursor_offset;
- box[0].y = origin.y + lines[cursor_line].origin_y - fm.ascent + 1;
- box[1].x = box[0].x;
- box[1].y = box[0].y + font_height - 1;
- ZnTransformPoints(transfo, box, box, 2);
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) box[0].x, (int) box[0].y, (int) box[1].x, (int) box[1].y);
- }
-
-
- /*
- * If the current transform is a pure translation, it is
- * possible to optimize by directly drawing to the X back
- * buffer. Else, we draw in a temporary buffer, get
- * its content as an image, transform the image into another
- * one and use this last image as a mask to draw in the X
- * back buffer.
- */
- if (ZnTransfoIsTranslation(transfo)) {
- drw = wi->draw_buffer;
-
- gc = wi->gc;
- values.foreground = ZnGetGradientPixel(text->color, 0.0);
- }
- else {
- dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
- item->item_bounding_box.orig.x);
- dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
- item->item_bounding_box.orig.y);
-
- drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer,
- MAX(dest_im_width, text->max_width),
- MAX(dest_im_height, text->height), 1);
- gc = XCreateGC(wi->dpy, drw, 0, NULL);
- XSetForeground(wi->dpy, gc, 0);
- XFillRectangle(wi->dpy, drw, gc, 0, 0,
- MAX(dest_im_width, text->max_width),
- MAX(dest_im_height, text->height));
- dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
- XYPixmap, 0, NULL, dest_im_width, dest_im_height,
- 8, 0);
- dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
- memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);
-
- values.foreground = 1;
-
- pos.x = 0;
- pos.y = 0;
- }
-
- /*
- * Setup the gc to render the text and draw it.
- */
- values.font = Tk_FontId(text->font);
- gc_mask = GCFont | GCForeground;
- if (text->fill_pattern != ZnUnspecifiedImage) {
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(text->fill_pattern, wi->win);
- gc_mask |= GCFillStyle | GCStipple;
- }
- else {
- values.fill_style = FillSolid;
- gc_mask |= GCFillStyle;
- }
- if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
- /*
- * These 3 values should be fetched from the font.
- * Currently I don't know how without diving into
- * Tk internals.
- */
- underline_thickness = 2;
- underline_pos = fm.descent/2;
- overstrike_pos = fm.ascent*3/10;
- values.line_style = LineSolid;
- values.line_width = underline_thickness;
- gc_mask |= GCLineStyle | GCLineWidth;
- }
- XChangeGC(wi->dpy, gc, gc_mask, &values);
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- int tmp_x, tmp_y;
-
- tmp_x = (int)(pos.x + lines_ptr->origin_x);
- tmp_y = (int)(pos.y + lines_ptr->origin_y);
- Tk_DrawChars(wi->dpy, drw, gc,
- text->font, (char *) lines_ptr->start,
- (int) lines_ptr->num_bytes, tmp_x, tmp_y);
- if (ISSET(text->flags, UNDERLINED)) {
- int y_under = tmp_y + underline_pos;
-
- XDrawLine(wi->dpy, drw, gc,
- tmp_x, y_under, tmp_x + (int) lines_ptr->width, y_under);
- }
- if (ISSET(text->flags, OVERSTRIKED)) {
- int y_over = tmp_y-overstrike_pos;
-
- XDrawLine(wi->dpy, drw, gc,
- tmp_x, y_over, tmp_x + (int) lines_ptr->width, y_over);
- }
- }
-
- if (dest_im != NULL) {
- src_im = XGetImage(wi->dpy, drw, 0, 0, text->max_width, text->height,
- 1, XYPixmap);
-
- box[0].x = origin.x;
- box[0].y = origin.y;
- box[3].x = box[0].x + text->max_width;
- box[3].y = box[0].y + text->height;
- box[1].x = box[0].x;
- box[1].y = box[3].y;
- box[2].x = box[3].x;
- box[2].y = box[0].y;
- ZnTransformPoints(transfo, box, box, 4);
- for (i = 0; i < 4; i++) {
- box[i].x -= item->item_bounding_box.orig.x;
- box[i].y -= item->item_bounding_box.orig.y;
- box[i].x = ZnNearestInt(box[i].x);
- box[i].y = ZnNearestInt(box[i].y);
- }
-
- ZnMapImage(src_im, dest_im, box);
-
- TkPutImage(NULL, 0,wi->dpy, drw, gc, dest_im,
- 0, 0, 0, 0, dest_im_width, dest_im_height);
-
- values.foreground = ZnGetGradientPixel(text->color, 0.0);
- values.stipple = drw;
- values.ts_x_origin = (int) item->item_bounding_box.orig.x;
- values.ts_y_origin = (int) item->item_bounding_box.orig.y;
- values.fill_style = FillStippled;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
- &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- (int) item->item_bounding_box.orig.x,
- (int) item->item_bounding_box.orig.y,
- dest_im_width, dest_im_height);
-
- XFreeGC(wi->dpy, gc);
- Tk_FreePixmap(wi->dpy, drw);
- XDestroyImage(src_im);
- XDestroyImage(dest_im);
- }
-}
-
-
-/*
-**********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TextItem text = (TextItem) item;
- TextLineInfo lines, lines_ptr;
- ZnTextInfo *ti = &wi->text_info;
- ZnPoint o, c, origin;
- ZnTransfo *transfo;
- GLdouble m[16];
- int i, num_lines;
- XColor *color;
- unsigned short alpha;
- Tk_FontMetrics fm;
- int font_height;
- int underline_thickness, underline_pos=0, overstrike_pos=0;
- int sel_first_line=-1, sel_last_line=-1, cursor_line=-1;
- int sel_start_offset=0, sel_stop_offset=0, cursor_offset=0;
-
- if (!text->text_info) {
- return;
- }
-
-#ifdef GL_LIST
- if (!item->gl_list) {
- item->gl_list = glGenLists(1);
- glNewList(item->gl_list, GL_COMPILE);
-#endif
- lines = (TextLineInfo) ZnListArray(text->text_info);
- num_lines = ZnListSize(text->text_info);
- Tk_GetFontMetrics(text->font, &fm);
- font_height = fm.ascent+fm.descent;
-
- /*
- * These 3 values should be fetched from the font.
- * Currently I don't know how without diving into
- * Tk internals.
- */
- underline_thickness = 2;
- underline_pos = fm.descent/2;
- overstrike_pos = fm.ascent*3/10;
-
- transfo = ComputeTransfoAndOrigin(item, &origin);
-
- /*
- * Compute the selection and the cursor geometry.
- */
- ComputeCursor(item, &cursor_line, &cursor_offset);
- ComputeSelection(item, &sel_first_line, &sel_last_line,
- &sel_start_offset, &sel_stop_offset);
-
- ZnGLMakeCurrent(wi->dpy, wi);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glPushMatrix();
- memset(m, 0, sizeof(m));
- m[0] = m[5] = m[15] = 1.0;
- if (transfo) {
- m[0] = transfo->_[0][0]; m[1] = transfo->_[0][1];
- m[4] = transfo->_[1][0]; m[5] = transfo->_[1][1];
- m[12] = ZnNearestInt(transfo->_[2][0]);
- m[13] = ZnNearestInt(transfo->_[2][1]);
- }
- glLoadMatrixd(m);
- glTranslated(origin.x, origin.y, 0.0);
- glPushMatrix();
-
- /*
- * Render the selection.
- */
- if ((ti->sel_item == item) && (sel_first_line >= 0)) {
- color = ZnGetGradientColor(ti->sel_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- o.x = lines[sel_first_line].origin_x + sel_start_offset;
- o.y = lines[sel_first_line].origin_y - fm.ascent;
- glBegin(GL_QUADS);
- if (sel_first_line == sel_last_line) {
- c.x = o.x + sel_stop_offset - sel_start_offset;
- c.y = o.y + font_height;
- glVertex2d(o.x, o.y);
- glVertex2d(o.x, c.y);
- glVertex2d(c.x, c.y);
- glVertex2d(c.x, o.y);
- }
- else {
- c.x = o.x + (text->max_width -
- lines[sel_first_line].origin_x - sel_start_offset);
- c.y = o.y + font_height;
- glVertex2d(o.x, o.y);
- glVertex2d(o.x, c.y);
- glVertex2d(c.x, c.y);
- glVertex2d(c.x, o.y);
- for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
- i < sel_last_line; i++, lines_ptr++) {
- o.x = 0;
- o.y = lines_ptr->origin_y - fm.ascent;
- c.x = o.x + text->max_width;
- c.y = o.y + font_height;
- glVertex2d(o.x, o.y);
- glVertex2d(o.x, c.y);
- glVertex2d(c.x, c.y);
- glVertex2d(c.x, o.y);
- }
- o.x = 0;
- o.y = lines[sel_last_line].origin_y - fm.ascent;
- c.x = o.x + lines[sel_last_line].origin_x + sel_stop_offset;
- c.y = o.y + font_height;
- glVertex2d(o.x, o.y);
- glVertex2d(o.x, c.y);
- glVertex2d(c.x, c.y);
- glVertex2d(c.x, o.y);
- }
- glEnd();
- }
-
- /*
- * Render the cursor.
- */
- if ((cursor_line >= 0) &&
- (wi->focus_item == item) && ti->cursor_on) {
- color = ZnGetGradientColor(ti->insert_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glLineWidth((GLfloat) ti->insert_width);
-
- o.x = lines[cursor_line].origin_x + cursor_offset;
- o.y = lines[cursor_line].origin_y - fm.ascent + 1;
- c.x = o.x;
- c.y = o.y + font_height - 1;
-
- glBegin(GL_LINES);
- glVertex2d(o.x, o.y);
- glVertex2d(c.x, c.y);
- glEnd();
- }
-
- /*
- * Render the text.
- */
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(text->tfi));
- color = ZnGetGradientColor(text->color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- glTranslated(lines_ptr->origin_x, lines_ptr->origin_y, 0.0);
-
- if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
- glLineWidth((GLfloat) underline_thickness);
- glDisable(GL_TEXTURE_2D);
- if (ISSET(text->flags, UNDERLINED)) {
- glBegin(GL_LINES);
- glVertex2d(0, underline_pos);
- glVertex2d(lines_ptr->width, underline_pos);
- glEnd();
- }
- if (ISSET(text->flags, OVERSTRIKED)) {
- glBegin(GL_LINES);
- glVertex2d(0, -overstrike_pos);
- glVertex2d(lines_ptr->width, -overstrike_pos);
- glEnd();
- }
- glEnable(GL_TEXTURE_2D);
- }
-
- ZnRenderString(text->tfi, lines_ptr->start, lines_ptr->num_bytes);
- glPopMatrix();
- glPushMatrix();
- }
-
- glPopMatrix();
- glPopMatrix();
-
- glDisable(GL_TEXTURE_2D);
-#ifdef GL_LIST
- glEndList();
- }
-
- glCallList(item->gl_list);
-#endif
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- TextItem text = (TextItem) item;
- double dist = 1.0e40, new_dist;
- int num_lines, i;
- TextLineInfo lines, lines_ptr;
- Tk_FontMetrics fm;
- int font_height;
- ZnPoint box[4], origin, *p = ps->point;
- ZnTransfo *transfo;
-
- if (!text->text_info || !text->text) {
- return dist;
- }
-
- transfo = ComputeTransfoAndOrigin(item, &origin);
-
- lines = ZnListArray(text->text_info);
- num_lines = ZnListSize(text->text_info);
- Tk_GetFontMetrics(text->font, &fm);
- font_height = fm.descent + fm.ascent;
- if (text->spacing > 0) {
- font_height += text->spacing;
- }
-
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- box[0].x = origin.x + lines_ptr->origin_x;
- box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
- box[2].x = box[0].x + lines_ptr->width;
- box[2].y = box[0].y + font_height;
- box[1].x = box[2].x;
- box[1].y = box[0].y;
- box[3].x = box[0].x;
- box[3].y = box[2].y;
- ZnTransformPoints(transfo, box, box, 4);
- new_dist = ZnPolygonToPointDist(box, 4, p);
- dist = MIN(dist, new_dist);
- if (dist <= 0.0) {
- dist = 0.0;
- break;
- }
- }
-
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- TextItem text = (TextItem) item;
- Tk_FontMetrics fm;
- TextLineInfo lines, lines_ptr;
- ZnPoint origin;
- ZnReal alignment;
- int i, num_lines;
- char path[150];
-
- lines = (TextLineInfo) ZnListArray(text->text_info);
- num_lines = ZnListSize(text->text_info);
-
- if (Tk_PostscriptFont(wi->interp, wi->ps_info, text->font) != TCL_OK) {
- return TCL_ERROR;
- }
- if (Tk_PostscriptColor(wi->interp, wi->ps_info,
- ZnGetGradientColor(text->color, 0.0, NULL)) != TCL_OK) {
- return TCL_ERROR;
- }
- if (text->fill_pattern != ZnUnspecifiedImage) {
- Tcl_AppendResult(wi->interp, "/StippleText {\n ", NULL);
- Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
- ZnImagePixmap(text->fill_pattern, wi->win));
- Tcl_AppendResult(wi->interp, "} bind def\n", NULL);
- }
-
- ComputeTransfoAndOrigin(item, &origin);
-
- sprintf(path, "/InitialTransform load setmatrix\n"
- "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
- "1 -1 scale\n",
- wi->current_transfo->_[0][0], wi->current_transfo->_[0][1],
- wi->current_transfo->_[1][0], wi->current_transfo->_[1][1],
- wi->current_transfo->_[2][0], wi->current_transfo->_[2][1]);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- sprintf(path, "%.15g %.15g [\n", origin.x, origin.y);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- /*
- * Emit code to draw the lines.
- */
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- ZnPostscriptString(wi->interp, lines_ptr->start, lines_ptr->num_bytes);
- }
-
- switch (text->alignment) {
- default:
- case TK_JUSTIFY_LEFT:
- alignment = 0;
- break;
- case TK_JUSTIFY_CENTER:
- alignment = 0.5;
- break;
- case TK_JUSTIFY_RIGHT:
- alignment = 1;
- break;
- }
- Tk_GetFontMetrics(text->font, &fm);
- /* DrawText should not mess with anchors, they are already accounted for */
- sprintf(path, "] %d %g %g %g %s DrawText\n", fm.linespace, 0.0, 0.0,
- alignment, (text->fill_pattern == ZnUnspecifiedImage) ? "false" : "true");
- Tcl_AppendResult(wi->interp, path, NULL);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- TextItem text = (TextItem) item;
-
- if (text->num_chars != 0) {
- ZnRectOrigin2Anchor(text->poly, anchor, p);
- }
- else {
- *p = *text->poly;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- TextItem text = (TextItem) item;
-
- ZnTriStrip1(tristrip, text->poly, 4, False);
-
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item origin. This doesn't take care of
- * the possible attachment. The change will be effective at the
- * end of the attachment.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- TextItem text = (TextItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " texts can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on texts", NULL);
- return TCL_ERROR;
- }
- text->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &text->pos;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Index --
- * Parse a text index and return its value and a
- * error status (standard Tcl result).
- *
- **********************************************************************************
- */
-static int
-PointToChar(TextItem text,
- int x,
- int y)
-{
- int i, n, num_lines, dummy, byte_index;
- ZnPoint p;
- TextLineInfo ti;
- Tk_FontMetrics fm;
- ZnReal a, b;
-
- byte_index = 0;
- if (!text->text_info) {
- return 0;
- }
-
- p.x = x;
- p.y = y;
- a = ZnLineToPointDist(&text->poly[0], &text->poly[2], &p, NULL);
- b = ZnLineToPointDist(&text->poly[0], &text->poly[1], &p, NULL);
- p.x = (text->max_width * b /
- hypot(text->poly[2].x - text->poly[0].x, text->poly[2].y - text->poly[0].y));
- p.y = (text->height * a /
- hypot(text->poly[1].x - text->poly[0].x, text->poly[1].y - text->poly[0].y));
- p.x = ZnNearestInt(p.x);
- p.y = ZnNearestInt(p.y);
-
- /*
- * Point above text, returns index 0.
- */
- if (p.y < 0) {
- return 0;
- }
-
- /*
- * Find the text line under point.
- */
- num_lines = ZnListSize(text->text_info);
- ti = ZnListArray(text->text_info);
- Tk_GetFontMetrics(text->font, &fm);
- for (i = 0; i < num_lines; i++, ti++) {
- if (p.y < ti->origin_y + fm.descent) {
- if (p.x < ti->origin_x) {
- /*
- * Point to the left of the current line, returns
- * index of first char.
- */
- byte_index = ti->start - text->text;
- break;
- }
- if (p.x >= (ti->origin_x + ti->width)) {
- /*
- * Point to the right of the current line, returns
- * index past the last char.
- */
- byte_index = ti->start + ti->num_bytes - text->text;
- break;
- }
- n = Tk_MeasureChars(text->font, ti->start, (int) ti->num_bytes,
- (int) (p.x + 2 - ti->origin_x), TK_PARTIAL_OK,
- &dummy);
-#ifdef PTK_800
- byte_index = (ti->start + n - 1) - text->text;
-#else
- byte_index = Tcl_UtfPrev(ti->start + n, ti->start) - text->text;
-#endif
- break;
- }
- }
- if (i == num_lines) {
- /*
- * Point below all lines, return the index after
- * the last char in text.
- */
- ti--;
- byte_index = ti->start + ti->num_bytes - text->text;
- }
-
- return Tcl_NumUtfChars(text->text, byte_index);
-}
-
-/*
- * Return a new index from a current index and a
- * move command.
- *
- * 0 end of index line
- * 1 beginning of index line
- * 2 next word or end of word from index
- * 3 previous word or beginning of word from index
- * 4 previous line from index line
- * 5 next line from index line
- *
- */
-static int
-MoveFromIndex(TextItem text,
- unsigned int char_index,
- int move)
-{
- unsigned int num_lines, byte_index, num_bytes=0;
- unsigned int line_index, line_start=0;
- TextLineInfo lines, p;
- char *strp;
-
- if (!text->text_info || !text->text) {
- return char_index;
- }
- byte_index = Tcl_UtfAtIndex(text->text, (int) char_index)-text->text;
- num_lines = ZnListSize(text->text_info);
- lines = p = ZnListArray(text->text_info);
- for (line_index = 0; line_index < num_lines; line_index++, p++) {
- line_start = p->start - text->text;
- num_bytes = p->num_bytes;
- if (line_start + num_bytes >= byte_index) {
- break;
- }
- }
- if (line_index == num_lines) {
- line_index--;
- p--;
- }
-
- switch (move) {
- case 0:
- byte_index = line_start + num_bytes;
- goto convert_it;
- case 1:
- byte_index = line_start;
- goto convert_it;
- case 2:
- strp = &text->text[byte_index];
- while ((strp[1] == ' ') || (strp[1] == '\n')) {
- strp++;
- }
- while ((strp[1] != ' ') && (strp[1] != '\n') && strp[1]) {
- strp++;
- }
- byte_index = strp + 1 - text->text;
- goto convert_it;
- case 3:
- strp = &text->text[byte_index];
- while ((strp != text->text) && ((strp[-1] == ' ') || (strp[-1] == '\n'))) {
- strp--;
- }
- while ((strp != text->text) && (strp[-1] != ' ') && (strp[-1] != '\n')) {
- strp--;
- }
- byte_index = strp - text->text;
- goto convert_it;
- case 4:
- if (line_index > 0) {
- byte_index -= line_start;
- p = &lines[line_index-1];
- byte_index = MIN(byte_index, p->num_bytes);
- line_start = p->start - text->text;
- byte_index += line_start;
- }
- goto convert_it;
- case 5:
- if (line_index < num_lines-1) {
- byte_index -= line_start;
- p = &lines[line_index+1];
- byte_index = MIN(byte_index, p->num_bytes);
- line_start = p->start - text->text;
- byte_index += line_start;
- }
- convert_it:
- char_index = Tcl_NumUtfChars(text->text, (int) byte_index);
- default:
- return char_index;
- }
-}
-
-static int
-Index(ZnItem item,
- int field,
- Tcl_Obj *index_spec,
- int *index)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- unsigned int length;
- int c, x, y;
- double tmp;
- char *end, *p;
-
- p = Tcl_GetString(index_spec);
- c = p[0];
- length = strlen(p);
-
- if ((c == 'e') && (length > 1) && (strncmp(p, "end", length) == 0)) {
- *index = text->num_chars;
- }
- else if ((c == 'e') && (length > 1) && (strncmp(p, "eol", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 0);
- }
- else if ((c == 'b') && (length > 1) && (strncmp(p, "bol", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 1);
- }
- else if ((c == 'e') && (length > 1) && (strncmp(p, "eow", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 2);
- }
- else if ((c == 'b') && (length > 1) && (strncmp(p, "bow", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 3);
- }
- else if ((c == 'u') && (strncmp(p, "up", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 4);
- }
- else if ((c == 'd') && (strncmp(p, "down", length) == 0)) {
- *index = MoveFromIndex(text, text->insert_index, 5);
- }
- else if ((c == 'i') && (strncmp(p, "insert", length) == 0)) {
- *index = text->insert_index;
- }
- else if ((c == 's') && (strncmp(p, "sel.first", length) == 0) &&
- (length >= 5)) {
- if (ti->sel_item != item) {
- Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
- return TCL_ERROR;
- }
- *index = ti->sel_first;
- }
- else if ((c == 's') && (strncmp(p, "sel.last", length) == 0) &&
- (length >= 5)) {
- if (ti->sel_item != item) {
- Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
- return TCL_ERROR;
- }
- /*
- * We return a modified selection end so that it reflect
- * the text index of the last character _not_ the insertion
- * point between the last and the next.
- */
- *index = ti->sel_last-1;
- }
- else if (c == '@') {
- p++;
- tmp = strtod(p, &end);
- if ((end == p) || (*end != ',')) {
- goto badIndex;
- }
- /*x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
- x = (int) tmp;
- p = end+1;
- tmp = strtod(p, &end);
- if ((end == p) || (*end != 0)) {
- goto badIndex;
- }
- /*y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
- y = (int) tmp;
-
- *index = PointToChar(text, x, y);
- }
- else if (Tcl_GetIntFromObj(wi->interp, index_spec, index) == TCL_OK) {
- if (*index < 0){
- *index = 0;
- }
- else if ((unsigned int) *index > text->num_chars) {
- *index = text->num_chars;
- }
- }
- else {
- badIndex:
- Tcl_AppendResult(wi->interp, "bad index \"", p, "\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * InsertChars --
- *
- **********************************************************************************
- */
-static void
-InsertChars(ZnItem item,
- int field,
- int *index,
- char *chars)
-{
- TextItem text = (TextItem) item;
- ZnTextInfo *ti = &item->wi->text_info;
- unsigned int num_chars, byte_index, num_bytes = strlen(chars);
- char *new;
-
- if (num_bytes == 0) {
- return;
- }
- if (*index < 0) {
- *index = 0;
- }
- if ((unsigned int) *index > text->num_chars) {
- *index = text->num_chars;
- }
- num_chars = Tcl_NumUtfChars(chars, (int) num_bytes);
-
- if (text->text) {
- byte_index = Tcl_UtfAtIndex(text->text, *index)-text->text;
- new = ZnMalloc(strlen(text->text) + num_bytes + 1);
- memcpy(new, text->text, (size_t) byte_index);
- strcpy(new + byte_index + num_bytes, text->text + byte_index);
- ZnFree(text->text);
- }
- else {
- byte_index = 0;
- new = ZnMalloc(num_bytes + 1);
- new[num_bytes] = 0;
- }
- memcpy(new + byte_index, chars, num_bytes);
- text->text = new;
- text->num_chars += num_chars;
-
- if (text->insert_index >= (unsigned int) *index) {
- text->insert_index += num_chars;
- }
- if (ti->sel_item == item) {
- if (ti->sel_first >= *index) {
- ti->sel_first += num_chars;
- }
- if (ti->sel_last >= *index) {
- ti->sel_last += num_chars;
- }
- if ((ti->anchor_item == item) && (ti->sel_anchor >= *index)) {
- ti->sel_anchor += num_chars;
- }
- }
-
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
-}
-
-
-/*
- **********************************************************************************
- *
- * DeleteChars --
- *
- **********************************************************************************
- */
-static void
-DeleteChars(ZnItem item,
- int field,
- int *first,
- int *last)
-{
- TextItem text = (TextItem) item;
- int byte_count, first_offset;
- int char_count, num_bytes;
- ZnTextInfo *ti = &item->wi->text_info;
- char *new;
-
- if (!text->text) {
- return;
- }
- if (*first < 0) {
- *first = 0;
- }
- if (*last >= (int) text->num_chars) {
- *last = text->num_chars-1;
- }
- if (*first > *last) {
- return;
- }
- char_count = *last + 1 - *first;
- first_offset = Tcl_UtfAtIndex(text->text, *first)-text->text;
- byte_count = Tcl_UtfAtIndex(text->text + first_offset, char_count)-
- (text->text+first_offset);
- num_bytes = strlen(text->text);
-
- if (num_bytes - byte_count) {
- new = (char *) ZnMalloc((unsigned) (num_bytes + 1 - byte_count));
- memcpy(new, text->text, (size_t) first_offset);
- strcpy(new + first_offset, text->text + first_offset + byte_count);
- ZnFree(text->text);
- text->text = new;
- text->num_chars -= char_count;
- }
- else {
- ZnFree(text->text);
- text->text = NULL;
- text->num_chars = 0;
- }
-
- if (text->insert_index > (unsigned int) *first) {
- text->insert_index -= char_count;
- if (text->insert_index < (unsigned int) *first) {
- text->insert_index = *first;
- }
- else if (*first == 0) {
- text->insert_index = 0;
- }
- }
- if (ti->sel_item == item) {
- if (ti->sel_first > *first) {
- ti->sel_first -= char_count;
- if (ti->sel_first < *first) {
- ti->sel_first = *first;
- }
- }
- if (ti->sel_last >= *first) {
- ti->sel_last -= char_count;
- if (ti->sel_last < *first - 1) {
- ti->sel_last = *first - 1;
- }
- }
- if (ti->sel_first > ti->sel_last) {
- ti->sel_item = ZN_NO_ITEM;
- }
- if ((ti->anchor_item == item) && (ti->sel_anchor > *first)) {
- ti->sel_anchor -= char_count;
- if (ti->sel_anchor < *first) {
- ti->sel_anchor = *first;
- }
- }
- }
-
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
-}
-
-
-/*
- **********************************************************************************
- *
- * Cursor --
- *
- **********************************************************************************
- */
-static void
-TextCursor(ZnItem item,
- int field,
- int index)
-{
- TextItem text = (TextItem) item;
-
- if (index < 0) {
- text->insert_index = 0;
- }
- else if ((unsigned int) index > text->num_chars) {
- text->insert_index = text->num_chars;
- }
- else {
- text->insert_index = index;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Selection --
- *
- **********************************************************************************
- */
-static int
-Selection(ZnItem item,
- int field,
- int offset,
- char *chars,
- int max_bytes)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- int count;
- char const *sel_first, *sel_last;
-
- if (!text->text) {
- return 0;
- }
- if ((ti->sel_first < 0) ||
- (ti->sel_first > ti->sel_last)) {
- return 0;
- }
- sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first);
- sel_last = Tcl_UtfAtIndex(sel_first, ti->sel_last + 1 - ti->sel_first);
- count = sel_last - sel_first - offset;
- if (count <= 0) {
- return 0;
- }
- if (count > max_bytes) {
- count = max_bytes;
- }
- memcpy(chars, sel_first + offset, (size_t) count);
- chars[count] = 0;
-
- return count;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct
- *
- **********************************************************************************
- */
-static ZnItemClassStruct TEXT_ITEM_CLASS = {
- "text",
- sizeof(TextItemStruct),
- text_attrs,
- 0, /* num_parts */
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- Tk_Offset(TextItemStruct, pos),
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- NULL, /* GetContours */
- Coords,
- InsertChars,
- DeleteChars,
- TextCursor,
- Index,
- NULL, /* Part */
- Selection,
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnText = (ZnItemClassId) &TEXT_ITEM_CLASS;
diff --git a/generic/Track.c b/generic/Track.c
deleted file mode 100644
index 63686c4..0000000
--- a/generic/Track.c
+++ /dev/null
@@ -1,2372 +0,0 @@
-/*
- * Track.c -- Implementation of Track and WayPoint items.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Types.h"
-#include "Track.h"
-#include "Draw.h"
-#include "Geo.h"
-#include "Item.h"
-#include "Group.h"
-#include "WidgetInfo.h"
-#include "Image.h"
-#include "tkZinc.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-/*
- * Define this to enable overlap manager setting
- * the label distance rho.
- */
-#undef DP
-
-/*
- * Some default values
-*/
-#define DEFAULT_MARKER_SIZE 0
-#define DEFAULT_LABEL_ANGLE 20
-#define DEFAULT_LABEL_DISTANCE 50
-#define DEFAULT_LINE_WIDTH 1
-#define DEFAULT_LABEL_PREFERRED_ANGLE 0
-#define DEFAULT_CONVERGENCE_STYLE 0
-
-#define SPEED_VECTOR_PICKING_THRESHOLD 5 /* In pixels */
-
-/*
- * Sets a threshold for calculating distance from label_dx, label_dy.
- * Above this threshold value, the module is discarded, label_distance
- * is preferred.
- */
-#define LABEL_DISTANCE_THRESHOLD 5
-
-#define MARKER_FILLED_BIT 1 << 0
-#define FILLED_HISTORY_BIT 1 << 1
-#define DOT_MIXED_HISTORY_BIT 1 << 2
-#define CIRCLE_HISTORY_BIT 1 << 3
-#define SV_MARK_BIT 1 << 4
-#define SV_TICKS_BIT 1 << 5
-#define POLAR_BIT 1 << 6
-#define FROZEN_LABEL_BIT 1 << 7
-#define LAST_AS_FIRST_BIT 1 << 8
-#define HISTORY_VISIBLE_BIT 1 << 9
-
-#define CURRENT_POSITION -2
-#define LEADER -3
-#define CONNECTION -4
-#define SPEED_VECTOR -5
-
-
-/*
-**********************************************************************************
-*
-* Specific Track item record
-*
-**********************************************************************************
-*/
-typedef struct {
- ZnPoint world; /* world coord of pos */
- ZnPoint dev; /* dev coord of pos */
- ZnBool visible;
-} HistoryStruct, *History;
-
-typedef struct _TrackItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- unsigned short flags;
- ZnImage symbol; /* item symbol */
- ZnGradient *symbol_color;
- int label_angle; /* Label angle from track. */
- ZnDim label_distance; /* Label distance from track. */
- ZnDim label_dx; /* Label dx/dy from track. */
- ZnDim label_dy;
- int label_preferred_angle;
- int label_convergence_style;
- Tk_Anchor label_anchor;
- ZnLeaderAnchors leader_anchors; /* Spec of the leader attachment */
- ZnGradient *leader_color; /* leader color */
- ZnLineStyle leader_style;
- ZnLineShape leader_shape;
- ZnLineEnd leader_first_end;
- ZnLineEnd leader_last_end;
- ZnDim leader_width;
- ZnDim marker_size; /* world size of error circle */
- ZnGradient *marker_color; /* error circle color */
- ZnLineStyle marker_style; /* error circle style */
- ZnImage marker_fill_pattern; /* error circle fill pattern */
- ZnGradient *connection_color; /* connection color */
- ZnLineStyle connection_style;
- ZnDim connection_width;
- ZnGradient *speed_vector_color; /* s. v. color */
- ZnPoint pos; /* item world coordinates */
- ZnPoint speed_vector; /* s. v. slope in world coord */
- ZnDim speed_vector_width;
- ZnGradient *history_color;
- ZnDim history_width;
-
- /* Private data */
- ZnFieldSetStruct field_set;
- ZnPoint dev; /* device coords of current pos */
- ZnPoint speed_vector_dev; /* s. v. end in device coord */
- ZnDim marker_size_dev; /* dev size of error circle */
- ZnList history; /* pos list */
- ZnList leader_points;
-} TrackItemStruct, *TrackItem;
-
-
-static ZnAttrConfig track_attrs[] = {
- { ZN_CONFIG_BOOL, "-circlehistory", NULL,
- Tk_Offset(TrackItemStruct, flags), CIRCLE_HISTORY_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(TrackItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-connectioncolor", NULL,
- Tk_Offset(TrackItemStruct, connection_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-connectionsensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CONNECTION),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-connectionstyle", NULL,
- Tk_Offset(TrackItemStruct, connection_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-connectionwidth", NULL,
- Tk_Offset(TrackItemStruct, connection_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-filledhistory", NULL,
- Tk_Offset(TrackItemStruct, flags), FILLED_HISTORY_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-filledmarker", NULL,
- Tk_Offset(TrackItemStruct, flags), MARKER_FILLED_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-frozenlabel", NULL,
- Tk_Offset(TrackItemStruct, flags), FROZEN_LABEL_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-historycolor", NULL,
- Tk_Offset(TrackItemStruct, history_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-historywidth", NULL,
- Tk_Offset(TrackItemStruct, history_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-labelanchor", NULL,
- Tk_Offset(TrackItemStruct, label_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ANGLE, "-labelangle", NULL,
- Tk_Offset(TrackItemStruct, label_angle), 0,
- ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
- { ZN_CONFIG_UINT, "-labelconvergencestyle", NULL,
- Tk_Offset(TrackItemStruct, label_convergence_style), 0, 0, False },
- { ZN_CONFIG_DIM, "-labeldistance", NULL,
- Tk_Offset(TrackItemStruct, label_distance), 0,
- ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
- { ZN_CONFIG_DIM, "-labeldx", NULL,
- Tk_Offset(TrackItemStruct, label_dx), 0,
- ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
- { ZN_CONFIG_DIM, "-labeldy", NULL,
- Tk_Offset(TrackItemStruct, label_dy), 0,
- ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
- { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
- Tk_Offset(TrackItemStruct, field_set.label_format), 0,
- ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_ANGLE, "-labelpreferredangle", NULL,
- Tk_Offset(TrackItemStruct, label_preferred_angle), 0, 0, False },
- { ZN_CONFIG_BOOL, "-lastasfirst", NULL,
- Tk_Offset(TrackItemStruct, flags), LAST_AS_FIRST_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LEADER_ANCHORS, "-leaderanchors", NULL,
- Tk_Offset(TrackItemStruct, leader_anchors), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-leadercolor", NULL,
- Tk_Offset(TrackItemStruct, leader_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_END, "-leaderfirstend", NULL,
- Tk_Offset(TrackItemStruct, leader_first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-leaderlastend", NULL,
- Tk_Offset(TrackItemStruct, leader_last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-leadersensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(LEADER),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-leaderstyle", NULL,
- Tk_Offset(TrackItemStruct, leader_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_SHAPE, "-leadershape", NULL,
- Tk_Offset(TrackItemStruct, leader_shape), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_DIM, "-leaderwidth", NULL,
- Tk_Offset(TrackItemStruct, leader_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
- Tk_Offset(TrackItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BITMAP, "-markerfillpattern", NULL,
- Tk_Offset(TrackItemStruct, marker_fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-markersize", NULL,
- Tk_Offset(TrackItemStruct, marker_size), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-markerstyle", NULL,
- Tk_Offset(TrackItemStruct, marker_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-mixedhistory", NULL,
- Tk_Offset(TrackItemStruct, flags), DOT_MIXED_HISTORY_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_UINT, "-numfields", NULL,
- Tk_Offset(TrackItemStruct, field_set.num_fields), 0, 0, True },
- { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TrackItemStruct, pos), 0,
- ZN_COORDS_FLAG|ZN_MOVED_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(TrackItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
- { ZN_CONFIG_POINT, "-speedvector", NULL, Tk_Offset(TrackItemStruct, speed_vector), 0,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-speedvectorcolor", NULL,
- Tk_Offset(TrackItemStruct, speed_vector_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-speedvectormark", NULL,
- Tk_Offset(TrackItemStruct, flags), SV_MARK_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-speedvectorsensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(SPEED_VECTOR),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-speedvectorticks", NULL,
- Tk_Offset(TrackItemStruct, flags), SV_TICKS_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-speedvectorwidth", NULL,
- Tk_Offset(TrackItemStruct, speed_vector_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BITMAP, "-symbol", NULL,
- Tk_Offset(TrackItemStruct, symbol), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-symbolcolor", NULL,
- Tk_Offset(TrackItemStruct, symbol_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-symbolsensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CURRENT_POSITION),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(TrackItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
- { ZN_CONFIG_BOOL, "-historyvisible", NULL,
- Tk_Offset(TrackItemStruct, flags), HISTORY_VISIBLE_BIT, ZN_COORDS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-static ZnAttrConfig wp_attrs[] = {
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(TrackItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-connectioncolor", NULL,
- Tk_Offset(TrackItemStruct, connection_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-connectionsensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CONNECTION),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-connectionstyle", NULL,
- Tk_Offset(TrackItemStruct, connection_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-connectionwidth", NULL,
- Tk_Offset(TrackItemStruct, connection_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-filledmarker", NULL,
- Tk_Offset(TrackItemStruct, flags), MARKER_FILLED_BIT, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-labelanchor", NULL,
- Tk_Offset(TrackItemStruct, label_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ANGLE, "-labelangle", NULL,
- Tk_Offset(TrackItemStruct, label_angle), 0,
- ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
- { ZN_CONFIG_DIM, "-labeldistance", NULL,
- Tk_Offset(TrackItemStruct, label_distance), 0,
- ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
- { ZN_CONFIG_DIM, "-labeldx", NULL,
- Tk_Offset(TrackItemStruct, label_dx), 0,
- ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
- { ZN_CONFIG_DIM, "-labeldy", NULL,
- Tk_Offset(TrackItemStruct, label_dy), 0,
- ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
- { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
- Tk_Offset(TrackItemStruct, field_set.label_format), 0,
- ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
- { ZN_CONFIG_LEADER_ANCHORS, "-leaderanchors", NULL,
- Tk_Offset(TrackItemStruct, leader_anchors), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-leadercolor", NULL,
- Tk_Offset(TrackItemStruct, leader_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_LINE_END, "-leaderfirstend", NULL,
- Tk_Offset(TrackItemStruct, leader_first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_END, "-leaderlastend", NULL,
- Tk_Offset(TrackItemStruct, leader_last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-leadersensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(LEADER),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_LINE_SHAPE, "-leadershape", NULL,
- Tk_Offset(TrackItemStruct, leader_shape), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-leaderstyle", NULL,
- Tk_Offset(TrackItemStruct, leader_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-leaderwidth", NULL,
- Tk_Offset(TrackItemStruct, leader_width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
- Tk_Offset(TrackItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BITMAP, "-markerfillpattern", NULL,
- Tk_Offset(TrackItemStruct, marker_fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_DIM, "-markersize", NULL,
- Tk_Offset(TrackItemStruct, marker_size), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_LINE_STYLE, "-markerstyle", NULL,
- Tk_Offset(TrackItemStruct, marker_style), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_UINT, "-numfields", NULL,
- Tk_Offset(TrackItemStruct, field_set.num_fields), 0, 0, True },
- { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TrackItemStruct, pos), 0,
- ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(TrackItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BITMAP, "-symbol", NULL,
- Tk_Offset(TrackItemStruct, symbol), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT, "-symbolcolor", NULL,
- Tk_Offset(TrackItemStruct, symbol_color), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-symbolsensitive", NULL,
- Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CURRENT_POSITION),
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(TrackItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(TrackItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-
-/*
-**********************************************************************************
-*
-* Init --
-*
-**********************************************************************************
-*/
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- TrackItem track = (TrackItem) item;
- ZnFieldSet field_set = &track->field_set;
- ZnWInfo *wi = item->wi;
- int num_fields;
-
- /*printf("size of a track = %d\n", sizeof(TrackItemStruct));*/
-
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- SET(item->part_sensitive, ZnPartToBit(CURRENT_POSITION));
- SET(item->part_sensitive, ZnPartToBit(LEADER));
- SET(item->part_sensitive, ZnPartToBit(CONNECTION));
- SET(item->part_sensitive, ZnPartToBit(SPEED_VECTOR));
- track->symbol_color = ZnGetGradientByValue(wi->fore_color);
- track->symbol = ZnGetImageByValue(wi->track_symbol, NULL, NULL);
- track->label_anchor = TK_ANCHOR_CENTER;
- track->label_angle = DEFAULT_LABEL_ANGLE;
- track->label_distance = DEFAULT_LABEL_DISTANCE;
- SET(track->flags, POLAR_BIT);
- CLEAR(track->flags, FROZEN_LABEL_BIT);
-
- track->label_preferred_angle = DEFAULT_LABEL_PREFERRED_ANGLE;
- track->label_convergence_style = DEFAULT_CONVERGENCE_STYLE ;
-
- track->leader_anchors = NULL;
- track->leader_color = ZnGetGradientByValue(wi->fore_color);
- track->leader_style = ZN_LINE_SIMPLE;
- track->leader_shape = ZN_LINE_STRAIGHT;
- track->leader_width = DEFAULT_LINE_WIDTH;
- track->connection_color = ZnGetGradientByValue(wi->fore_color);
- track->connection_style = ZN_LINE_SIMPLE;
- track->connection_width = DEFAULT_LINE_WIDTH;
- track->marker_color = ZnGetGradientByValue(wi->fore_color);
- track->marker_style = ZN_LINE_SIMPLE;
- track->marker_fill_pattern = ZnUnspecifiedImage;
- track->speed_vector_color = ZnGetGradientByValue(wi->fore_color);
- track->history_color = ZnGetGradientByValue(wi->fore_color);
- track->history_width = 8;
- CLEAR(track->flags, MARKER_FILLED_BIT);
- SET(track->flags, FILLED_HISTORY_BIT);
- CLEAR(track->flags, DOT_MIXED_HISTORY_BIT);
- CLEAR(track->flags, CIRCLE_HISTORY_BIT);
- CLEAR(track->flags, LAST_AS_FIRST_BIT);
- CLEAR(track->flags, SV_MARK_BIT);
- CLEAR(track->flags, SV_TICKS_BIT);
-
- if (item->class == ZnTrack) {
- item->priority = 1;
- SET(track->flags, HISTORY_VISIBLE_BIT);
- track->marker_size = DEFAULT_MARKER_SIZE;
- track->speed_vector.x = 0;
- track->speed_vector.y = 0;
- track->speed_vector_width = DEFAULT_LINE_WIDTH;
- }
- else {
- item->priority = 1;
- CLEAR(track->flags, HISTORY_VISIBLE_BIT);
- track->marker_size = 0;
- track->speed_vector.x = 0.0;
- track->speed_vector.y = 10.0;
- }
- field_set->item = item;
- field_set->label_format = NULL;
- /*
- * Then try to see if some fields are needed.
- */
- if ((*argc > 0) && (Tcl_GetString((*args)[0])[0] != '-') &&
- (Tcl_GetIntFromObj(wi->interp, (*args)[0], &num_fields) != TCL_ERROR)) {
- field_set->num_fields = num_fields;
- *args += 1;
- *argc -= 1;
- ZnFIELD.InitFields(field_set);
- }
- else {
- Tcl_AppendResult(wi->interp, " number of fields expected", NULL);
- return TCL_ERROR;
- }
-
- track->pos.x = 0;
- track->pos.y = 0;
- track->field_set.label_pos.x = 0;
- track->field_set.label_pos.y = 0;
- track->leader_first_end = NULL;
- track->leader_last_end = NULL;
-
- track->history = NULL;
- track->dev.x = 0;
- track->dev.y = 0;
- track->speed_vector_dev.x = 0;
- track->speed_vector_dev.y = 0;
- track->marker_size_dev = 0;
- track->leader_points = NULL;
-
- return TCL_OK;
-}
-
-
-/*
-**********************************************************************************
-*
-* Clone --
-*
-**********************************************************************************
-*/
-static void
-Clone(ZnItem item)
-{
- TrackItem track = (TrackItem) item;
-
- if (track->history) {
- track->history = ZnListDuplicate(track->history);
- }
- track->dev.x = 0;
- track->dev.y = 0;
- track->speed_vector_dev.x = 0;
- track->speed_vector_dev.y = 0;
- track->marker_size_dev = 0;
- if (track->leader_points) {
- track->leader_points = ZnListDuplicate(track->leader_points);
- }
- if (track->leader_first_end) {
- ZnLineEndDuplicate(track->leader_first_end);
- }
- if (track->leader_last_end) {
- ZnLineEndDuplicate(track->leader_last_end);
- }
-
- ZnFIELD.CloneFields(&track->field_set);
- track->field_set.item = item;
-
- /*
- * We get all shared resources, colors bitmaps.
- */
- track->symbol_color = ZnGetGradientByValue(track->symbol_color);
- track->leader_color = ZnGetGradientByValue(track->leader_color);
- track->connection_color = ZnGetGradientByValue(track->connection_color);
- track->marker_color = ZnGetGradientByValue(track->marker_color);
- track->speed_vector_color = ZnGetGradientByValue(track->speed_vector_color);
- track->history_color = ZnGetGradientByValue(track->history_color);
- if (track->symbol != ZnUnspecifiedImage) {
- track->symbol = ZnGetImageByValue(track->symbol, NULL, NULL);
- }
- if (track->marker_fill_pattern != ZnUnspecifiedImage) {
- track->marker_fill_pattern = ZnGetImageByValue(track->marker_fill_pattern, NULL, NULL);
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* Destroy --
-*
-**********************************************************************************
-*/
-static void
-Destroy(ZnItem item)
-{
- TrackItem track = (TrackItem) item;
-
- if (track->leader_points) {
- ZnListFree(track->leader_points);
- }
- if (track->leader_first_end) {
- ZnLineEndDelete(track->leader_first_end);
- }
- if (track->leader_last_end) {
- ZnLineEndDelete(track->leader_last_end);
- }
-
- if (track->history) {
- ZnListFree(track->history);
- }
-
- /*
- * Release shared resources.
- */
- ZnFreeGradient(track->symbol_color);
- ZnFreeGradient(track->leader_color);
- ZnFreeGradient(track->connection_color);
- ZnFreeGradient(track->marker_color);
- ZnFreeGradient(track->speed_vector_color);
- ZnFreeGradient(track->history_color);
- if (track->symbol != ZnUnspecifiedImage) {
- ZnFreeImage(track->symbol, NULL, NULL);
- track->symbol = ZnUnspecifiedImage;
- }
- if (track->marker_fill_pattern != ZnUnspecifiedImage) {
- ZnFreeImage(track->marker_fill_pattern, NULL, NULL);
- track->marker_fill_pattern = ZnUnspecifiedImage;
- }
-
- ZnFIELD.FreeFields(&track->field_set);
-}
-
-
-/*
-**********************************************************************************
-*
-* Configure --
-*
-**********************************************************************************
-*/
-static void
-AddToHistory(TrackItem track,
- ZnPoint old_pos)
-{
- ZnWInfo *wi = ((ZnItem) track)->wi;
-
- if (track->history) {
- HistoryStruct hist;
-
- hist.world = old_pos;
- hist.dev = track->dev;
- hist.visible = True;
- ZnListAdd(track->history, &hist, ZnListHead);
- ZnListTruncate(track->history, wi->track_managed_history_size);
- }
- else {
- /* We do not shift the first time we move as the preceding position
- * is not valid. */
- /*printf("creating history\n");*/
- track->history = ZnListNew(wi->track_managed_history_size+1,
- sizeof(HistoryStruct));
- }
-}
-
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- TrackItem track = (TrackItem) item;
- ZnWInfo *wi = item->wi;
- ZnItem old_connected;
- ZnPoint old_pos;
-
- old_pos = track->pos;
- old_connected = item->connected_item;
-
- if (ZnConfigureAttributes(wi, item, item, track_attrs, argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- if (track->label_angle < 0) {
- track->label_angle = 360 + track->label_angle;
- }
-
- /*
- * Adapt to the new label locating system.
- */
- if (ISSET(*flags, ZN_POLAR_FLAG)) {
- SET(track->flags, POLAR_BIT);
- ZnGroupSetCallOm(item->parent, True);
- }
- else if (ISSET(*flags, ZN_CARTESIAN_FLAG)) {
- CLEAR(track->flags, POLAR_BIT);
- ZnGroupSetCallOm(item->parent, True);
- }
-
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- /*
- * If the new connected item is not appropriate back up
- * to the old one.
- */
- if ((item->connected_item == ZN_NO_ITEM) ||
- (((item->connected_item->class == ZnTrack) ||
- (item->connected_item->class == ZnWayPoint)) &&
- (item->parent == item->connected_item->parent))) {
- ZnITEM.UpdateItemDependency(item, old_connected);
- }
- else {
- item->connected_item = old_connected;
- }
- }
-
- if (ISSET(*flags, ZN_VIS_FLAG)) {
- /* Record the change to trigger the overlap manager latter */
- if ((item->class == ZnTrack) && ISSET(item->flags, ZN_VISIBLE_BIT)) {
- ZnGroupSetCallOm(item->parent, True);
- }
- }
-
- /* If the current position has changed, shift the past pos. */
- if (ISSET(*flags, ZN_MOVED_FLAG)) {
- if (item->class == ZnTrack) {
- AddToHistory(track, old_pos);
- ZnGroupSetCallOm(item->parent, True);
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
-**********************************************************************************
-*
-* Query --
-*
-**********************************************************************************
-*/
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, track_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
-**********************************************************************************
-*
-* ComputeCoordinates --
-*
-**********************************************************************************
-*/
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- TrackItem track = (TrackItem) item;
- ZnFieldSet field_set = &track->field_set;
- ZnItem c_item;
- History hist;
- ZnPoint old_label_pos, old_pos, p, xp;
- ZnDim old_label_width, old_label_height;
- ZnReal rotation;
- ZnBBox bbox;
- ZnPoint *points;
- unsigned int num_points, num_acc_pos, i;
- int alignment;
- int w2=0, h2=0, w=0, h=0;
-
- ZnResetBBox(&item->item_bounding_box);
- old_label_pos = field_set->label_pos;
- old_label_width = field_set->label_width;
- old_label_height = field_set->label_height;
-
- old_pos = track->dev;
-
- ZnTransformPoint(wi->current_transfo, &track->pos, &track->dev);
- track->dev.x = ZnNearestInt(track->dev.x);
- track->dev.y = ZnNearestInt(track->dev.y);
- /*printf("track pos %g %g --> %g %g\n", track->pos.x, track->pos.y, track->dev.x, track->dev.y);*/
- if (track->symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(track->symbol, &w, &h);
- /*printf("taille symbole %d %d\n", w, h);*/
- w2 = (w+1)/2;
- h2 = (h+1)/2;
- bbox.orig.x = track->dev.x - w2;
- bbox.orig.y = track->dev.y - h2;
- bbox.corner.x = bbox.orig.x + w;
- bbox.corner.y = bbox.orig.y + h;
-
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
-
- /* Here we approximate the past position sizes to the size
- of the current position. They are actually smaller but who
- care :-). In fact it is even worse as we use the overall
- information from the symbol font.
- */
- if ((item->class == ZnTrack) && track->history) {
- unsigned int visible_history_size;
- /*
- * Trunc the visible history to the managed size.
- */
- ZnListTruncate(track->history, wi->track_managed_history_size);
- visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
- wi->track_visible_history_size : 0);
-
- ZnResetBBox(&bbox);
- w = (int) track->history_width;
- w2 = (w+1)/2;
- num_acc_pos = ZnListSize(track->history);
- hist = ZnListArray(track->history);
- for (i = 0; i < num_acc_pos; i++) {
- ZnTransformPoint(wi->current_transfo, &hist[i].world, &hist[i].dev);
- if ((i < visible_history_size) && (hist[i].visible)) {
- bbox.orig.x = hist[i].dev.x - w2;
- bbox.orig.y = hist[i].dev.y - w2;
- bbox.corner.x = bbox.orig.x + w;
- bbox.corner.y = bbox.orig.y + w;
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- }
- }
- }
-
- /*
- * Compute the speed vector end.
- */
- if (item->class == ZnTrack) {
- p.x = track->pos.x + track->speed_vector.x * wi->speed_vector_length;
- p.y = track->pos.y + track->speed_vector.y * wi->speed_vector_length;
- ZnTransformPoint(wi->current_transfo, &p, &track->speed_vector_dev);
- track->speed_vector_dev.x = ZnNearestInt(track->speed_vector_dev.x);
- track->speed_vector_dev.y = ZnNearestInt(track->speed_vector_dev.y);
- if (ISSET(track->flags, SV_MARK_BIT)) {
- int w = (int) track->speed_vector_width + 1;
- ZnAddPointToBBox(&item->item_bounding_box,
- track->speed_vector_dev.x - w,
- track->speed_vector_dev.y - w);
- ZnAddPointToBBox(&item->item_bounding_box,
- track->speed_vector_dev.x + w,
- track->speed_vector_dev.y + w);
- }
- else {
- ZnAddPointToBBox(&item->item_bounding_box, track->speed_vector_dev.x,
- track->speed_vector_dev.y);
- }
- }
-
- /*
- * Take care of the connection between items.
- */
- c_item = item->connected_item;
- if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
- w2 = (int) track->connection_width/2;
- ZnAddPointToBBox(&item->item_bounding_box, track->dev.x-w2, track->dev.y-w2);
- ZnAddPointToBBox(&item->item_bounding_box, ((TrackItem)c_item)->dev.x+w2,
- ((TrackItem)c_item)->dev.y+w2);
- }
-
- /*
- * Compute the size of the circular marker.
- */
- p.x = track->pos.x + track->marker_size;
- p.y = track->pos.y;
- ZnTransformPoint(wi->current_transfo, &p, &xp);
- xp.x = xp.x - track->dev.x;
- xp.y = xp.y - track->dev.y;
- track->marker_size_dev = sqrt(xp.x*xp.x + xp.y*xp.y);
- track->marker_size_dev = ZnNearestInt(track->marker_size_dev);
- if (track->marker_size_dev > PRECISION_LIMIT) {
- ZnAddPointToBBox(&item->item_bounding_box,
- track->dev.x - (ZnPos) track->marker_size_dev,
- track->dev.y - (ZnPos) track->marker_size_dev);
- ZnAddPointToBBox(&item->item_bounding_box,
- track->dev.x + (ZnPos) track->marker_size_dev,
- track->dev.y + (ZnPos) track->marker_size_dev);
- }
-
- /* Compute the new label bounding box. */
- if (field_set->label_format && field_set->num_fields) {
- ZnDim bb_width, bb_height;
- ZnReal rho, dist;
- ZnPoint leader_end;
- int it;
-
- ZnFIELD.GetLabelBBox(field_set, &bb_width, &bb_height);
- /*
- * Compute the label position.
- */
- if (ISSET(track->flags, POLAR_BIT)) {
- rho = track->label_distance;
- /*
- * Compute heading after applying the transform.
- */
- ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &rotation, NULL);
- /*printf("rotation=%g, heading=%g, angle=%d\n", rotation,
- ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y),
- track->label_angle);*/
- rotation = ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y)-rotation;
- it = 0;
- while (1) {
- ZnPointPolarToCartesian(rotation, rho, (ZnReal) track->label_angle,
- &track->label_dx, &track->label_dy);
- field_set->label_pos.x = track->dev.x + track->label_dx;
- field_set->label_pos.y = track->dev.y - track->label_dy;
- ZnAnchor2Origin(&field_set->label_pos, bb_width, bb_height,
- track->label_anchor, &field_set->label_pos);
- ZnResetBBox(&bbox);
- ZnAddPointToBBox(&bbox, field_set->label_pos.x, field_set->label_pos.y);
- ZnAddPointToBBox(&bbox, field_set->label_pos.x + bb_width, field_set->label_pos.y + bb_height);
- dist = ZnRectangleToPointDist(&bbox, &track->dev);
- dist = track->label_distance - dist;
- if (ABS(dist) < 1.0 || it > 5) {
- break;
- }
- it++;
- rho += dist;
- }
- }
- else {
- field_set->label_pos.x = track->dev.x + track->label_dx;
- field_set->label_pos.y = track->dev.y - track->label_dy;
- ZnAnchor2Origin(&field_set->label_pos, bb_width, bb_height,
- track->label_anchor, &field_set->label_pos);
- }
- field_set->label_pos.x = ZnNearestInt(field_set->label_pos.x);
- field_set->label_pos.y = ZnNearestInt(field_set->label_pos.y);
-
- /*
- * Need to compensate for GL thick lines
- */
-#ifdef GL
-#define CORR 1
-#else
-#define CORR 0
-#endif
- ZnAddPointToBBox(&item->item_bounding_box, field_set->label_pos.x - CORR, field_set->label_pos.y - CORR);
- ZnAddPointToBBox(&item->item_bounding_box,
- field_set->label_pos.x + (ZnPos) bb_width + CORR,
- field_set->label_pos.y + (ZnPos) bb_height + CORR);
-#undef CORR
-
- /*
- * Process the leader.
- */
- if (track->leader_width > 0) {
- int left_x, left_y, right_x, right_y;
- ZnPoint end_points[ZN_LINE_END_POINTS];
-
- /*
- * Compute the actual leader end in the label.
- */
- if (track->leader_anchors) {
- left_x = track->leader_anchors->left_x;
- right_x = track->leader_anchors->right_x;
- left_y = track->leader_anchors->left_y;
- right_y = track->leader_anchors->right_y;
- }
- else {
- left_x = right_x = left_y = right_y = 50;
- }
- if (track->label_angle >= 270 || track->label_angle < 90) {
- if (track->leader_anchors && (left_y < 0)) {
- ZnFIELD.GetFieldBBox(field_set, (unsigned int) left_x, &bbox);
- leader_end.x = bbox.orig.x;
- leader_end.y = bbox.corner.y;
- }
- else {
- leader_end.x = field_set->label_pos.x + left_x*bb_width/100;
- leader_end.y = field_set->label_pos.y + left_y*bb_height/100;
- }
- alignment = ZN_AA_LEFT;
- }
- else {
- if (track->leader_anchors && (right_y < 0)) {
- ZnFIELD.GetFieldBBox(field_set, (unsigned int) right_x, &bbox);
- leader_end.x = bbox.corner.x;
- leader_end.y = bbox.corner.y;
- }
- else {
- leader_end.x = field_set->label_pos.x + right_x*bb_width/100;
- leader_end.y = field_set->label_pos.y + right_y*bb_height/100;
- }
- alignment = ZN_AA_RIGHT;
- }
-
- ZnFIELD.SetFieldsAutoAlign(field_set, alignment);
-
- /* Clip the leader on the label's fields */
- ZnFIELD.LeaderToLabel(field_set, &track->dev, &leader_end);
-
- /* Setup leader shape points */
- if (!track->leader_points) {
- track->leader_points = ZnListNew(ZN_LINE_SHAPE_POINTS, sizeof(ZnPoint));
- }
- ZnLineShapePoints(&track->dev, &leader_end, track->leader_width,
- track->leader_shape, &bbox, track->leader_points);
- ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
- points = (ZnPoint *) ZnListArray(track->leader_points);
- num_points = ZnListSize(track->leader_points);
-
- /* Setup leader ends */
- if (track->leader_first_end != NULL) {
- ZnGetLineEnd(&points[0], &points[1], track->leader_width,
- CapRound, track->leader_first_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- if (track->leader_last_end != NULL) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
- CapRound, track->leader_last_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- }
- }
-
- /* Update connected items. */
- if ((old_label_pos.x != field_set->label_pos.x) ||
- (old_label_pos.y != field_set->label_pos.y) ||
- (old_label_width != field_set->label_width) ||
- (old_label_height != field_set->label_height) ||
- (old_pos.x != track->dev.x) ||
- (old_pos.y != track->dev.y)) {
- /* Update connected items */
- SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* ToArea --
-* Tell if the object is entirely outside (-1),
-* entirely inside (1) or in between (0).
-*
-**********************************************************************************
-*/
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- TrackItem track = (TrackItem) item;
- int inside;
- int width, height;
- ZnDim lwidth, lheight;
- ZnBBox bbox, *area = ta->area;
- ZnPoint pts[2];
-
- /*
- * Try the current position.
- */
- ZnResetBBox(&bbox);
- if (track->symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(track->symbol, &width, &height);
- bbox.orig.x = track->dev.x-(width+1)/2;
- bbox.orig.y = track->dev.y-(height+1)/2;
- bbox.corner.x = bbox.orig.x + width;
- bbox.corner.y = bbox.orig.y + height;
- }
- inside = ZnBBoxInBBox(&bbox, area);
- if (inside == 0) {
- /*printf("track pos\n");*/
- return 0;
- }
-
- /*
- * Try the fields.
- */
- ZnFIELD.GetLabelBBox(&track->field_set, &lwidth, &lheight);
- if ((lwidth > 0.0) && (lheight > 0.0)) {
- if (ZnFIELD.FieldsToArea(&track->field_set, area) != inside) {
- return 0;
- }
- }
-
- /*
- * Try the leader.
- */
- if (track->field_set.label_format && (track->leader_width > 0)) {
- ZnPoint end_points[ZN_LINE_END_POINTS];
- ZnPoint *points;
- unsigned int num_points;
-
- points = (ZnPoint *) ZnListArray(track->leader_points);
- num_points = ZnListSize(track->leader_points);
- lwidth = track->leader_width > 1 ? track->leader_width : 0;
- if (ZnPolylineInBBox(points, num_points, lwidth,
- CapRound, JoinRound, area) != inside) {
- /*printf("track leader\n");*/
- return 0;
- }
- if (track->leader_first_end != NULL) {
- ZnGetLineEnd(&points[0], &points[1], track->leader_width,
- CapRound, track->leader_first_end, end_points);
- if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != inside) {
- /*printf("track leader\n");*/
- return 0;
- }
- }
- if (track->leader_last_end != NULL) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
- CapRound, track->leader_last_end, end_points);
- if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != inside) {
- /*printf("track leader\n");*/
- return 0;
- }
- }
- }
-
- /*
- * Try the speed vector.
- */
- if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
- pts[0] = track->dev;
- pts[1] = track->speed_vector_dev;
- lwidth = track->speed_vector_width > 1 ? track->speed_vector_width : 0;
- if (ZnPolylineInBBox(pts, 2, lwidth, CapRound, JoinRound, area) != inside) {
- /*printf("track speed vector\n");*/
- return 0;
- }
- }
-
- /*
- * Try the connection.
- */
- if ((item->connected_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
- pts[0] = track->dev;
- pts[1] = ((TrackItem) item->connected_item)->dev;
- lwidth = track->connection_width > 1 ? track->connection_width : 0;
- if (ZnPolylineInBBox(pts, 2, lwidth, CapRound, JoinRound, area) != inside) {
- /*printf("track connection\n");*/
- return 0;
- }
- }
-
- return inside;
-}
-
-
-/*
-**********************************************************************************
-*
-* Draw --
-*
-**********************************************************************************
-*/
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TrackItem track = (TrackItem) item;
- ZnItem c_item;
- XGCValues values;
- History hist;
- unsigned int h_side_size, side_size, width=0, height=0;
- unsigned int i, nb_hist, num_acc_pos;
- int x, y;
-
- /* Draw the marker */
- if (track->marker_size_dev != 0) {
- ZnSetLineStyle(wi, track->marker_style);
- values.foreground = ZnGetGradientPixel(track->marker_color, 0.0);
- values.line_width = 0;
- if (ISSET(track->flags, MARKER_FILLED_BIT)) {
- if (track->marker_fill_pattern == ZnUnspecifiedImage) {
- /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- }
- else {
- /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(track->marker_fill_pattern, wi->win);
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle | GCStipple | GCLineWidth | GCForeground, &values);
- }
- XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
- (int) (track->dev.x - (ZnPos) track->marker_size_dev),
- (int) (track->dev.y - (ZnPos) track->marker_size_dev),
- (unsigned int) track->marker_size_dev * 2,
- (unsigned int) track->marker_size_dev * 2,
- 0, 360 * 64);
- }
- else {
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- (int) (track->dev.x - (ZnPos) track->marker_size_dev),
- (int) (track->dev.y - (ZnPos) track->marker_size_dev),
- (unsigned int) (track->marker_size_dev * 2),
- (unsigned int) (track->marker_size_dev * 2),
- 0, 360 * 64);
- }
- }
-
- /*
- * Draw the connection.
- */
- c_item = item->connected_item;
- if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
- ZnPoint pts[2];
-
- pts[0] = track->dev;
- pts[1] = ((TrackItem) item->connected_item)->dev;
- ZnDrawLineShape(wi, pts, 2, track->connection_style,
- ZnGetGradientPixel(track->connection_color, 0.0),
- track->connection_width, ZN_LINE_STRAIGHT);
- }
-
- /*
- * Draw the speed vector.
- */
- if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
- values.foreground = ZnGetGradientPixel(track->speed_vector_color, 0.0);
- values.line_width = (int) (track->speed_vector_width > 1 ? track->speed_vector_width : 0);
- values.line_style = LineSolid;
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc,
- GCForeground | GCLineWidth | GCLineStyle | GCFillStyle, &values);
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) track->dev.x,
- (int) track->dev.y,
- (int) track->speed_vector_dev.x,
- (int) track->speed_vector_dev.y);
- }
-
- /*
- * Draw the leader.
- */
- if (track->field_set.label_format && (track->leader_width > 0)) {
- ZnPoint end_points[ZN_LINE_END_POINTS];
- XPoint xpoints[ZN_LINE_END_POINTS];
- ZnPoint *points;
- unsigned int num_points;
-
- points = (ZnPoint *) ZnListArray(track->leader_points);
- num_points = ZnListSize(track->leader_points);
- ZnDrawLineShape(wi, points, num_points, track->leader_style,
- ZnGetGradientPixel(track->leader_color, 0.0),
- track->leader_width, track->leader_shape);
- if (track->leader_first_end != NULL) {
- ZnGetLineEnd(&points[0], &points[1], track->leader_width,
- CapRound, track->leader_first_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xpoints[i].x = (short) end_points[i].x;
- xpoints[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- if (track->leader_last_end != NULL) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
- CapRound, track->leader_last_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xpoints[i].x = (short) end_points[i].x;
- xpoints[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- }
-
- if (track->symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(track->symbol, &width, &height);
- }
-
- /*
- * Draw the history, current pos excepted.
- */
- if ((item->class == ZnTrack) && track->history) {
- unsigned int visible_history_size;
-
- visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
- wi->track_visible_history_size : 0);
-
- values.foreground = ZnGetGradientPixel(track->history_color, 0.0);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);
- if (ISCLEAR(track->flags, FILLED_HISTORY_BIT)) {
- values.line_width = 0;
- values.line_style = LineSolid;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth | GCLineStyle, &values);
- }
- num_acc_pos = MIN(visible_history_size, ZnListSize(track->history));
- hist = ZnListArray(track->history);
- side_size = (int) track->history_width;
-
- for (i = 0, nb_hist = 0; i < num_acc_pos; i++) {
- if (ISSET(track->flags, LAST_AS_FIRST_BIT) &&
- (i == visible_history_size-1)) {
- values.foreground = ZnGetGradientPixel(track->symbol_color, 0.0);
- XChangeGC(wi->dpy, wi->gc, GCForeground, &values);
- }
- side_size--;
- side_size = MAX(1, side_size);
- h_side_size = (side_size+1)/2;
- if (hist[i].visible) {
- if (ISSET(track->flags, DOT_MIXED_HISTORY_BIT) && !(nb_hist++ % 2)) {
- x = (int) hist[i].dev.x;
- y = (int) hist[i].dev.y;
- /* Draw a point (portability layer doesn't define a XDrawPoint) */
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, x, y, x, y);
- }
- else {
- x = ((int) hist[i].dev.x) - h_side_size;
- y = ((int) hist[i].dev.y) - h_side_size;
- if (ISSET(track->flags, CIRCLE_HISTORY_BIT)) {
- if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
- XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, side_size, side_size, 0, 360*64);
- }
- else {
- XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, side_size - 1, side_size - 1, 0, 360*64);
- }
- }
- else {
- if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, side_size, side_size);
- }
- else {
- XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, side_size - 1, side_size - 1);
- }
- }
- }
- }
- }
- }
-
- /*
- * Draw the current position using a pattern for Tk.
- */
- if (track->symbol != ZnUnspecifiedImage) {
- x = ((int) track->dev.x) - (width+1)/2;
- y = ((int) track->dev.y) - (height+1)/2;
- values.foreground = ZnGetGradientPixel(track->symbol_color, 0.0);
- values.fill_style = FillStippled;
- values.stipple = ZnImagePixmap(track->symbol, wi->win);
- values.ts_x_origin = x;
- values.ts_y_origin = y;
- XChangeGC(wi->dpy, wi->gc,
- GCForeground|GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin,
- &values);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height);
- }
-
- /*
- * Draw the label.
- */
- ZnFIELD.DrawFields(&track->field_set);
-}
-
-
-/*
-**********************************************************************************
-*
-* Render --
-*
-**********************************************************************************
-*/
-#ifdef GL
-struct MarkerCBData {
- ZnPoint *p;
- int num;
- ZnReal size;
- ZnPoint center;
-};
-
-static void
-MarkerRenderCB(void *closure)
-{
- struct MarkerCBData *cbd = (struct MarkerCBData *) closure;
- int i;
-
- glBegin(GL_TRIANGLE_FAN);
- glVertex2d(cbd->center.x, cbd->center.y);
- for (i = 0; i < cbd->num; i++) {
- glVertex2d(cbd->center.x + cbd->p[i].x*cbd->size,
- cbd->center.y + cbd->p[i].y*cbd->size);
- }
- glEnd();
-}
-
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TrackItem track = (TrackItem) item;
- TrackItem c_item;
- History hist;
- unsigned int h_side_size, side_size, width=0, height=0;
- unsigned int i, j, nb_hist, num_acc_pos;
- unsigned short alpha;
- XColor *color;
- ZnPoint *points;
- unsigned int num_points;
- ZnReal x0, y0, size;
-
- /* Draw the marker */
- if (track->marker_size_dev != 0) {
- points = ZnGetCirclePoints(3, ZN_CIRCLE_MEDIUM, 0.0, 2*M_PI, &num_points, NULL);
- x0 = track->dev.x;
- y0 = track->dev.y;
- size = track->marker_size_dev;
- if (ISSET(track->flags, MARKER_FILLED_BIT)) {
- ZnBBox bbox;
- struct MarkerCBData cbd;
-
- cbd.center.x = x0;
- cbd.center.y = y0;
- cbd.num = num_points;
- cbd.size = size;
- cbd.p = points;
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (track->marker_fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
- ZnResetBBox(&bbox);
- ZnAddPointToBBox(&bbox, track->dev.x-size, track->dev.y-size);
- ZnAddPointToBBox(&bbox, track->dev.x+size, track->dev.y+size);
- ZnRenderTile(wi, track->marker_fill_pattern, track->marker_color,
- MarkerRenderCB, &cbd, (ZnPoint *) &bbox);
- }
- else {
- color = ZnGetGradientColor(track->marker_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- MarkerRenderCB(&cbd);
- }
- }
- else {
- glLineWidth(1.0);
- ZnSetLineStyle(wi, track->marker_style);
- glBegin(GL_LINE_LOOP);
- for (i = 0; i < num_points; i++) {
- glVertex2d(x0 + points[i].x*size, y0 + points[i].y*size);
- }
- glEnd();
- }
- }
-
- /*
- * Draw the connection.
- */
- c_item = (TrackItem) item->connected_item;
- if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
- color = ZnGetGradientColor(track->connection_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glLineWidth((GLfloat)track->connection_width);
- glBegin(GL_LINES);
- glVertex2d(track->dev.x, track->dev.y);
- glVertex2d(c_item->dev.x, c_item->dev.y);
- glEnd();
- }
-
- /*
- * Draw the speed vector.
- */
- if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
- unsigned int num_clips=0, svlength=0;
- ZnReal svxstep=0, svystep=0;
- GLfloat ticksize=0;
-
- color = ZnGetGradientColor(track->speed_vector_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glLineWidth((GLfloat)track->speed_vector_width);
-
- /*
- * Turn off AA to obtain a square point precisely defined
- */
- if (ISSET(track->flags, SV_TICKS_BIT) ||
- ISSET(track->flags, SV_MARK_BIT)) {
- glDisable(GL_POINT_SMOOTH);
-
- if (ISSET(track->flags, SV_TICKS_BIT)) {
- num_clips = ZnListSize(wi->clip_stack);
- ticksize = 3;
- svlength = (int) wi->speed_vector_length;
- svxstep = (track->speed_vector_dev.x-track->dev.x)/svlength;
- svystep = (track->speed_vector_dev.y-track->dev.y)/svlength;
- glPointSize(ticksize);
- ZnGlStartClip(num_clips, False);
- glBegin(GL_POINTS);
- for (i = 1; i < svlength; i++) {
- glVertex2d(track->dev.x + i*svxstep, track->dev.y + i*svystep);
- }
- glEnd();
- ZnGlRenderClipped();
- }
- }
-
- glBegin(GL_LINES);
- glVertex2d(track->dev.x, track->dev.y);
- glVertex2d(track->speed_vector_dev.x, track->speed_vector_dev.y);
- glEnd();
-
- if (ISSET(track->flags, SV_MARK_BIT)) {
- glPointSize((GLfloat) (track->speed_vector_width + 2.0));
- glBegin(GL_POINTS);
- glVertex2d(track->speed_vector_dev.x, track->speed_vector_dev.y);
- glEnd();
- }
-
- if (ISSET(track->flags, SV_TICKS_BIT) ||
- ISSET(track->flags, SV_MARK_BIT)) {
- glEnable(GL_POINT_SMOOTH);
-
- if (ISSET(track->flags, SV_TICKS_BIT)) {
- glPointSize(ticksize);
- ZnGlRestoreStencil(num_clips, False);
- glBegin(GL_POINTS);
- for (i = 1; i < svlength; i++) {
- glVertex2d(track->dev.x + i*svxstep, track->dev.y + i*svystep);
- }
- glEnd();
- ZnGlEndClip(num_clips);
- }
- }
- }
-
- /*
- * Draw the leader.
- */
- if (track->field_set.label_format && (track->leader_width > 0)) {
- points = ZnListArray(track->leader_points);
- num_points = ZnListSize(track->leader_points);
- ZnRenderPolyline(wi,
- points, num_points, track->leader_width,
- track->leader_style, CapRound, JoinRound,
- track->leader_first_end, track->leader_last_end,
- track->leader_color);
- }
-
- if (track->symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(track->symbol, &width, &height);
- }
-
- /*
- * Draw the history, current pos excepted.
- */
- if ((item->class == ZnTrack) && track->history) {
- unsigned int visible_history_size;
-
- visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
- wi->track_visible_history_size : 0);
-
- points = ZnGetCirclePoints(3, ZN_CIRCLE_COARSE, 0.0, 2*M_PI, &num_points, NULL);
- color = ZnGetGradientColor(track->history_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- glLineWidth(1.0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- num_acc_pos = MIN(visible_history_size, ZnListSize(track->history));
- hist = ZnListArray(track->history);
- side_size = (int) track->history_width;
- /*
- * Turning off line and point smoothing
- * to enhance ;-) history drawing.
- */
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_POINT_SMOOTH);
- for (i = 0, nb_hist = 0; i < num_acc_pos; i++) {
- if (ISSET(track->flags, LAST_AS_FIRST_BIT) &&
- (i == visible_history_size-1)) {
- color = ZnGetGradientColor(track->symbol_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- side_size--;
- side_size = MAX(1, side_size);
- h_side_size = (side_size+1)/2;
- if (hist[i].visible) {
- x0 = hist[i].dev.x;
- y0 = hist[i].dev.y;
- if ((ISSET(track->flags, DOT_MIXED_HISTORY_BIT) && !(nb_hist++ % 2)) ||
- (side_size == 1)) {
- glPointSize(1.0);
- glBegin(GL_POINTS);
- glVertex2d(x0, y0);
- glEnd();
- }
- else {
- if (ISSET(track->flags, CIRCLE_HISTORY_BIT)) {
- if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
- glPointSize((GLfloat) side_size);
- glBegin(GL_POINTS);
- glVertex2d(x0, y0);
- glEnd();
- }
- else {
-#if 1
- glBegin(GL_LINE_LOOP);
- for (j = 0; j < num_points; j++) {
- glVertex2d(x0 + points[j].x*h_side_size,
- y0 + points[j].y*h_side_size);
- }
- glEnd();
-#else
- RenderHollowDot(wi, &hist[i].dev, side_size+1);
-#endif
- }
- }
- else {
- if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
- glBegin(GL_QUADS);
- glVertex2d(x0 - h_side_size, y0 - h_side_size);
- glVertex2d(x0 - h_side_size, y0 + h_side_size);
- glVertex2d(x0 + h_side_size, y0 + h_side_size);
- glVertex2d(x0 + h_side_size, y0 - h_side_size);
- glEnd();
- }
- else {
- glBegin(GL_LINE_LOOP);
- glVertex2d(x0 - h_side_size, y0 - h_side_size);
- glVertex2d(x0 - h_side_size, y0 + h_side_size);
- glVertex2d(x0 + h_side_size, y0 + h_side_size);
- glVertex2d(x0 + h_side_size, y0 - h_side_size);
- glEnd();
- }
- }
- }
- }
- }
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_POINT_SMOOTH);
- }
-
- /*
- * Draw the current position using a pattern.
- */
- if (track->symbol != ZnUnspecifiedImage) {
- ZnPoint p;
-
- p.x = track->dev.x - (width+1)/2;
- p.y = track->dev.y - (height+1)/2;
- ZnRenderIcon(wi, track->symbol, track->symbol_color, &p, True);
- }
-
- /*
- * Render the label.
- */
- ZnFIELD.RenderFields(&track->field_set);
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
-**********************************************************************************
-*
-* IsSensitive --
-*
-**********************************************************************************
-*/
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- if (ISCLEAR(item->flags, ZN_SENSITIVE_BIT) ||
- !item->parent->class->IsSensitive(item->parent, ZN_NO_PART)) {
- return False;
- }
-
- if (item_part < ZN_NO_PART) {
- return ISSET(item->part_sensitive, ZnPartToBit(item_part));
- }
- else if (item_part >= 0) {
- return ZnFIELD.IsFieldSensitive(&((TrackItem) item)->field_set, item_part);
- }
- else if (item_part == ZN_NO_PART) {
- return ISSET(item->flags, ZN_SENSITIVE_BIT);
- }
- return True;
-}
-
-
-/*
-**********************************************************************************
-*
-* Pick --
-*
-**********************************************************************************
-*/
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- TrackItem track = (TrackItem) item;
- ZnItem c_item;
- ZnBBox bbox;
- double dist=0, new_dist;
- ZnPoint *points, *p = ps->point;
- int num_points, i;
- int width=0, height=0;
- double width_2;
- int best_part;
- ZnPoint pts[2];
-
- /*
- * Try one of the fields.
- */
- dist = ZnFIELD.FieldsPick(&track->field_set, p, &best_part);
- if (dist <= 0.0) {
- goto report0;
- }
-
- /*
- * Try the current position symbol.
- */
- ZnResetBBox(&bbox);
- if (track->symbol != ZnUnspecifiedImage) {
- ZnSizeOfImage(track->symbol, &width, &height);
- bbox.orig.x = track->dev.x-(width+1)/2;
- bbox.orig.y = track->dev.y-(height+1)/2;
- bbox.corner.x = bbox.orig.x + width;
- bbox.corner.y = bbox.orig.y + height;
- }
-
- new_dist = ZnRectangleToPointDist(&bbox, p);
- if (new_dist < dist) {
- best_part = CURRENT_POSITION;
- dist = new_dist;
- }
- if (dist <= 0.0) {
- goto report0;
- }
-
- /*
- * Try the leader.
- */
- if (track->field_set.label_format && (track->leader_width > 0) &&
- track->leader_points) {
- ZnPoint end_points[ZN_LINE_END_POINTS];
-
- width_2 = (track->leader_width>1) ? ((double) track->leader_width)/2.0 : 0;
- points = (ZnPoint *) ZnListArray(track->leader_points);
- num_points = ZnListSize(track->leader_points)-1;
- for (i = 0; i < num_points; i++) {
- new_dist = ZnLineToPointDist(&points[i], &points[i+1], p, NULL);
- new_dist -= width_2;
- if (new_dist < dist) {
- best_part = LEADER;
- dist = new_dist;
- }
- if (dist <= 0.0) {
- goto report0;
- }
- }
- if (track->leader_first_end != NULL) {
- ZnGetLineEnd(&points[0], &points[1], track->leader_width,
- CapRound, track->leader_first_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- best_part = LEADER;
- dist = new_dist;
- }
- if (dist <= 0.0) {
- goto report0;
- }
- }
- if (track->leader_last_end != NULL) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
- CapRound, track->leader_last_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- best_part = LEADER;
- dist = new_dist;
- }
- if (dist <= 0.0) {
- goto report0;
- }
- }
- }
-
- /*
- * Try the speed vector.
- */
- if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
- pts[0] = track->dev;
- pts[1] = track->speed_vector_dev;
- new_dist = ZnPolylineToPointDist(pts, 2, track->speed_vector_width,
- CapRound, JoinRound, p);
- if (new_dist < dist) {
- best_part = SPEED_VECTOR;
- dist = new_dist;
- }
- if (dist <= 0.0) {
- goto report0;
- }
- }
-
- /*
- * Try the connection.
- */
- c_item = item->connected_item;
- if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
- pts[0] = track->dev;
- pts[1] = ((TrackItem) item->connected_item)->dev;
- new_dist = ZnPolylineToPointDist(pts, 2, track->connection_width,
- CapRound, JoinRound, p);
- if (new_dist < dist) {
- dist = new_dist;
- best_part = CONNECTION;
- }
- if (dist <= 0.0) {
- report0:
- dist = 0.0;
- }
- }
-
- /* printf("track %d reporting part %d, distance %lf\n",
- item->id, best_part, dist); */
- ps->a_part = best_part;
- return dist;
-}
-
-
-/*
-**********************************************************************************
-*
-* PostScript --
-*
-**********************************************************************************
-*/
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- return TCL_OK;
-}
-
-
-#ifdef ATC
-/*
-**********************************************************************************
-*
-* ZnSendTrackToOm --
-*
-**********************************************************************************
-*/
-/*
- * TODO:
- *
- * The tracks should be identified by their ids not their
- * structure pointer. This would enable an easy interface
- * between the overlap manager and the applications when
- * dealing with tracks.
- */
-void *
-ZnSendTrackToOm(void *ptr,
- void *item,
- int *x,
- int *y,
- int *sv_dx,
- int *sv_dy,
- /*int *label_x,
- int *label_y,
- int *label_width,
- int *label_height,*/
- int *rho,
- int *theta,
- int *visibility,
- int *locked,
- int *preferred_angle,
- int *convergence_style)
-{
- ZnWInfo *wi = (ZnWInfo *) ptr;
- ZnItem current_item = (ZnItem) item;
- TrackItem track;
- ZnBBox zn_bbox, bbox;
- ZnBool to_be_sent;
-
- int rho_derived ;
-
- zn_bbox.orig.x = zn_bbox.orig.y = 0;
- zn_bbox.corner.x = wi->width;
- zn_bbox.corner.y = wi->height;
-
- if (current_item == ZN_NO_ITEM) {
- current_item = ZnGroupHead(wi->om_group);
- }
- else {
- current_item = current_item->next;
- }
-
- while (current_item != ZN_NO_ITEM) {
- to_be_sent = current_item->class == ZnTrack;
-
- /* We send invisibles items because the current algorithm
- take care of the age of the tracks.
- to_be_sent &= ISSET(current_item->flags, ZN_VISIBLE_BIT);*/
-
- ZnIntersectBBox(&zn_bbox, &current_item->item_bounding_box, &bbox);
- to_be_sent &= !ZnIsEmptyBBox(&bbox);
-
- if (to_be_sent) {
- track = (TrackItem) current_item;
-
- *x = (int) track->dev.x;
- *y = wi->height - ((int) track->dev.y);
-
- /*
- * We must send world values for speed vector deltas as device
- * equivalents can be null. But then if the image is rotated this
- * is nonsense.
- */
- *sv_dx = (int) track->speed_vector.x;
- *sv_dy = (int) track->speed_vector.y;
-
- /* Fri Oct 13 15:16:38 2000
- *label_x = track->field_set.label_pos.x;
- *label_y = wi->height - track->field_set.label_pos.y;
- if (track->field_set.label_format) {
- ZnDim bb_width, bb_height;
-
- ZnFIELD.GetLabelBBox(&track->field_set, &bb_width, &bb_height);
- *label_width = bb_width;
- *label_height = bb_height;
- }
- else {
- *label_width = 0;
- *label_height = 0;
- }
- */
-
- /*
- * Trial to fix rho drift due to ZnPointPolarToCartesian
- * roundoff error.
- */
- rho_derived = (int) sqrt(track->label_dx*track->label_dx +
- track->label_dy*track->label_dy);
-#ifdef DP
- if (ABS(rho_derived - track->label_distance) < LABEL_DISTANCE_THRESHOLD) {
- /* The error is narrow so value discarded */
- *rho = track->label_distance ;
- }
- else {
- /* Means a user change has been performed on label_dx label_dy */
- *rho = rho_derived ;
- }
-#else
- *rho = rho_derived;
-#endif
- *theta = track->label_angle;
- *visibility = (ISSET(current_item->flags, ZN_VISIBLE_BIT) ? 1 : 0 );
- *locked = (ISSET(track->flags, FROZEN_LABEL_BIT) ? 1 : 0);
- *preferred_angle = track->label_preferred_angle;
- *convergence_style = track->label_convergence_style;
- break;
- }
-
- current_item = current_item->next;
- }
-
- return (void *) current_item;
-}
-
-
-/*
-**********************************************************************************
-*
-* ZnSetLabelAngleFromOm --
-*
-**********************************************************************************
-*/
-void
-ZnSetLabelAngleFromOm(void *ptr, /* No longer in use. */
- void *item,
- int rho,
- int theta)
-{
- TrackItem track = (TrackItem) item;
-
- theta %= 360;
- if (theta < 0) {
- theta += 360;
- }
- if (ISCLEAR(track->flags, FROZEN_LABEL_BIT) && (track->label_angle != theta)) {
- track->label_angle = theta;
-#ifdef DP
- track->label_distance = rho;
-#endif
- SET(track->flags, POLAR_BIT);
- ZnITEM.Invalidate((ZnItem) item, ZN_COORDS_FLAG);
- /* ZnGroupSetCallOm(((ZnItem)item)->parent, True);*/
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* ZnQueryLabelPosition -- OverlapMan query the widget about what would be the
-* label position if label_angle is theta
-*
-**********************************************************************************
-*/
-void
-ZnQueryLabelPosition(void *ptr, /* No longer in use. */
- void *item,
- int theta,
- int *x,
- int *y,
- int *w,
- int *h)
-{
- ZnItem it = (ZnItem) item;
- ZnWInfo *wi = it->wi;
- TrackItem track = (TrackItem) it;
-
- if (track->field_set.label_format) {
- ZnDim bb_width, bb_height;
- ZnDim delta_x, delta_y;
- ZnReal heading;
-
- /*
- * !! BUG !! This doesn't work if the current transform has some rotation.
- */
- heading = ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y);
- ZnPointPolarToCartesian(heading, track->label_distance, (ZnReal) theta, &delta_x, &delta_y);
- ZnFIELD.GetLabelBBox(&track->field_set, &bb_width, &bb_height);
- /*
- * !! BUG !! This assume a label placing relative to the center anchor.
- * We must fix this by taking into account the label anchor.
- */
- *x = (int) track->dev.x + (int) (delta_x - bb_width/2);
- *y = (int) track->dev.y - (int) (delta_y + bb_height/2);
- *y = ((int) wi->height) - *y;
- *w = (int) bb_width;
- *h = (int) bb_height;
- }
- else {
- *x = *y = *w = *h = 0;
- }
-}
-#endif
-
-
-/*
-**********************************************************************************
-*
-* ZnSetHistoryVisibility -- PLC - not yet implemented
-*
-**********************************************************************************
-*/
-void
-ZnSetHistoryVisibility(ZnItem item,
- int index,
- ZnBool visible)
-{
-}
-
-
-/*
-**********************************************************************************
-*
-* ZnTruncHistory -- PLC - not yet interfaced
-*
-**********************************************************************************
-*/
-void
-ZnTruncHistory(ZnItem item)
-{
- TrackItem track = (TrackItem) item;
-
- if (track->history) {
- int size = ZnListSize (track->history);
- History hist_tbl = ZnListArray (track->history);
- while (size--) {
- hist_tbl[size].visible = False;
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* GetFieldSet --
-*
-**********************************************************************************
-*/
-static ZnFieldSet
-GetFieldSet(ZnItem item)
-{
- return &((TrackItem) item)->field_set;
-}
-
-
-/*
-**********************************************************************************
-*
-* GetAnchor --
-*
-**********************************************************************************
-*/
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- ZnFieldSet field_set = &((TrackItem) item)->field_set;
- ZnDim width, height;
-
- if (field_set->label_format) {
- ZnFIELD.GetLabelBBox(field_set, &width, &height);
- ZnOrigin2Anchor(&field_set->label_pos, width, height, anchor, p);
- }
- else {
- p->x = p->y = 0.0;
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* Coords --
-* Return or edit the item position.
-*
-**********************************************************************************
-*/
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- TrackItem track = (TrackItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp, " ",
- item->class->name, "s can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on ",
- item->class->name, "s", NULL);
- return TCL_ERROR;
- }
- if (item->class == ZnTrack) {
- AddToHistory(track, track->pos);
- }
- track->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &track->pos;
- }
- return TCL_OK;
-}
-
-
-/*
-**********************************************************************************
-*
-* Part --
-* Convert a private part from/to symbolic representation.
-*
-**********************************************************************************
-*/
-static int
-Part(ZnItem item,
- Tcl_Obj **part_spec,
- int *part)
-{
- char *part_str="";
- int c;
- char *end;
-
- if (*part_spec) {
- part_str = Tcl_GetString(*part_spec);
- if (strlen(part_str) == 0) {
- *part = ZN_NO_PART;
- }
- else if (isdigit(part_str[0])) {
- *part = strtol(part_str, &end, 0);
- if ((*end != 0) || (*part < 0) ||
- ((unsigned int) *part >= ((TrackItem) item)->field_set.num_fields)) {
- goto part_error;
- }
- }
- else {
- c = part_str[0];
- if ((c == 'c') && (strcmp(part_str, "connection") == 0)) {
- *part = CONNECTION;
- }
- else if ((c == 'l') && (strcmp(part_str, "leader") == 0)) {
- *part = LEADER;
- }
- else if ((c == 'p') && (strcmp(part_str, "position") == 0)) {
- *part = CURRENT_POSITION;
- }
- else if ((c == 's') && (strcmp(part_str, "speedvector") == 0)) {
- if (item->class != ZnTrack) {
- goto part_error;
- }
- *part = SPEED_VECTOR;
- }
- else {
- part_error:
- Tcl_AppendResult(item->wi->interp, " invalid item part specification", NULL);
- return TCL_ERROR;
- }
- }
- }
- else {
- if (*part >= 0) {
- *part_spec = Tcl_NewIntObj(*part);
- }
- else {
- part_str = "";
- switch (*part) {
- default:
- case ZN_NO_PART:
- break;
- case CURRENT_POSITION:
- part_str = "position";
- break;
- case LEADER:
- part_str = "leader";
- break;
- case CONNECTION:
- part_str = "connection";
- break;
- case SPEED_VECTOR:
- if (item->class == ZnTrack) {
- part_str = "speedvector";
- break;
- }
- }
- if (part_str[0]) {
- *part_spec = Tcl_NewStringObj(part_str, -1);
- }
- }
- }
- return TCL_OK;
-}
-
-
-/*
-**********************************************************************************
-*
-* Index --
-* Parse a text index and return its value and aa
-* error status (standard Tcl result).
-*
-**********************************************************************************
-*/
-static int
-Index(ZnItem item,
- int field,
- Tcl_Obj *index_spec,
- int *index)
-{
- return ZnFIELD.FieldIndex(&((TrackItem) item)->field_set, field,
- index_spec, index);
-}
-
-
-/*
-**********************************************************************************
-*
-* InsertChars --
-*
-**********************************************************************************
-*/
-static void
-InsertChars(ZnItem item,
- int field,
- int *index,
- char *chars)
-{
- if (ZnFIELD.FieldInsertChars(&((TrackItem) item)->field_set,
- field, index, chars)) {
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* DeleteChars --
-*
-**********************************************************************************
-*/
-static void
-DeleteChars(ZnItem item,
- int field,
- int *first,
- int *last)
-{
- if (ZnFIELD.FieldDeleteChars(&((TrackItem) item)->field_set,
- field, first, last)) {
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-}
-
-
-/*
-**********************************************************************************
-*
-* Cursor --
-*
-**********************************************************************************
-*/
-static void
-TrackCursor(ZnItem item,
- int field,
- int index)
-{
- ZnFIELD.FieldCursor(&((TrackItem) item)->field_set, field, index);
-}
-
-
-/*
-**********************************************************************************
-*
-* Selection --
-*
-**********************************************************************************
-*/
-static int
-Selection(ZnItem item,
- int field,
- int offset,
- char *chars,
- int max_chars)
-{
- return ZnFIELD.FieldSelection(&((TrackItem) item)->field_set, field,
- offset, chars, max_chars);
-}
-
-
-/*
-**********************************************************************************
-*
-* Exported functions struct --
-*
-**********************************************************************************
-*/
-/*
- * Track -position attribute is not handled the same way as other
- * interface items like texts, icons and such, as it make little sense
- * to change the local transform of a track. It is always processed as
- * a point in the coordinate system of the track's parent. It is the same
- * for the points in the history and the speed vector end.
- */
-static ZnItemClassStruct TRACK_ITEM_CLASS = {
- "track",
- sizeof(TrackItemStruct),
- track_attrs,
- 4, /* num_parts */
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- GetFieldSet,
- GetAnchor,
- NULL, /* GetClipVertices */
- NULL, /* GetContours */
- Coords,
- InsertChars,
- DeleteChars,
- TrackCursor,
- Index,
- Part,
- Selection,
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-static ZnItemClassStruct WAY_POINT_ITEM_CLASS = {
- "waypoint",
- sizeof(TrackItemStruct),
- wp_attrs,
- 3, /* num_parts */
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- -1,
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- GetFieldSet,
- GetAnchor,
- NULL, /* GetClipVertices */
- NULL, /* GetContours */
- Coords,
- InsertChars,
- DeleteChars,
- TrackCursor,
- Index,
- Part,
- Selection,
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Render,
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnTrack = (ZnItemClassId) &TRACK_ITEM_CLASS;
-ZnItemClassId ZnWayPoint = (ZnItemClassId) &WAY_POINT_ITEM_CLASS;
diff --git a/generic/Track.h b/generic/Track.h
deleted file mode 100644
index d96a7a6..0000000
--- a/generic/Track.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Track.h --
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Tue Jan 19 16:03:53 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Track_h
-#define _Track_h
-
-
-#include "Item.h"
-
-
-/*
- **********************************************************************************
- *
- * Functions defined in Track.c for internal use.
- *
- **********************************************************************************
- */
-
-void *ZnSendTrackToOm(void *ptr, void *item, int *x, int *y,
- int *sv_dx, int *sv_dy,
- /* Fri Oct 13 15:18:11 2000
- int *label_x, int *label_y,
- int *label_width, int *label_height,*/
- int *rho, int *theta, int *visibility, int *locked,
- int *preferred_angle, int *convergence_style);
-void ZnSetLabelAngleFromOm(void *ptr, void *item, int rho, int theta);
-void ZnQueryLabelPosition(void *ptr, void *item, int theta,
- int *x, int *y, int *w, int *h);
-void ZnSetHistoryVisibility(ZnItem item, int index, ZnBool visibility);
-void ZnTruncHistory(ZnItem item);
-
-
-#endif /* _Track_h */
diff --git a/generic/Transfo.c b/generic/Transfo.c
deleted file mode 100644
index d9cee9f..0000000
--- a/generic/Transfo.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Transfo.c -- Implementation of transformation routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * This package deals with *AFFINE* 3x3 matrices.
- * This means that you should not try to feed it with matrices
- * containing perspective changes. It is assumed that the third
- * column is always [0 0 1] as this is the case for affine matrices.
- * Furthermore affine matrices are known to be invertible (non singular).
- * Despite this, various tests are done to test the invertibility because
- * of numerical precision or limit.
- * Any of the operations in this module yield an affine matrix. Composition
- * of two affine matrices and inversion of an affine matrix result in an
- * affine matrix (Affine matrices Group property). Rotation, translation
- * anamorphic scaling, xy skew and yx skew also preserve the property.
- *
- */
-
-
-#include "Item.h"
-#include "Geo.h"
-#include "Transfo.h"
-#include "Types.h"
-
-#include <stdlib.h>
-
-
-static const char rcsid[] = "$Imagine: Transfo.c,v 1.7 1997/01/24 14:33:37 lecoanet Exp $";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-
-/*
- *************************************************************************
- *
- * The transformation primitives are based on affines matrices retricted
- * to the following pattern:
- *
- * x x 0
- * x x 0
- * x x 1
- *
- * It is necessary to feed only those matrices to the Transfo primitives
- * as they do optimizations based on the properties of affine matrices.
- * Furthermore the package stores only the first two columns, the third
- * is constant. There is no way to describe perspective transformation
- * with these transformation matrices.
- *
- *************************************************************************
- */
-
-/*
- *************************************************************************
- *
- * ZnTransfoNew --
- * Create a new transformation and return it initialized to
- * identity.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnTransfoNew()
-{
- ZnTransfo *t;
-
- t = (ZnTransfo *) ZnMalloc(sizeof(ZnTransfo));
- ZnTransfoSetIdentity(t);
-
- return t;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoDuplicate --
- * Create a new transformation identical to the model t.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnTransfoDuplicate(ZnTransfo *t)
-{
- ZnTransfo *nt;
-
- nt = (ZnTransfo *) ZnMalloc(sizeof(ZnTransfo));
- if (t) {
- *nt = *t;
- }
- else {
- ZnTransfoSetIdentity(nt);
- }
-
- return nt;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoFree --
- * Delete a transformation and free its memory.
- *
- *************************************************************************
- */
-void
-ZnTransfoFree(ZnTransfo *t)
-{
- ZnFree(t);
-}
-
-
-/*
- *************************************************************************
- *
- * ZnPrintTransfo --
- * Print the transfo matrix on stdout.
- *
- *************************************************************************
- */
-void
-ZnPrintTransfo(ZnTransfo *t)
-{
- /*
- * sx 0 cos(rot) sin(rot) 1 tan(skewy) 1 0
- * 0 sy -sin(rot) cos(rot) tan(skewx) 1 0 1
- * 0 0 0 0 0 0 tx ty
- */
- if (t) {
- printf("(%5g %5g\n %5g %5g\n %5g %5g)\n",
- t->_[0][0], t->_[0][1],
- t->_[1][0], t->_[1][1],
- t->_[2][0], t->_[2][1]);
- }
- else {
- printf("(%5g %5g\n %5g %5g\n %5g %5g)\n",
- 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
- }
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoIsIdentity --
- * Tell if the given transfo is (close to) identity.
- *
- *************************************************************************
- */
-ZnBool
-ZnTransfoIsIdentity(ZnTransfo *t)
-{
- ZnReal tmp;
- ZnBool res = False;
-
- tmp = t->_[0][0] - 1.0;
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- tmp = t->_[1][1] - 1.0;
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- tmp = t->_[0][1];
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- tmp = t->_[1][0];
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- tmp = t->_[2][0];
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- tmp = t->_[2][1];
- res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
- return res;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoSetIdentity --
- * Initialize the given transfo to identity.
- *
- *************************************************************************
- */
-void
-ZnTransfoSetIdentity(ZnTransfo *t)
-{
- t->_[0][0] = 1;
- t->_[0][1] = 0;
- t->_[1][0] = 0;
- t->_[1][1] = 1;
- t->_[2][0] = 0;
- t->_[2][1] = 0;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoCompose --
- * Combine two transformations t1 and t2 by post-concatenation.
- * Returns the resulting transformation.
- * t2 can be NULL, meaning identity transform. This is used in
- * the toolkit to optimize some cases.
- *
- * All the parameters must be distincts transforms.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnTransfoCompose(ZnTransfo *res,
- ZnTransfo *t1,
- ZnTransfo *t2)
-{
- if ((t1 != NULL) && (t2 != NULL)) {
- register float tmp;
-
- tmp = t1->_[0][0];
- res->_[0][0] = tmp*t2->_[0][0] + t1->_[0][1]*t2->_[1][0];
- res->_[0][1] = tmp*t2->_[0][1] + t1->_[0][1]*t2->_[1][1];
- tmp = t1->_[1][0];
- res->_[1][0] = tmp*t2->_[0][0] + t1->_[1][1]*t2->_[1][0];
- res->_[1][1] = tmp*t2->_[0][1] + t1->_[1][1]*t2->_[1][1];
- tmp = t1->_[2][0];
- res->_[2][0] = tmp*t2->_[0][0] + t1->_[2][1]*t2->_[1][0] + t2->_[2][0];
- res->_[2][1] = tmp*t2->_[0][1] + t1->_[2][1]*t2->_[1][1] + t2->_[2][1];
- }
- else if (t1 == NULL) {
- if (res != t2) {
- *res = *t2;
- }
- }
- else if (t2 == NULL) {
- if (res != t2) {
- *res = *t1;
- }
- }
- else {
- ZnTransfoSetIdentity(res);
- }
-
- return res;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoInvert --
- * Compute the inverse of the given matrix and return it. This
- * function makes the assumption that the matrix is affine to
- * optimize the job. Do not give it a general matrix, this will
- * fail. This code is from Graphics Gems II. Anyway an affine
- * matrix is always invertible for affine matrices form a sub
- * group of the non-singular matrices.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnTransfoInvert(ZnTransfo *t,
- ZnTransfo *inv)
-{
- float pos, neg, temp, det_l;
-
- if (t == NULL) {
- ZnTransfoSetIdentity(inv);
- return inv;
- }
-
- /*
- * Compute the determinant of the upper left 2x2 sub matrix to see
- * if it is singular.
- */
- pos = neg = 0.0;
- temp = t->_[0][0] * t->_[1][1];
- if (temp >= 0.0) {
- pos += temp;
- }
- else {
- neg += temp;
- }
- temp = - t->_[0][1] * t->_[1][0];
- if (temp >= 0.0) {
- pos += temp;
- }
- else {
- neg += temp;
- }
- det_l = pos + neg;
- temp = det_l / (pos - neg); /* Why divide by (pos - neg) ?? */
-
- if (ABS(temp) < PRECISION_LIMIT) {
- ZnWarning("ZnTransfoInvert : singular matrix\n");
- return NULL;
- }
-
- det_l = 1 / det_l;
- inv->_[0][0] = t->_[1][1] * det_l;
- inv->_[0][1] = - t->_[0][1] * det_l;
- inv->_[1][0] = - t->_[1][0] * det_l;
- inv->_[1][1] = t->_[0][0] * det_l;
- /*
- * The code below is equivalent to:
- * inv->_[2][0] = (t->_[1][0] * t->_[2][1] - t->_[1][1] * t->_[2][0]) * det_l;
- * inv->_[2][1] = - (t->_[0][0] * t->_[2][1] - t->_[0][1] * t->_[2][0]) * det_l;
- *
- * with some operations factored (already computed) to increase speed.
- */
- inv->_[2][0] = - (inv->_[0][0] * t->_[2][0] + inv->_[1][0] * t->_[2][1]);
- inv->_[2][1] = - (inv->_[0][1] * t->_[2][0] + inv->_[1][1] * t->_[2][1]);
-
- return inv;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoDecompose --
- * Decompose an affine matrix into translation, scale, skew and
- * rotation. The different values are stored in the locations
- * pointed to by the pointer parameters. If some values are not
- * needed a NULL pointer can be given instead. The resulting skew
- * shews x coordinate when y change.
- * This code is taken from Graphics Gems II.
- *
- *************************************************************************
- */
-void
-ZnTransfoDecompose(ZnTransfo *t,
- ZnPoint *scale,
- ZnPoint *trans,
- ZnReal *rotation,
- ZnReal *skewxy)
-{
- ZnTransfo local;
- float skew, len, rot, det;
-
- if (t == NULL) {
- /* Identity transform */
- if (scale) {
- scale->x = 1.0;
- scale->y = 1.0;
- }
- if (trans) {
- trans->x = 0.0;
- trans->y = 0.0;
- }
- if (rotation) {
- *rotation = 0.0;
- }
- if (skewxy) {
- *skewxy = 0.0;
- }
- //printf("Transfo is identity\n");
- return;
- }
-
- det = (t->_[0][0]*t->_[1][1] - t->_[0][1]*t->_[1][0]);
- if (ABS(det) < PRECISION_LIMIT) {
- ZnWarning("ZnTransfoDecompose : singular matrix\n");
- return;
- }
-
- local = *t;
- //ZnPrintTransfo(&local);
- /* Get translation part if needed */
- if (trans) {
- trans->x = ABS(local._[2][0]) < PRECISION_LIMIT ? 0 : local._[2][0];
- trans->y = ABS(local._[2][1]) < PRECISION_LIMIT ? 0 : local._[2][1];
- }
- if (!scale && !skewxy && !rotation) {
- return;
- }
-
- /* Get scale and skew */
- len = (float) sqrt(local._[0][0]*local._[0][0] +
- local._[0][1]*local._[0][1]); /* Get x scale from 1st row */
- if (scale) {
- scale->x = len < PRECISION_LIMIT ? 0.0 : len;
- }
- local._[0][0] /= len; /* Normalize 1st row */
- local._[0][1] /= len;
- skew = (local._[0][0]*local._[1][0] +
- local._[0][1]*local._[1][1]); /* Skew is dot product of 1st row & 2nd row */
- /* Make the 2nd row orthogonal to the 1st row
- * by linear combinaison:
- * row1.x = row1.x + row0.x*-skew &
- * row1.y = row1.y + row0.y*-skew
- */
- local._[1][0] -= local._[0][0]*skew;
- local._[1][1] -= local._[0][1]*skew;
- len = (float) sqrt(local._[1][0]*local._[1][0] +
- local._[1][1]*local._[1][1]); /* Get y scale from 2nd row */
- if (scale) {
- scale->y = len < PRECISION_LIMIT ? 0.0 : len;
- }
-
- if (!skewxy && !rotation) {
- return;
- }
-
- local._[1][0] /= len; /* Normalize 2nd row */
- local._[1][1] /= len;
- skew /= len;
- if (skewxy) {
- *skewxy = ABS(skew) < PRECISION_LIMIT ? 0.0 : skew;
- //printf("skew %f\n", *skewxy);
- }
-
- if (!rotation) {
- return;
- }
-
- //printf("Matrix after scale & skew extracted\n");
- //ZnPrintTransfo(&local);
- /* Get rotation */
- /* Check for a coordinate system flip. If det of upper-left 2x2
- * is -1, there is a reflection. If the rotation is < 180° negate
- * the y scale. If the rotation is > 180° then negate the x scale
- * and report a rotation between 0 and 180°. This dissymetry is
- * the result of computing (z) rotation from the first row (x component
- * of the axis system basis).
- */
- det = (local._[0][0]*local._[1][1]- local._[0][1]*local._[1][0]);
-
- rot = (float) atan2(local._[0][1], local._[0][0]);
- if (rot < 0) {
- rot = (2 * (float) M_PI) + rot;
- }
- rot = rot < PRECISION_LIMIT ? 0 : rot;
- if (rot >= M_PI) {
- /*rot -= M_PI; Why that, I'll have to check Graphic Gems ??? */
- if (scale && det < 0) {
- scale->x *= -1;
- }
- }
- else if (scale && det < 0) {
- scale->y *= -1;
- }
-
- //printf("scalex %f\n", scale->x);
- //printf("scaley %f\n", scale->y);
- //printf("rotation %f\n", rot*180.0/3.1415);
-
- if (rotation) {
- *rotation = rot;
- }
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoEqual --
- * Return True if t1 and t2 are equal (i.e they have the same
- * rotation, skew scales and translations). If include_translation
- * is True the translations are considered in the test.
- *
- *************************************************************************
- */
-ZnBool
-ZnTransfoEqual(ZnTransfo *t1,
- ZnTransfo *t2,
- ZnBool include_translation)
-{
- if (include_translation) {
- return (t1->_[0][0] == t2->_[0][0] &&
- t1->_[0][1] == t2->_[0][1] &&
- t1->_[1][0] == t2->_[1][0] &&
- t1->_[1][1] == t2->_[1][1] &&
- t1->_[2][0] == t2->_[2][0] &&
- t1->_[2][1] == t2->_[2][1]);
- }
- else {
- return (t1->_[0][0] == t2->_[0][0] &&
- t1->_[0][1] == t2->_[0][1] &&
- t1->_[1][0] == t2->_[1][0] &&
- t1->_[1][1] == t2->_[1][1]);
- }
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoHasSkew --
- * Return True if t has a skew factor in x or y or describe a
- * rotation or both.
- *
- *************************************************************************
- */
-ZnBool
-ZnTransfoHasSkew(ZnTransfo *t)
-{
- return t->_[0][1] != 0.0 || t->_[1][0] != 0.0;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransfoIsTranslation --
- * Return True if t is a pure translation.
- *
- *************************************************************************
- */
-ZnBool
-ZnTransfoIsTranslation(ZnTransfo *t)
-{
- if (!t) {
- return True;
- }
- return (t->_[0][0] == 1.0 &&
- t->_[0][1] == 0.0 &&
- t->_[1][0] == 0.0 &&
- t->_[1][1] == 1.0);
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransformPoint --
- * Apply the transformation to the point. The point is
- * modified and returned as the value of the function.
- * It is safe for p and xp to be the same point (structure).
- * A NULL transformation means identity. This is only used
- * in the toolkit to optimize some cases. It should never
- * happen in user code.
- *
- *************************************************************************
- */
-ZnPoint *
-ZnTransformPoint(ZnTransfo *t,
- register ZnPoint *p,
- ZnPoint *xp)
-{
- if (t == NULL) {
- xp->x = p->x;
- xp->y = p->y;
- }
- else {
- ZnReal a;
- a = t->_[0][0]*p->x + t->_[1][0]*p->y + t->_[2][0];
- xp->y = t->_[0][1]*p->x + t->_[1][1]*p->y + t->_[2][1];
- xp->x = a;
- }
- return xp;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTransformPoints --
- * Apply the transformation to the points in p returning points in xp.
- * It is safe for p and xp to be the same array of ponits.
- * The number of points is in num.
- * A NULL transformation means identity. This is only used
- * in the toolkit to optimize some cases. It should never
- * happen in user code.
- *
- *************************************************************************
- */
-void
-ZnTransformPoints(ZnTransfo *t,
- ZnPoint *p,
- ZnPoint *xp,
- unsigned int num)
-{
- if (t == NULL) {
- memcpy(xp, p, sizeof(ZnPoint)*num);
- }
- else {
- unsigned int i;
-
- for (i = 0; i < num; i++) {
- ZnReal a;
- a = t->_[0][0]*p[i].x + t->_[1][0]*p[i].y + t->_[2][0];
- xp[i].y = t->_[0][1]*p[i].x + t->_[1][1]*p[i].y + t->_[2][1];
- xp[i].x = a;
- }
- }
-}
-
-
-/*
- *************************************************************************
- *
- * ZnTranslate --
- * Translate the given transformation by delta_x, delta_y. Returns
- * the resulting transformation. If abs is true, delta_x and
- * delta_y are used to set the translation instead of adding deltas.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnTranslate(ZnTransfo *t,
- ZnReal delta_x,
- ZnReal delta_y,
- ZnBool abs)
-{
- if (abs) {
- t->_[2][0] = (float) delta_x;
- t->_[2][1] = (float) delta_y;
- }
- else {
- t->_[2][0] = t->_[2][0] + (float) delta_x;
- t->_[2][1] = t->_[2][1] + (float) delta_y;
- }
-
- return t;
-}
-
-/*
- *************************************************************************
- *
- * ZnScale --
- * Scale the given transformation by scale_x, scale_y. Returns the
- * resulting transformation.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnScale(ZnTransfo *t,
- ZnReal scale_x,
- ZnReal scale_y)
-{
- t->_[0][0] = t->_[0][0] * (float) scale_x;
- t->_[0][1] = t->_[0][1] * (float) scale_y;
- t->_[1][0] = t->_[1][0] * (float) scale_x;
- t->_[1][1] = t->_[1][1] * (float) scale_y;
- t->_[2][0] = t->_[2][0] * (float) scale_x;
- t->_[2][1] = t->_[2][1] * (float) scale_y;
-
- return t;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnRotateRad --
- * Rotate the given transformation by angle radians
- * counter-clockwise around the origin. Returns the resulting
- * transformation.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnRotateRad(ZnTransfo *t,
- ZnReal angle)
-{
- float c = (float) cos(angle);
- float s = (float) sin(angle);
- float tmp;
-
- tmp = t->_[0][0];
- t->_[0][0] = tmp*c - t->_[0][1]*s;
- t->_[0][1] = tmp*s + t->_[0][1]*c;
- tmp = t->_[1][0];
- t->_[1][0] = tmp*c - t->_[1][1]*s;
- t->_[1][1] = tmp*s + t->_[1][1]*c;
- tmp = t->_[2][0];
- t->_[2][0] = tmp*c - t->_[2][1]*s;
- t->_[2][1] = tmp*s + t->_[2][1]*c;
-
- return t;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnRotateDeg --
- * Rotate the given transformation by angle degrees
- * counter-clockwise around the origin. Returns the resulting
- * transformation.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnRotateDeg(ZnTransfo *t,
- ZnReal angle)
-{
- return ZnRotateRad(t, ZnDegRad(angle));
-}
-
-
-/*
- *************************************************************************
- *
- * ZnSkewRad --
- * Skew the given transformation by x_angle and y_angle radians
- * counter-clockwise around the origin. Returns the resulting
- * transformation.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnSkewRad(ZnTransfo *t,
- ZnReal skew_x,
- ZnReal skew_y)
-{
- float sx = (float) tan(skew_x);
- float sy = (float) tan(skew_y);
- float tmp;
-
- tmp = t->_[0][0];
- t->_[0][0] = tmp + t->_[0][1]*sx;
- t->_[0][1] = tmp*sy + t->_[0][1];
- tmp = t->_[1][0];
- t->_[1][0] = tmp + t->_[1][1]*sx;
- t->_[1][1] = tmp*sy + t->_[1][1];
- tmp = t->_[2][0];
- t->_[2][0] = tmp + t->_[2][1]*sx;
- t->_[2][1] = tmp*sy + t->_[2][1];
-
- return t;
-}
-
-
-/*
- *************************************************************************
- *
- * ZnSkewDeg --
- * Skew the given transformation by x_angle and y_angle degrees
- * counter-clockwise around the origin. Returns the resulting
- * transformation.
- *
- *************************************************************************
- */
-ZnTransfo *
-ZnSkewDeg(ZnTransfo *t,
- ZnReal skew_x,
- ZnReal skew_y)
-{
- return ZnSkewRad(t, ZnDegRad(skew_x), ZnDegRad(skew_y));
-}
-
-
-#undef PRECISION_LIMIT
-
-
diff --git a/generic/Transfo.h b/generic/Transfo.h
deleted file mode 100644
index ab28d6f..0000000
--- a/generic/Transfo.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Transfo.h -- Header for common geometric routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Transfo_h
-#define _Transfo_h
-
-
-#include "Types.h"
-
-#include <math.h>
-#include <limits.h>
-
-
-/*
- * First subscript is matrix row, second is matrix column.
- * So a[0][1] is upper right corner of matrix a and a[2][0]
- * is lower left corner.
- */
-typedef struct _ZnTransfo {
- float _[3][2];
-} ZnTransfo;
-
-
-ZnTransfo *
-ZnTransfoNew(void);
-ZnTransfo *
-ZnTransfoDuplicate(ZnTransfo *t);
-void
-ZnTransfoFree(ZnTransfo *t);
-void
-ZnPrintTransfo(ZnTransfo *t);
-void
-ZnTransfoSetIdentity(ZnTransfo *t);
-ZnBool
-ZnTransfoIsIdentity(ZnTransfo *t);
-ZnTransfo *
-ZnTransfoCompose(ZnTransfo *res,
- ZnTransfo *t1,
- ZnTransfo *t2);
-ZnTransfo *
-ZnTransfoInvert(ZnTransfo *t,
- ZnTransfo *inv);
-void
-ZnTransfoDecompose(ZnTransfo *t,
- ZnPoint *scale,
- ZnPoint *trans,
- ZnReal *rotation,
- ZnReal *skewxy);
-ZnBool
-ZnTransfoEqual(ZnTransfo *t1,
- ZnTransfo *t2,
- ZnBool include_translation);
-ZnBool
-ZnTransfoHasSkew(ZnTransfo *t);
-ZnBool
-ZnTransfoIsTranslation(ZnTransfo *t);
-ZnPoint *
-ZnTransformPoint(ZnTransfo *t,
- ZnPoint *p,
- ZnPoint *xp);
-void
-ZnTransformPoints(ZnTransfo *t,
- ZnPoint *p,
- ZnPoint *xp,
- unsigned int num);
-ZnTransfo *
-ZnTranslate(ZnTransfo *t,
- ZnReal delta_x,
- ZnReal delta_y,
- ZnBool abs);
-ZnTransfo *
-ZnScale(ZnTransfo *t,
- ZnReal scale_x,
- ZnReal scale_y);
-ZnTransfo *
-ZnRotateRad(ZnTransfo *t,
- ZnReal angle);
-ZnTransfo *
-ZnRotateDeg(ZnTransfo *t,
- ZnReal angle);
-ZnTransfo *
-ZnSkewRad(ZnTransfo *t,
- ZnReal skew_x,
- ZnReal skew_y);
-ZnTransfo *
-ZnSkewDeg(ZnTransfo *t,
- ZnReal skew_x,
- ZnReal skew_y);
-
-#endif /* _Transfo_h */
diff --git a/generic/Triangles.c b/generic/Triangles.c
deleted file mode 100644
index 1565b5b..0000000
--- a/generic/Triangles.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Triangles.c -- Implementation of Triangle fan/strips item.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Tue Dec 11 10:52:01 2001
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Draw.h"
-#include "Item.h"
-#include "Geo.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-#include "Image.h"
-#include "Color.h"
-
-#include <ctype.h>
-
-
-static const char rcsid[] = "$Id";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-/*
- * Bit offset of flags.
- */
-#define FAN_BIT 1<<0 /* Tell if the triangles are arranged in fan or strips. */
-
-
-/*
- **********************************************************************************
- *
- * Specific Triangles item record
- *
- **********************************************************************************
- */
-typedef struct _TrianglesItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnList points;
- unsigned short flags;
- ZnList colors;
-
- /* Private data */
- ZnTriStrip dev_points;
-} TrianglesItemStruct, *TrianglesItem;
-
-
-static ZnAttrConfig tr_attrs[] = {
- { ZN_CONFIG_GRADIENT_LIST, "-colors", NULL,
- Tk_Offset(TrianglesItemStruct, colors), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-fan", NULL,
- Tk_Offset(TrianglesItemStruct, flags), FAN_BIT, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(TrianglesItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(TrianglesItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(TrianglesItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(TrianglesItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- ZnWInfo *wi = item->wi;
- TrianglesItem tr = (TrianglesItem) item;
- unsigned int num_points;
- ZnPoint *points;
- ZnList l;
- ZnGradient **grads;
-
- tr->dev_points.num_strips = 0;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 1;
- tr->points = NULL;
-
- if (*argc < 1) {
- Tcl_AppendResult(wi->interp, " triangles coords expected", NULL);
- return TCL_ERROR;
- }
- if (ZnParseCoordList(wi, (*args)[0], &points,
- NULL, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (num_points < 3) {
- Tcl_AppendResult(wi->interp, " malformed triangles coords, need at least 3 points", NULL);
- return TCL_ERROR;
- }
-
- tr->points = ZnListNew(num_points, sizeof(ZnPoint));
- l = ZnListFromArray(points, num_points, sizeof(ZnPoint));
- ZnListAppend(tr->points, l);
- ZnListFree(l);
- (*args)++;
- (*argc)--;
-
- CLEAR(tr->flags, FAN_BIT);
- tr->colors = ZnListNew(1, sizeof(ZnGradient *));
- ZnListAssertSize(tr->colors, 1);
- grads = ZnListArray(tr->colors);
- *grads = ZnGetGradientByValue(wi->fore_color);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- TrianglesItem tr = (TrianglesItem) item;
-
- if (tr->colors) {
- int i, num_grads;
- ZnGradient **grads;
-
- tr->colors = ZnListDuplicate(tr->colors);
- num_grads = ZnListSize(tr->colors);
- grads = ZnListArray(tr->colors);
- for (i = 0; i < num_grads; i++, grads++) {
- *grads = ZnGetGradientByValue(*grads);
- }
- }
-
- tr->dev_points.num_strips = 0;
- tr->points = ZnListDuplicate(tr->points);
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- TrianglesItem tr = (TrianglesItem) item;
-
- ZnListFree(tr->points);
- if (tr->dev_points.num_strips) {
- ZnFree(tr->dev_points.strips->points);
- }
- if (tr->colors) {
- int i, num_grads;
- ZnGradient **grads;
-
- num_grads = ZnListSize(tr->colors);
- grads = ZnListArray(tr->colors);
- for (i = 0; i < num_grads; i++, grads++) {
- ZnFreeGradient(*grads);
- }
- ZnListFree(tr->colors);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- int status = TCL_OK;
-
- status = ZnConfigureAttributes(item->wi, item, item, tr_attrs, argc, argv, flags);
-
- return status;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, tr_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- TrianglesItem tr = (TrianglesItem) item;
- ZnPoint *points;
- ZnPoint *dev_points;
- unsigned int num_points;
-
- ZnResetBBox(&item->item_bounding_box);
-
- points = (ZnPoint *) ZnListArray(tr->points);
- num_points = ZnListSize(tr->points);
-
- /*
- * Allocate space for devices coordinates
- */
- if (tr->dev_points.num_strips == 0) {
- dev_points = ZnMalloc(num_points * sizeof(ZnPoint));
- }
- else {
- dev_points = tr->dev_points.strips->points;
- if (tr->dev_points.strips->num_points < num_points) {
- dev_points = ZnRealloc(dev_points, num_points * sizeof(ZnPoint));
- }
- }
- ZnTriStrip1(&tr->dev_points, dev_points, num_points,
- ISSET(tr->flags, FAN_BIT));
-
- /*
- * Compute device coordinates.
- */
- ZnTransformPoints(wi->current_transfo, points, dev_points, num_points);
-
- /*
- * Compute the bounding box.
- */
- ZnAddPointsToBBox(&item->item_bounding_box, dev_points, num_points);
-
- /*
- * Expand 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(ZnItem item,
- ZnToArea ta)
-{
- TrianglesItem tr = (TrianglesItem) item;
- ZnPoint *points;
- unsigned int i, num_points;
- int result=-1, result2;
- ZnBBox *area = ta->area;
-
- if (tr->dev_points.num_strips == 0) {
- return -1;
- }
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_points;
-
- if (ISCLEAR(tr->flags, FAN_BIT)) {
- result = ZnPolygonInBBox(points, 3, area, NULL);
- if (result == 0) {
- return 0;
- }
- points++;
- for (i = 0; i < num_points-3; i++, points++) {
- result2 = ZnPolygonInBBox(points, 3, area, NULL);
- if (result2 != result) {
- return 0;
- }
- }
- }
- else {
- ZnPoint tri[3];
-
- tri[0] = points[0];
- tri[1] = points[1];
- tri[2] = points[2];
- result = ZnPolygonInBBox(points, num_points, area, NULL);
- if (result == 0) {
- return 0;
- }
- points += 3;
- for (i = 0; i < num_points-3; i++, points++) {
- tri[1] = tri[2];
- tri[2] = *points;
- result2 = ZnPolygonInBBox(points, num_points, area, NULL);
- if (result2 != result) {
- return 0;
- }
- }
- }
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TrianglesItem tr = (TrianglesItem) item;
- unsigned int i, num_points, last_color_index;
- ZnPoint *points;
- ZnGradient **grads;
-
- if (tr->dev_points.num_strips == 0) {
- return;
- }
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_points;
-
- grads = ZnListArray(tr->colors);
- last_color_index = ZnListSize(tr->colors)-1;
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
-
- if (ISCLEAR(tr->flags, FAN_BIT)) {
- XPoint *xpoints;
- ZnListAssertSize(ZnWorkXPoints, num_points);
- xpoints = ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = ZnNearestInt(points[i].x);
- xpoints[i].y = ZnNearestInt(points[i].y);
- }
- for (i = 0; i < num_points-2; i++, xpoints++) {
- if (i <= last_color_index) {
- XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(grads[i], 0.0));
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, 3, Convex, CoordModeOrigin);
- }
- }
- else {
- XPoint tri[3];
-
- tri[0].x = ZnNearestInt(points[0].x);
- tri[0].y = ZnNearestInt(points[0].y);
- tri[1].x = ZnNearestInt(points[1].x);
- tri[1].y = ZnNearestInt(points[1].y);
- tri[2].x = ZnNearestInt(points[2].x);
- tri[2].y = ZnNearestInt(points[2].y);
- points += 3;
- for (i = 0; i < num_points-2; i++, points++) {
- if (i <= last_color_index) {
- XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(grads[i], 0.0));
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- tri, 3, Convex, CoordModeOrigin);
- tri[1] = tri[2];
- tri[2].x = ZnNearestInt(points->x);
- tri[2].y = ZnNearestInt(points->y);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Render --
- *
- **********************************************************************************
- */
-#ifdef GL
-static void
-Render(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- TrianglesItem tr = (TrianglesItem) item;
- int i, num_points, last_color_index;
- ZnPoint *points;
- ZnGradient **grads;
- unsigned short alpha;
- XColor *color;
-
- if (tr->dev_points.num_strips == 0) {
- return;
- }
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_points;
-
- grads = ZnListArray(tr->colors);
- last_color_index = ZnListSize(tr->colors)-1;
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (ISCLEAR(tr->flags, FAN_BIT)) {
- glBegin(GL_TRIANGLE_STRIP);
- }
- else {
- glBegin(GL_TRIANGLE_FAN);
- }
-
- for (i = 0; i < num_points; i++, points++) {
- if (i <= last_color_index) {
- color = ZnGetGradientColor(grads[i], 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- glVertex2d(points->x, points->y);
- }
- glEnd();
-}
-#else
-static void
-Render(ZnItem item)
-{
-}
-#endif
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
- item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- TrianglesItem tr = (TrianglesItem) item;
- double dist=1.0e40, new_dist;
- ZnPoint *points, *p = ps->point;
- int i, num_points;
-
- if (tr->dev_points.num_strips == 0) {
- return dist;
- }
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_points;
-
- if (ISCLEAR(tr->flags, FAN_BIT)) {
- for (i = 0; i < num_points-2; i++, points++) {
- new_dist = ZnPolygonToPointDist(points, 3, p);
- if (new_dist <= 0.0) {
- return 0.0;
- }
- if (new_dist < dist) {
- dist = new_dist;
- }
- }
- }
- else {
- ZnPoint tri[3];
-
- tri[0] = points[0];
- tri[1] = points[1];
- tri[2] = points[2];
- for (i = 0; i < num_points-2; i++, points++) {
- new_dist = ZnPolygonToPointDist(tri, 3, p);
- if (new_dist <= 0.0) {
- return 0.0;
- }
- if (new_dist < dist) {
- dist = new_dist;
- }
- tri[1] = tri[2];
- tri[2] = *points;
- }
- }
-
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- TrianglesItem tr = (TrianglesItem) item;
- ZnPoint *points;
- int i, num_points, last_color_index;
- int edge;
- ZnGradient **grads;
- XColor *color = NULL;
- double red, green, blue;
- ZnBBox bbox;
- char path[150];
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_points;
- ZnResetBBox(&bbox);
- ZnAddPointsToBBox(&bbox, points, num_points);
-
- grads = ZnListArray(tr->colors);
- last_color_index = ZnListSize(tr->colors)-1;
-
- Tcl_AppendResult(wi->interp,
- "/ShadingDict <<\n /ShadingType 4\n /ColorSpace /DeviceRGB\n",
- " /DataSource [", NULL);
- for (i = 0; i < num_points; i++) {
- if (i <= last_color_index) {
- color = ZnGetGradientColor(grads[i], 0.0, NULL);
- }
- if (i < 3) {
- edge = 0;
- }
- else if (ISCLEAR(tr->flags, FAN_BIT)) {
- edge = 1;
- }
- else {
- edge = 2;
- }
- red = ((double) (color->red >> 8)) / 255.0;
- green = ((double) (color->green >> 8)) / 255.0;
- blue = ((double) (color->blue >> 8)) / 255.0;
-
- sprintf(path, "%d %.15g %.15g %.4g %.4g %.4g ",
- edge, points[i].x, points[i].y, red, green, blue);
- Tcl_AppendResult(wi->interp, path, NULL);
- }
- Tcl_AppendResult(wi->interp, "]\n>> def\n", NULL);
- Tcl_AppendResult(wi->interp, "<<\n /PatternType 2\n /Shading ShadingDict\n>>\n", NULL);
- Tcl_AppendResult(wi->interp, "matrix identmatrix makepattern setpattern\n", NULL);
- sprintf(path, "%.15g %.15g %.15g %.15g rectfill\n", bbox.orig.x, bbox.orig.y,
- bbox.corner.x - bbox.orig.x, bbox.corner.y - bbox.orig.y);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- * Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- TrianglesItem tr = (TrianglesItem) item;
-
- if (tr->dev_points.num_strips == 0) {
- tristrip->num_strips = 0;
- return True;
- }
-
- ZnTriStrip1(tristrip, tr->dev_points.strips->points,
- tr->dev_points.strips->num_points,
- tr->dev_points.strips[0].fan);
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetContours --
- * Get the external contour(s).
- * Never ever call ZnPolyFree on the poly returned by GetContours.
- *
- **********************************************************************************
- */
-static ZnBool
-GetContours(ZnItem item,
- ZnPoly *poly)
-{
- TrianglesItem tr = (TrianglesItem) item;
- ZnPoint *points;
- unsigned int k, j, num_points;
- int i;
-
- if (tr->dev_points.num_strips == 0) {
- poly->num_contours = 0;
- return True;
- }
-
- num_points = tr->dev_points.strips->num_points;
-
- if (ISCLEAR(tr->flags, FAN_BIT)) {
- ZnListAssertSize(ZnWorkPoints, num_points);
- points = ZnListArray(ZnWorkPoints);
-
- for (k = 1, j = 0; k < num_points; k += 2, j++) {
- points[j] = tr->dev_points.strips->points[k];
- }
- i = num_points - 1;
- if (num_points % 2 == 0) {
- i--;
- }
- for ( ; i >= 0; i -= 2, j++) {
- points[j] = tr->dev_points.strips->points[i];
- }
- ZnPolyContour1(poly, points, num_points, False);
- }
- else {
- ZnPolyContour1(poly, tr->dev_points.strips->points, num_points, False);
- }
- poly->contours[0].cw = !ZnTestCCW(poly->contours[0].points, poly->contours[0].num_points);
- poly->contours[0].controls = NULL;
- return False;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item vertices.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- TrianglesItem tr = (TrianglesItem) item;
- unsigned int num_points, i;
- ZnPoint *points;
-
- if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (cmd == ZN_COORDS_REPLACE_ALL) {
- ZnList tmp;
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need at least 3 points on triangles", NULL);
- return TCL_ERROR;
- }
- tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
- ZnListEmpty(tr->points);
- ZnListAppend(tr->points, tmp);
- ZnListFree(tmp);
- }
- else {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need at least 1 point on triangles", NULL);
- return TCL_ERROR;
- }
- points = ZnListArray(tr->points);
- num_points = ZnListSize(tr->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || ((unsigned int) index >= num_points)) {
- range_err:
- Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
- return TCL_ERROR;
- }
- points[index] = (*pts)[0];
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- points = ZnListArray(tr->points);
- num_points = ZnListSize(tr->points);
- if (cmd == ZN_COORDS_READ_ALL) {
- *num_pts = num_points;
- *pts = points;
- }
- else {
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || ((unsigned int)index >= num_points)) {
- goto range_err;
- }
- *num_pts = 1;
- *pts = &points[index];
- }
- }
- else if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST)) {
- if (cmd == ZN_COORDS_ADD) {
- num_points = ZnListSize(tr->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || ((unsigned int)index >= num_points)) {
- goto range_err;
- }
- for (i = 0; i < *num_pts; i++, index++) {
- ZnListAdd(tr->points, &(*pts)[i], (unsigned int) index);
- }
- }
- else {
- ZnList tmp;
- tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
- ZnListAppend(tr->points, tmp);
- ZnListFree(tmp);
- }
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if (cmd == ZN_COORDS_REMOVE) {
- if (ZnListSize(tr->points) < 4) {
- Tcl_AppendResult(item->wi->interp,
- " triangles should keep at least 3 points", NULL);
- return TCL_ERROR;
- }
- points = ZnListArray(tr->points);
- num_points = ZnListSize(tr->points);
- if (index < 0) {
- index += num_points;
- }
- if ((index < 0) || ((unsigned int)index >= num_points)) {
- goto range_err;
- }
- ZnListDelete(tr->points, (unsigned int) index);
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
-
- return TCL_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(ZnItem item,
- ZnPoint *p,
- int *contour,
- int *vertex,
- int *o_vertex)
-{
- TrianglesItem tr = (TrianglesItem) item;
- int i, k, num_points;
- ZnPoint *points;
- ZnReal dist=1.0e40, new_dist, dist2;
-
- *contour = *vertex = *o_vertex = -1;
-
- points = tr->dev_points.strips->points;
- num_points = tr->dev_points.strips->num_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 = ZnLineToPointDist(&points[*vertex], &points[i], p, NULL);
- k = ((unsigned)(*vertex-1)) % num_points;
- dist2 = ZnLineToPointDist(&points[*vertex], &points[k], p, NULL);
- if (dist2 < new_dist) {
- *o_vertex = k;
- }
- else {
- *o_vertex = i;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct TRIANGLES_ITEM_CLASS = {
- "triangles",
- sizeof(TrianglesItemStruct),
- tr_attrs,
- 0, /* num_parts */
- 0, /* flags */
- -1,
- 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 ZnTriangles = (ZnItemClassId) &TRIANGLES_ITEM_CLASS;
diff --git a/generic/Types.h b/generic/Types.h
deleted file mode 100644
index d52128c..0000000
--- a/generic/Types.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Types.h -- Some types and macros used by the Zinc widget.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Mon Feb 1 12:13:24 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _Types_h
-#define _Types_h
-
-
-#ifdef _WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# undef WIN32_LEAN_AND_MEAN
-# if defined(_MSC_VER)
-# define DllEntryPoint DllMain
-# endif
-// Suppress complaints about deprecated standard C functions
-// like strcpy and strcat
-# ifndef __GNUC__
-# pragma warning(disable : 4996)
-# endif
-#endif
-
-#ifdef GL
-# ifdef _WIN32
-# include <GL/gl.h>
-# else
-# include <GL/glx.h>
-# endif
-#endif
-
-#define NEED_REAL_STDIO
-
-#include <tk.h>
-#include <tkInt.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#ifdef PTK
-# include <tkPort.h>
-# include <tkImgPhoto.h>
-# include <tkVMacro.h>
-# ifndef PTK_800
-# define Arg Tcl_Obj *
-# endif
-#else
-# include <tkDecls.h>
-# include <tkIntDecls.h>
-#endif
-#include <stdio.h>
-
-
-/* This EXTERN declaration is needed for Tcl < 8.0.3 */
-#ifndef EXTERN
-# ifdef __cplusplus
-# define EXTERN extern "C" TCL_STORAGE_CLASS
-# else
-# define EXTERN extern TCL_STORAGE_CLASS
-# endif
-#endif
-
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-
-typedef double ZnReal; /* Keep it a double for GL and Tcl. */
-typedef int ZnBool; /* Keep it an int to keep Tk happy */
-typedef ZnReal ZnPos;
-typedef ZnReal ZnDim;
-typedef void *ZnPtr;
-
-
-#define ZnPixel(color) ((color)->pixel)
-#define ZnMalloc(size) ((void *)ckalloc(size))
-#define ZnFree(ptr) (ckfree((char *)(ptr)))
-#define ZnRealloc(ptr, size) ((void *)ckrealloc((void *)(ptr), size))
-#define ZnWarning(msg) (fprintf(stderr, "%s", (msg)))
-
-#define ZnUnspecifiedImage None
-#define ZnUnspecifiedColor NULL
-
-#ifndef TCL_INTEGER_SPACE
-# define TCL_INTEGER_SPACE 24
-#endif
-
-#ifdef PTK_800
-/*
- * Macros for Tk8.4/perl/Tk utf compatibility
- */
-#define Tcl_NumUtfChars(str, len) (((len)<0)?((int)strlen(str)):(len))
-#define Tcl_UtfAtIndex(str, index) (&(str)[(index)])
-#define Tcl_GetString(str) (Tcl_GetStringFromObj(str, NULL))
-
-#define Tk_GetScrollInfoObj(interp, argc, args, fract, count) \
-Tk_GetScrollInfo(interp, argc, (Tcl_Obj **) args, fract, count)
-#endif
-
-/*
- * Macros for Windows compatibility
- */
-#ifdef _WIN32
-# include <tkWinInt.h>
-
-# ifndef _MSC_VER
-# undef EXTERN
-# define EXTERN
-# endif
-# ifdef TCL_STORAGE_CLASS
-# undef TCL_STORAGE_CLASS
-# endif
-# ifdef BUILD_Tkzinc
-# define TCL_STORAGE_CLASS DLLEXPORT
-# else
-# define TCL_STORAGE_CLASS DLLIMPORT
-# endif
-
-# ifndef __GNUC__
-// Okay, Those Xlib functions will bring inconsistancy errors
-// as they are already provided by Tk portability layer, shut them up.
-# pragma warning(disable : 4273)
-# endif
-#undef XFillRectangle
-void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
- unsigned int width, unsigned int height);
-# undef XFillRectangles
-void XFillRectangles(Display *display, Drawable d, GC gc,
- XRectangle* rectangles, int nrectangles);
-# undef XFillArc
-void XFillArc(Display *display, Drawable d, GC gc, int x, int y, unsigned int width,
- unsigned int height, int start, int extent);
-# undef XFillPolygon
-void XFillPolygon(Display *display, Drawable d, GC gc, XPoint *points, int npoints,
- int shape, int mode);
-# undef XDrawRectangle
-void XDrawRectangle(Display *display, Drawable d, GC gc, int x, int y,
- unsigned int width, unsigned int height);
-# undef XDrawArc
-void XDrawArc(Display *display, Drawable d, GC gc, int x, int y,
- unsigned int width, unsigned int height, int start, int extent);
-# undef XDrawLine
-void XDrawLine(Display *display, Drawable d, GC gc, int x1, int y1, int x2, int y2);
-# undef XDrawLines
-void XDrawLines(Display *display, Drawable d, GC gc, XPoint* points,
- int npoints, int mode);
-
-ZnBool ZnPointInRegion(TkRegion reg, int x, int y);
-void ZnUnionRegion(TkRegion sra, TkRegion srb,
- TkRegion dr_return);
-void ZnOffsetRegion(TkRegion reg, int dx, int dy);
-TkRegion ZnPolygonRegion(XPoint *points, int n,
- int fill_rule);
-# ifdef GL
-# define ZnGLContext HGLRC
-# define ZnGLWaitX()
-# define ZnGLWaitGL()
-# define ZN_GL_LINE_WIDTH_RANGE GL_LINE_WIDTH_RANGE
-# define ZN_GL_POINT_SIZE_RANGE GL_POINT_SIZE_RANGE
-# endif
-#else /* !_WIN32 */
-# define ZnPointInRegion(reg, x, y) \
- XPointInRegion((Region) reg, x, y)
-# define ZnPolygonRegion(points, npoints, fillrule) \
- ((TkRegion) XPolygonRegion(points, npoints, fillrule))
-# define ZnUnionRegion(sra, srb, rreturn) \
- XUnionRegion((Region) sra, (Region) srb, (Region) rreturn)
-# define ZnOffsetRegion(reg, dx, dy) \
- XOffsetRegion((Region) reg, dx, dy)
-# ifdef GL
-# define ZnGLContext GLXContext
-# define ZnGLWaitX() \
- glXWaitX()
-# define ZnGLWaitGL() \
- glXWaitGL()
-# define ZN_GL_LINE_WIDTH_RANGE GL_SMOOTH_LINE_WIDTH_RANGE
-# define ZN_GL_POINT_SIZE_RANGE GL_SMOOTH_POINT_SIZE_RANGE
-# endif
-#endif
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _Types_h */
diff --git a/generic/WidgetInfo.h b/generic/WidgetInfo.h
deleted file mode 100644
index 8483dca..0000000
--- a/generic/WidgetInfo.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * WidgetInfo.h -- Zinc Widget record.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Mon Feb 1 12:13:24 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _WidgetInfo_h
-#define _WidgetInfo_h
-
-
-#include "Item.h"
-#include "Transfo.h"
-#include "Types.h"
-#ifndef _WIN32
-#include "perfos.h"
-#endif
-#include "Color.h"
-
-
-#define ZN_NUM_ALPHA_STEPS 16
-
-/*
- * Constants for flags
- */
-#define ZN_REPICK_IN_PROGRESS (1<<0)
-#define ZN_GRABBED_ITEM (1<<1)
-#define ZN_GRABBED_PART (1<<2)
-#define ZN_REALIZED (1<<3)
-#define ZN_INTERNAL_NEED_REPICK (1<<4)
-#define ZN_UPDATE_SCROLLBARS (1<<5) /* If set, the scrollbars must be updated. */
-#define ZN_GOT_FOCUS (1<<6) /* Set means that the widget has the input focus. */
-#define ZN_UPDATE_PENDING (1<<7) /* Set means there is a pending graphic update. */
-#define ZN_HAS_GL (1<<8) /* Tell if openGL can be used. */
-#define ZN_HAS_X_SHAPE (1<<9) /* Tell if the X shape extension is available. */
-#define ZN_MONITORING (1<<10) /* Set if performance monitoring is on. */
-#define ZN_PRINT_CONFIG (1<<11) /* If set the openGL hardware configuration
- * is printed on startup. */
-#define ZN_CONFIGURE_EVENT (1<<12)
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-
-/*
- * The following structure provides information about the selection and
- * the insertion cursor. It is needed by only a few items, such as
- * those that display text. It is shared by the generic canvas code
- * and the item-specific code, but most of the fields should be written
- * only by the canvas generic code.
- */
-typedef struct _ZnTextInfo {
- ZnGradient *sel_color; /* Background color for selected text.
- * Read-only to items.*/
- ZnItem sel_item; /* Pointer to selected item. ZN_NO_ITEM
- * means that the widget doesn't own the
- * selection. Writable by items. */
- int sel_field;
- int sel_first; /* Index of first selected character.
- * Writable by items. */
- int sel_last; /* Index of last selected character.
- * Writable by items. */
- ZnItem anchor_item; /* Item corresponding to sel_anchor: not
- * necessarily sel_item. Read-only to items. */
- int anchor_field;
- int sel_anchor; /* Fixed end of selection (i.e. "select to"
- * operation will use this as one end of the
- * selection). Writable by items. */
- ZnGradient *insert_color; /* Used to draw vertical bar for insertion
- * cursor. Read-only to items. */
- unsigned int insert_width; /* Total width of insertion cursor. Read-only
- * to items. */
- ZnBool cursor_on; /* True means that an insertion cursor should
- * be displayed in focus_item. Read-only to
- * items.*/
-} ZnTextInfo;
-
-typedef struct _ZnWInfo {
- Tcl_Interp *interp; /* Interpreter associated with widget. */
- Tcl_Command cmd; /* Token for zinc widget command. */
- Tcl_HashTable *id_table; /* Hash table for object ids. */
- Tcl_HashTable *t_table; /* Hash table for transformations. */
- unsigned long obj_id; /* Id for the next new object. */
- int flags;
- Tk_BindingTable binding_table; /* Table of all bindings currently defined
- * for this widget. NULL means that no
- * bindings exist, so the table hasn't been
- * created. Each "object" used for this
- * table is either a Tk_Uid for a tag or
- * the address of an item named by id. */
- int state; /* Last known modifier state. Used to
- * defer picking a new current object
- * while buttons are down. */
- ZnItem current_item; /* Item picked from previous pick sequence */
- ZnItem new_item; /* Item picked from current pick sequence */
- int current_part;
- int new_part;
- ZnItem hot_item;
- ZnItem hot_prev;
- ZnItem focus_item; /* Item that currently has the input focus,
- * or ZN_NO_ITEM if no such item. Read-only to
- * items. */
- int focus_field;
- XEvent pick_event; /* Event used to forge fake events and to do
- * repicks. */
- ZnBBox exposed_area; /* Window area that need to be rexposed.
- * It is distinct from redraw_area which
- * is updated when items are changed. */
- Pixmap alpha_stipples[ZN_NUM_ALPHA_STEPS];
- int border_width;
- int opt_width; /* Window size as stated/reported by the option. */
- int opt_height; /* They are equal to the width/height fields after
- * the actual resize. They may to be equal if
- * the resize is not acknowledged by the geo
- * manager. */
- ZnGradient *relief_grad; /* The gradient describing the border relief
- * colors. */
- ZnReliefStyle relief; /* The border relief. */
-
- /* Tracks global resources */
-#ifdef ATC
- unsigned int track_managed_history_size; /* Size of history for tracks */
- unsigned int track_visible_history_size; /* Size of displayed history */
- ZnReal speed_vector_length; /* How long (in time) are speedvectors*/
- int om_group_id; /* Tell which group contains tracks to be */
- ZnItem om_group; /* processed for anti label overlap. */
-
- /* Maps global resources */
- Tk_Font map_text_font; /* Font for texts in Map items */
-#ifdef GL
- ZnTexFontInfo map_font_tfi; /* Used to preserve the default font from
- * being freed again and again */
-#endif
- Tcl_Obj *map_symbol_obj;
- ZnImage map_distance_symbol; /* Distance marks displayed along Map */
- /* lines. */
- Tcl_Obj *track_symbol_obj;
- ZnImage track_symbol; /* Symbol displayed at track/wp current */
- /* position. */
-#endif
- /* Transformer */
- ZnTransfo *current_transfo;
- ZnList transfo_stack;
- struct _ClipState *current_clip;
- ZnList clip_stack;
-
- /* Others */
- ZnGradient *fore_color; /* Default gradient used in new items */
- ZnGradient *back_color; /* Color of the widget background. */
- ZnGradient *bbox_color; /* Color used to draw bboxes (debug). */
- Tk_Cursor cursor; /* Cursor displayed in zinc window. */
- ZnBool draw_bboxes; /* Draw item's bboxes (debug). */
- ZnBool follow_pointer; /* Process pointer motion events to */
- /* emit enter/leave events. */
- int light_angle;
-
- int pick_aperture; /* size of pick aperture in pixels */
- Tk_Font font; /* Default font used in new items */
-#ifdef GL
- ZnTexFontInfo font_tfi; /* Used to preserve the default font from
- * being freed again and again */
-#endif
- Tcl_Obj *tile_obj;
- ZnImage tile;
-
- /* Zinc private resources */
- int width; /* Actual window dimension. */
- int height;
- int inset; /* Border and highlight width */
-
- /* Graphic variables */
- Display *dpy; /* The display of the widget window. */
- Screen *screen;
- Tk_Window win; /* The window of the widget. */
- Pixmap draw_buffer; /* Pixmap for double buffering */
- ZnBBox damaged_area; /* The current damaged rectangle */
- GC gc;
- ZnBool reshape; /* Use the Shape Extension on the window.*/
- ZnBool full_reshape; /* Use it on the top level window. */
- Window real_top;
- int render;
- unsigned char alpha; /* Current composite group alpha. */
- ZnItem top_group;
-#ifndef PTK_800
- Tk_OptionTable opt_table;
-#endif
-
- /* Text management */
- ZnTextInfo text_info;
- int insert_on_time;
- int insert_off_time;
- Tcl_TimerToken blink_handler;
- char *take_focus;
- int highlight_width; /* Width in pixels of highlight to draw
- * around widget when it has the focus.
- * = 0 means don't draw a highlight. */
- ZnGradient *highlight_bg_color; /* Color for drawing traversal highlight
- * area when highlight is off. */
- ZnGradient *highlight_color; /* Color for drawing traversal highlight.*/
-
- /* Scrollbar management */
- ZnPoint origin; /* Coordinate mapped to the upper left corner
- * of the zinc window. */
-#ifdef PTK
- LangCallback *x_scroll_cmd;
- LangCallback *y_scroll_cmd;
-#else
- Tcl_Obj *x_scroll_cmd; /* Command prefixes for communicating with */
- Tcl_Obj *y_scroll_cmd; /* scrollbars. NULL means no scrollbar.
- * Malloc'ed */
-#endif
- int x_scroll_incr; /* If >0, defines a grid for horiz/vert */
- int y_scroll_incr; /* scrolling. This is the size of the "unit",
- * and the left edge of the screen will always
- * lie on an even unit boundary. */
- int scroll_xo; /* This bbox define the region that is the */
- int scroll_yo; /* 100% area for scrolling (i.e. it determines */
- int scroll_xc; /* the size and location of the sliders on */
- int scroll_yc; /* scrollbars). */
- ZnBool confine; /* When true, it is not possible to scroll the
- * viewing area past the scroll region. */
- Tcl_Obj *region; /* Scroll region option string source of the
- * scroll_region above. */
- Tk_PostscriptInfo ps_info;
-
- /* Perf measurement variables. */
-#ifndef _WIN32
- ZnChrono this_draw_chrono;
- ZnChrono total_draw_chrono;
-#endif
- int num_items;
- int damaged_area_w;
- int damaged_area_h;
- int debug;
-} ZnWInfo;
-
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _WidgetInfo_h */
diff --git a/generic/Window.c b/generic/Window.c
deleted file mode 100644
index a6ac2d7..0000000
--- a/generic/Window.c
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * Window.c -- Implementation of Window item.
- *
- * Authors : Patrick LECOANET
- * Creation date : Fri May 12 11:25:53 2000
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#include "Item.h"
-#include "Geo.h"
-#include "Types.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-/*
- **********************************************************************************
- *
- * Specific Window item record
- *
- **********************************************************************************
- */
-typedef struct _WindowItemStruct {
- ZnItemStruct header;
-
- /* Public data */
- ZnPoint pos;
- Tk_Anchor anchor;
- Tk_Anchor connection_anchor;
- Tk_Window win;
- int width;
- int height;
-
- /* Private data */
- ZnPoint pos_dev;
- int real_width;
- int real_height;
-} WindowItemStruct, *WindowItem;
-
-
-static ZnAttrConfig wind_attrs[] = {
- { ZN_CONFIG_ANCHOR, "-anchor", NULL,
- Tk_Offset(WindowItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composealpha", NULL,
- Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
- ZN_DRAW_FLAG, False },
- { ZN_CONFIG_BOOL, "-composerotation", NULL,
- Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_BOOL, "-composescale", NULL,
- Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
- ZN_COORDS_FLAG, False },
- { ZN_CONFIG_ITEM, "-connecteditem", NULL,
- Tk_Offset(WindowItemStruct, header.connected_item), 0,
- ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
- { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
- Tk_Offset(WindowItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_INT, "-height", NULL,
- Tk_Offset(WindowItemStruct, height), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(WindowItemStruct, pos), 0,
- ZN_COORDS_FLAG, False},
- { ZN_CONFIG_PRI, "-priority", NULL,
- Tk_Offset(WindowItemStruct, header.priority), 0,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
- { ZN_CONFIG_BOOL, "-sensitive", NULL,
- Tk_Offset(WindowItemStruct, header.flags), ZN_SENSITIVE_BIT,
- ZN_REPICK_FLAG, False },
- { ZN_CONFIG_TAG_LIST, "-tags", NULL,
- Tk_Offset(WindowItemStruct, header.tags), 0, 0, False },
- { ZN_CONFIG_BOOL, "-visible", NULL,
- Tk_Offset(WindowItemStruct, header.flags), ZN_VISIBLE_BIT,
- ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
- { ZN_CONFIG_INT, "-width", NULL,
- Tk_Offset(WindowItemStruct, width), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_WINDOW, "-window", NULL,
- Tk_Offset(WindowItemStruct, win), 0,
- ZN_COORDS_FLAG|ZN_WINDOW_FLAG, False },
-
- { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
-};
-
-
-/*
- **********************************************************************************
- *
- * WindowDeleted --
- *
- * Do the bookeeping after a managed window deletion.
- *
- **********************************************************************************
- */
-static void
-WindowDeleted(ClientData client_data,
- XEvent *event)
-{
- WindowItem wind = (WindowItem) client_data;
-
- if (event->type == DestroyNotify) {
- wind->win = NULL;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Window item geometry manager --
- *
- **********************************************************************************
- */
-
-/*
- * A managed window changes requested dimensions.
- */
-static void
-WindowItemRequest(ClientData client_data,
- Tk_Window win)
-{
- WindowItem wind = (WindowItem) client_data;
-
- ZnITEM.Invalidate((ZnItem) wind, ZN_COORDS_FLAG);
-}
-
-/*
- * A managed window turns control over
- * to another geometry manager.
- */
-static void
-WindowItemLostSlave(ClientData client_data,
- Tk_Window win)
-{
- WindowItem wind = (WindowItem) client_data;
- ZnWInfo *wi = ((ZnItem) wind)->wi;
-
- Tk_DeleteEventHandler(wi->win, StructureNotifyMask, WindowDeleted,
- (ClientData) wind);
- if (wi->win != Tk_Parent(wind->win)) {
- Tk_UnmaintainGeometry(wind->win, wi->win);
- }
- Tk_UnmapWindow(wind->win);
- wind->win = NULL;
-}
-
-static Tk_GeomMgr wind_geom_type = {
- "zincwindow", /* name */
- WindowItemRequest, /* requestProc */
- WindowItemLostSlave, /* lostSlaveProc */
-};
-
-
-/*
- **********************************************************************************
- *
- * Init --
- *
- **********************************************************************************
- */
-static int
-Init(ZnItem item,
- int *argc,
- Tcl_Obj *CONST *args[])
-{
- WindowItem wind = (WindowItem) item;
-
- /* Init attributes */
- SET(item->flags, ZN_VISIBLE_BIT);
- SET(item->flags, ZN_SENSITIVE_BIT);
- SET(item->flags, ZN_COMPOSE_ALPHA_BIT); /* N.A */
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
- item->priority = 0;
-
- wind->pos.x = wind->pos.y = 0.0;
- wind->width = wind->height = 0;
- wind->anchor = TK_ANCHOR_NW;
- wind->connection_anchor = TK_ANCHOR_SW;
- wind->win = NULL;
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Clone --
- *
- **********************************************************************************
- */
-static void
-Clone(ZnItem item)
-{
- WindowItem wind = (WindowItem) item;
-
- /*
- * The same Tk widget can't be shared by to Window items.
- */
- wind->win = NULL;
-}
-
-
-/*
- **********************************************************************************
- *
- * Destroy --
- *
- **********************************************************************************
- */
-static void
-Destroy(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- WindowItem wind = (WindowItem) item;
-
- /*
- * Unmanage the widget.
- */
- if (wind->win) {
- Tk_DeleteEventHandler(wind->win, StructureNotifyMask, WindowDeleted,
- (ClientData) item);
- Tk_ManageGeometry(wind->win, (Tk_GeomMgr *) NULL, (ClientData) NULL);
- if (wi->win != Tk_Parent(wind->win)) {
- Tk_UnmaintainGeometry(wind->win, wi->win);
- }
- Tk_UnmapWindow(wind->win);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Configure --
- *
- **********************************************************************************
- */
-static int
-Configure(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[],
- int *flags)
-{
- WindowItem wind = (WindowItem) item;
- ZnWInfo *wi = item->wi;
- ZnItem old_connected;
- Tk_Window old_win;
-
- old_connected = item->connected_item;
- old_win = wind->win;
- if (ZnConfigureAttributes(wi, item, item, wind_attrs, argc, argv, flags) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- if (ISSET(*flags, ZN_ITEM_FLAG)) {
- /*
- * If the new connected item is not appropriate back up
- * to the old one.
- */
- if ((item->connected_item == ZN_NO_ITEM) ||
- (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
- (item->parent == item->connected_item->parent))) {
- ZnITEM.UpdateItemDependency(item, old_connected);
- }
- else {
- item->connected_item = old_connected;
- }
- }
-
- if (ISSET(*flags, ZN_WINDOW_FLAG)) {
- if (old_win != NULL) {
- Tk_DeleteEventHandler(old_win, StructureNotifyMask,
- WindowDeleted, (ClientData) item);
- Tk_ManageGeometry(old_win, (Tk_GeomMgr *) NULL, (ClientData) NULL);
- Tk_UnmaintainGeometry(old_win, wi->win);
- Tk_UnmapWindow(old_win);
- }
- if (wind->win != NULL) {
- Tk_CreateEventHandler(wind->win, StructureNotifyMask,
- WindowDeleted, (ClientData) item);
- Tk_ManageGeometry(wind->win, &wind_geom_type, (ClientData) item);
- }
- }
-
- if ((wind->win != NULL) &&
- ISSET(*flags, ZN_VIS_FLAG) &&
- ISCLEAR(item->flags, ZN_VISIBLE_BIT)) {
- Tk_UnmapWindow(wind->win);
- }
-
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Query --
- *
- **********************************************************************************
- */
-static int
-Query(ZnItem item,
- int argc,
- Tcl_Obj *CONST argv[])
-{
- if (ZnQueryAttribute(item->wi->interp, item, wind_attrs, argv[0]) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- * Compute the transformation to be used and the origin
- * of the window (upper left point in item coordinates).
- */
-static ZnTransfo *
-ComputeTransfoAndOrigin(ZnItem item,
- ZnPoint *origin)
-{
- WindowItem wind = (WindowItem) item;
- ZnTransfo *t;
-
- /*
- * The connected item support anchors, this is checked by configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- ZnTransfo inv;
-
- item->connected_item->class->GetAnchor(item->connected_item,
- wind->connection_anchor,
- origin);
-
- /* GetAnchor return a position in device coordinates not in
- * the item coordinate space. To compute the icon origin
- * (upper left corner), we must apply the inverse transform
- * to the ref point before calling anchor2origin.
- */
- ZnTransfoInvert(item->transfo, &inv);
- ZnTransformPoint(&inv, origin, origin);
- /*
- * The relevant transform in case of an attachment is the item
- * transform alone. This is case of local coordinate space where
- * only the translation is a function of the whole transform
- * stack, scale and rotation are reset.
- */
- t = item->transfo;
- }
- else {
- origin->x = origin->y = 0;
- t = item->wi->current_transfo;
- }
-
- ZnAnchor2Origin(origin, (ZnReal) wind->real_width, (ZnReal) wind->real_height,
- wind->anchor, origin);
- //origin->x = ZnNearestInt(origin->x);
- //origin->y = ZnNearestInt(origin->y);
-
- return t;
-}
-
-/*
- **********************************************************************************
- *
- * ComputeCoordinates --
- *
- **********************************************************************************
- */
-static void
-ComputeCoordinates(ZnItem item,
- ZnBool force)
-{
- ZnWInfo *wi = item->wi;
- WindowItem wind = (WindowItem) item;
- ZnPoint origin;
- ZnTransfo *t;
-
- ZnResetBBox(&item->item_bounding_box);
-
- if (wind->win == NULL) {
- return;
- }
-
- wind->real_width = wind->width;
- if (wind->real_width <= 0) {
- wind->real_width = Tk_ReqWidth(wind->win);
- if (wind->real_width <= 0) {
- wind->real_width = 1;
- }
- }
- wind->real_height = wind->height;
- if (wind->real_height <= 0) {
- wind->real_height = Tk_ReqHeight(wind->win);
- if (wind->real_height <= 0) {
- wind->real_height = 1;
- }
- }
-
- t = ComputeTransfoAndOrigin(item, &origin);
- ZnTransformPoint(wi->current_transfo, &origin, &wind->pos_dev);
- wind->pos_dev.x = ZnNearestInt(wind->pos_dev.x);
- wind->pos_dev.y = ZnNearestInt(wind->pos_dev.y);
-
- /*
- * Compute the bounding box.
- */
- ZnAddPointToBBox(&item->item_bounding_box, wind->pos_dev.x, wind->pos_dev.y);
- ZnAddPointToBBox(&item->item_bounding_box, wind->pos_dev.x+wind->real_width,
- wind->pos_dev.y+wind->real_height);
- item->item_bounding_box.orig.x -= 1.0;
- item->item_bounding_box.orig.y -= 1.0;
- item->item_bounding_box.corner.x += 1.0;
- item->item_bounding_box.corner.y += 1.0;
-
- /*
- * Update connected items.
- */
- SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
-}
-
-
-/*
- **********************************************************************************
- *
- * ToArea --
- * Tell if the object is entirely outside (-1),
- * entirely inside (1) or in between (0).
- *
- **********************************************************************************
- */
-static int
-ToArea(ZnItem item,
- ZnToArea ta)
-{
- WindowItem wind = (WindowItem) item;
- ZnBBox box;
- int w=0, h=0;
-
- box.orig = wind->pos_dev;
- if (wind->win != NULL) {
- w = wind->real_width;
- h = wind->real_height;
- }
- box.corner.x = box.orig.x + w;
- box.corner.y = box.orig.y + h;
-
- return ZnBBoxInBBox(&box, ta->area);
-}
-
-/*
- **********************************************************************************
- *
- * Draw --
- *
- **********************************************************************************
- */
-static void
-Draw(ZnItem item)
-{
- ZnWInfo *wi = item->wi;
- WindowItem wind = (WindowItem) item;
-
- if (wind->win == NULL) {
- return;
- }
-
- /*
- * If the window is outside the visible area, unmap it.
- */
- if ((item->item_bounding_box.corner.x <= 0) ||
- (item->item_bounding_box.corner.y <= 0) ||
- (item->item_bounding_box.orig.x >= wi->width) ||
- (item->item_bounding_box.orig.y >= wi->height)) {
- if (wi->win == Tk_Parent(wind->win)) {
- Tk_UnmapWindow(wind->win);
- }
- else {
- Tk_UnmaintainGeometry(wind->win, wi->win);
- }
- return;
- }
-
- /*
- * Position and map the window.
- */
- if (wi->win == Tk_Parent(wind->win)) {
- if ((wind->pos_dev.x != Tk_X(wind->win)) ||
- (wind->pos_dev.y != Tk_Y(wind->win)) ||
- (wind->real_width != Tk_Width(wind->win)) ||
- (wind->real_height != Tk_Height(wind->win))) {
- Tk_MoveResizeWindow(wind->win,
- (int) wind->pos_dev.x, (int) wind->pos_dev.y,
- wind->real_width, wind->real_height);
- }
- Tk_MapWindow(wind->win);
- }
- else {
- Tk_MaintainGeometry(wind->win, wi->win,
- (int) wind->pos_dev.x, (int) wind->pos_dev.y,
- wind->real_width, wind->real_height);
- }
-
-}
-
-
-/*
- **********************************************************************************
- *
- * IsSensitive --
- *
- **********************************************************************************
- */
-static ZnBool
-IsSensitive(ZnItem item,
- int item_part)
-{
- /*
- * Sensitivity can't be controlled.
- */
- return True;
-}
-
-
-/*
- **********************************************************************************
- *
- * Pick --
- *
- **********************************************************************************
- */
-static double
-Pick(ZnItem item,
- ZnPick ps)
-{
- WindowItem wind = (WindowItem) item;
- ZnBBox box;
- ZnReal dist = 1e40;
- ZnPoint *p = ps->point;
-
- box.orig = wind->pos_dev;
- if (wind->win != NULL) {
- box.corner.x = box.orig.x + wind->real_width;
- box.corner.y = box.orig.y + wind->real_height;
- dist = ZnRectangleToPointDist(&box, p);
- if (dist <= 0.0) {
- dist = 0.0;
- }
- }
- return dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * PostScript --
- *
- **********************************************************************************
- */
-#ifdef X_GetImage
-static int
-xerrorhandler(ClientData client_data,
- XErrorEvent *e)
-{
- return 0;
-}
-#endif
-
-static int
-PostScript(ZnItem item,
- ZnBool prepass,
- ZnBBox *area)
-{
- ZnWInfo *wi = item->wi;
- WindowItem wind = (WindowItem) item;
- char path[256];
- XImage *ximage;
- int result;
- ZnPoint origin;
- Tcl_DString buffer1, buffer2;
-#ifdef X_GetImage
- Tk_ErrorHandler handle;
-#endif
-
- sprintf(path, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
- Tk_Class(wind->win), Tk_PathName(wind->win), wind->real_width, wind->real_height,
- wind->pos_dev.x, wind->pos_dev.y);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- ComputeTransfoAndOrigin(item, &origin);
-
- sprintf(path, "/InitialTransform load setmatrix\n"
- "%.15g %.15g translate\n"
- "1 -1 scale\n",
- wind->pos_dev.x, wind->pos_dev.y + wind->real_height);
- Tcl_AppendResult(wi->interp, path, NULL);
-
- /* first try if the widget has its own "postscript" command. If it
- * exists, this will produce much better postscript than
- * when a pixmap is used.
- */
-#ifndef PTK
- Tcl_DStringInit(&buffer1);
- Tcl_DStringInit(&buffer2);
- Tcl_DStringGetResult(wi->interp, &buffer2);
- sprintf(path, "%s postscript -prolog 0\n", Tk_PathName(wind->win));
- result = Tcl_Eval(wi->interp, path);
- Tcl_DStringGetResult(wi->interp, &buffer1);
- Tcl_DStringResult(wi->interp, &buffer2);
- Tcl_DStringFree(&buffer2);
-
- if (result == TCL_OK) {
- Tcl_AppendResult(wi->interp, "50 dict begin\nsave\ngsave\n", NULL);
- sprintf (path, "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
- wind->real_height, wind->real_width, wind->real_height, wind->real_width);
- Tcl_AppendResult(wi->interp, path, NULL);
- Tcl_AppendResult(wi->interp, " 0 rlineto closepath\n",
- "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
- Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", NULL);
- Tcl_DStringFree(&buffer1);
-
- return result;
- }
- Tcl_DStringFree(&buffer1);
-#endif
-
- /*
- * If the window is off the screen it will generate an BadMatch/XError
- * We catch any BadMatch errors here
- */
-#ifdef X_GetImage
- handle = Tk_CreateErrorHandler(wi->dpy, BadMatch, X_GetImage, -1,
- xerrorhandler, (ClientData) wind->win);
-#endif
-
- /*
- * Generate an XImage from the window. We can then read pixel
- * values out of the XImage.
- */
- ximage = XGetImage(wi->dpy, Tk_WindowId(wind->win), 0, 0, (unsigned int) wind->real_width,
- (unsigned int) wind->real_height, AllPlanes, ZPixmap);
-
-#ifdef X_GetImage
- Tk_DeleteErrorHandler(handle);
-#endif
-
- if (ximage == NULL) {
- return TCL_OK;
- }
-
- result = ZnPostscriptXImage(wi->interp, wind->win, wi->ps_info, ximage,
- 0, 0, wind->real_width, wind->real_height);
- XDestroyImage(ximage);
-
- return result;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetAnchor --
- *
- **********************************************************************************
- */
-static void
-GetAnchor(ZnItem item,
- Tk_Anchor anchor,
- ZnPoint *p)
-{
- WindowItem wind = (WindowItem) item;
-
- if (wind->win != NULL) {
- ZnOrigin2Anchor(&wind->pos_dev, (ZnReal) wind->real_width,
- (ZnReal) wind->real_height, anchor, p);
- }
- else {
- p->x = p->y = 0.0;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * GetClipVertices --
- * Get the clipping shape.
- *
- **********************************************************************************
- */
-static ZnBool
-GetClipVertices(ZnItem item,
- ZnTriStrip *tristrip)
-{
- WindowItem wind = (WindowItem) item;
- int w=0, h=0;
- ZnPoint *points;
-
- ZnListAssertSize(ZnWorkPoints, 2);
- if (wind->win != NULL) {
- w = wind->real_width;
- h = wind->real_height;
- }
- points = ZnListArray(ZnWorkPoints);
- ZnTriStrip1(tristrip, points, 2, False);
- points[0] = wind->pos_dev;
- points[1].x = points[0].x + w;
- points[1].y = points[0].y + h;
-
- return True;
-}
-
-
-/*
- **********************************************************************************
- *
- * Coords --
- * Return or edit the item origin. This doesn't take care of
- * the possible attachment. The change will be effective at the
- * end of the attachment.
- *
- **********************************************************************************
- */
-static int
-Coords(ZnItem item,
- int contour,
- int index,
- int cmd,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts)
-{
- WindowItem wind = (WindowItem) item;
-
- if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
- Tcl_AppendResult(item->wi->interp,
- " windows can't add or remove vertices", NULL);
- return TCL_ERROR;
- }
- else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
- if (*num_pts == 0) {
- Tcl_AppendResult(item->wi->interp,
- " coords command need 1 point on windows", NULL);
- return TCL_ERROR;
- }
- wind->pos = (*pts)[0];
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
- *num_pts = 1;
- *pts = &wind->pos;
- }
- return TCL_OK;
-}
-
-
-/*
- **********************************************************************************
- *
- * Exported functions struct --
- *
- **********************************************************************************
- */
-static ZnItemClassStruct WINDOW_ITEM_CLASS = {
- "window",
- sizeof(WindowItemStruct),
- wind_attrs,
- 0, /* num_parts */
- ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
- Tk_Offset(WindowItemStruct, pos),
- Init,
- Clone,
- Destroy,
- Configure,
- Query,
- NULL, /* GetFieldSet */
- GetAnchor,
- GetClipVertices,
- NULL, /* GetContours */
- Coords,
- NULL, /* InsertChars */
- NULL, /* DeleteChars */
- NULL, /* Cursor */
- NULL, /* Index */
- NULL, /* Part */
- NULL, /* Selection */
- NULL, /* Contour */
- ComputeCoordinates,
- ToArea,
- Draw,
- Draw, /* Render use the same code as Draw. */
- IsSensitive,
- Pick,
- NULL, /* PickVertex */
- PostScript
-};
-
-ZnItemClassId ZnWindow = (ZnItemClassId) &WINDOW_ITEM_CLASS;
diff --git a/generic/perfos.c b/generic/perfos.c
deleted file mode 100644
index 77d19a4..0000000
--- a/generic/perfos.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * perfos.c -- Perfos modules.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-#ifndef _WIN32
-
-#include "perfos.h"
-#include "List.h"
-#include "Types.h"
-
-#include <X11/Xutil.h>
-
-
-static const char rcsid[] = "$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-
-
-static ZnList Chronos = NULL;
-
-
-/*
- **********************************************************************************
- *
- * HardwareSynchronize - Synchronise Xwindow.
- *
- **********************************************************************************
- */
-static void
-HardwareSynchronize(Display *test_display,
- Drawable test_window)
-{
- /*XImage *image;*/
-
- /* Synchronize yourself with the drawing engine by sending a
- XGetImage one pixel square. */
- /*
- image = XGetImage(test_display, test_window, 0, 0, 1, 1, ~0, ZPixmap);
- XDestroyImage(image);
- */
-}
-
-
-/*
- **********************************************************************************
- *
- * GetUCTime - Return machine time. This is the sum of user and system
- * times for the process so far.
- *
- **********************************************************************************
- */
-static long
-GetUCTime(void)
-{
- struct tms time;
-
- times(&time);
- return time.tms_utime + time.tms_stime;
-}
-
-
-/*
- **********************************************************************************
- *
- * GetCurrentTime - Return current time.
- *
- **********************************************************************************
- */
-static long
-GetCurrentTime(void)
-{
- struct timeval start;
-
- gettimeofday(&start, NULL);
- return((start.tv_sec * 100) + (start.tv_usec / 10000));
-}
-
-
-/*
- **********************************************************************************
- *
- * XGetCurrentTime - return current time after Xwindow synchronize.
- *
- **********************************************************************************
- */
-static long
-XGetCurrentTime(Display *display, Drawable window)
-{
- HardwareSynchronize(display, window);
- return(GetCurrentTime());
-}
-
-
-/*
- **********************************************************************************
- *
- * XCorrectionValue - Evaluate the correction value to apply
- * to counter the client-server round trip
- * time.
- *
- **********************************************************************************
- */
-static long
-XCorrectionValue(Display *display, Drawable window)
-{
- int i;
- long start, stop;
-
- start = GetCurrentTime();
- for (i = 0; i < 5; i++) {
- HardwareSynchronize(display, window);
- }
- stop = GetCurrentTime();
- return((stop - start) / 5);
-}
-
-/*
- **********************************************************************************
- *
- * ZnXStartChrono - Start a perf chrono with X synchronize.
- *
- **********************************************************************************
- */
-void
-ZnXStartChrono(ZnChrono chrono, Display *display, Drawable window)
-{
- chrono->current_correction = XCorrectionValue(display, window);
- chrono->current_delay = XGetCurrentTime(display, window);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnXStopChrono - Stop a perf chrono with X synchronize.
- *
- **********************************************************************************
- */
-void
-ZnXStopChrono(ZnChrono chrono, Display *display, Drawable window)
-{
- chrono->total_delay = chrono->total_delay +
- (XGetCurrentTime(display, window) -
- chrono->current_delay - chrono->current_correction);
- chrono->actions++;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnStartChrono - Start a perf chrono in user time.
- *
- **********************************************************************************
- */
-void
-ZnStartChrono(ZnChrono chrono)
-{
- chrono->current_delay = GetCurrentTime();
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnStopChrono - Stop a perf chrono in user time.
- *
- **********************************************************************************
- */
-void
-ZnStopChrono(ZnChrono chrono)
-{
- chrono->total_delay = chrono->total_delay + (GetCurrentTime() - chrono->current_delay);
- chrono->actions++;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnStartUCChrono - Start a perf chrono in uc time.
- *
- **********************************************************************************
- */
-void
-ZnStartUCChrono(ZnChrono chrono)
-{
- chrono->current_delay = GetUCTime();
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnStopUCChrono - Stop a perf chrono in uc time.
- *
- **********************************************************************************
- */
-void
-ZnStopUCChrono(ZnChrono chrono)
-{
- chrono->total_delay = chrono->total_delay + (GetUCTime() - chrono->current_delay);
- chrono->actions++;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPrintChronos - Print the currently available stats on all
- * chronos registered so far.
- *
- **********************************************************************************
- */
-void
-ZnPrintChronos(void)
-{
- int i, cnt;
- ZnChrono *chrs;
-
- cnt = ZnListSize(Chronos);
- chrs = (ZnChrono *) ZnListArray(Chronos);
- for (i = 0; i < cnt; i++) {
- if (chrs[i]->actions != 0) {
- printf("%s : %ld ms on %d times\n",
- chrs[i]->message,
- chrs[i]->total_delay * 10 / chrs[i]->actions,
- chrs[i]->actions);
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetChrono - Return the number of runs and the total time of the Chrono.
- *
- **********************************************************************************
- */
-void
-ZnGetChrono(ZnChrono chrono,
- long *time,
- int *actions)
-{
- if (time) {
- *time = chrono->total_delay*10;
- }
- if (actions) {
- *actions = chrono->actions;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnResetChronos - Reset all chronos or only the specified.
- *
- **********************************************************************************
- */
-void
-ZnResetChronos(ZnChrono chrono)
-{
- int i, cnt;
- ZnChrono *chrs;
-
- if (chrono) {
- chrono->actions = 0;
- chrono->total_delay = 0;
- }
- else {
- cnt = ZnListSize(Chronos);
- chrs = (ZnChrono *) ZnListArray(Chronos);
- for (i = 0; i < cnt; i++) {
- chrs[i]->actions = 0;
- chrs[i]->total_delay = 0;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnNewChrono - Return a new initialized chrono associated with
- * message.
- *
- **********************************************************************************
- */
-ZnChrono
-ZnNewChrono(char *message)
-{
- ZnChrono new;
-
- if (!Chronos) {
- Chronos = ZnListNew(8, sizeof(ZnChrono));
- }
-
- new = (ZnChrono) ZnMalloc(sizeof(ZnChronoRec));
- new->actions = 0;
- new->total_delay = 0;
- new->message = message;
-
- ZnListAdd(Chronos, &new, ZnListTail);
-
- return new;
-}
-
-/*
- **********************************************************************************
- *
- * ZnFreeChrono - Free the resources of a chrono.
- *
- **********************************************************************************
- */
-void
-ZnFreeChrono(ZnChrono chrono)
-{
- int i;
- ZnChrono *chrs = ZnListArray(Chronos);
-
- ZnFree(chrono);
-
- for (i = ZnListSize(Chronos)-1; i >= 0; i--) {
- if (chrs[i] == chrono) {
- ZnListDelete(Chronos, i);
- break;
- }
- }
-}
-
-#endif /* _WIN32 */
diff --git a/generic/perfos.h b/generic/perfos.h
deleted file mode 100644
index fb54bf5..0000000
--- a/generic/perfos.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * perfos.h -- Header for perf module.
- *
- * Authors : Patrick Lecoanet.
- * Creation date :
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1996 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _perfos_h
-#define _perfos_h
-
-#ifdef __CPLUSPLUS__
-extern "C" {
-#endif
-
-#ifndef _WIN32
-
-#include <stdio.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <X11/Xlib.h>
-
- typedef struct
- {
- long current_correction;
- long current_delay;
- long total_delay;
- int actions;
- char *message;
- } ZnChronoRec, *ZnChrono;
-
-
- void ZnXStartChrono(ZnChrono /*chrono*/, Display */*dpy*/, Drawable /*win*/);
- void ZnXStopChrono(ZnChrono /*chrono*/, Display */*dpy*/, Drawable /*win*/);
- void ZnStartChrono(ZnChrono /*chrono*/);
- void ZnStopChrono(ZnChrono /*chrono*/);
- void ZnStartUCChrono(ZnChrono /*chrono*/);
- void ZnStopUCChrono(ZnChrono /*chrono*/);
- ZnChrono ZnNewChrono(char */*message*/);
- void ZnFreeChrono(ZnChrono /*chrono*/);
- void ZnPrintChronos(void);
- void ZnGetChrono(ZnChrono /*chrono*/, long */*time*/, int */*actions*/);
- void ZnResetChronos(ZnChrono /*chrono*/);
-
-#endif /* _WIN32 */
-
-#ifdef __CPLUSPLUS__
-}
-#endif
-
-#endif /* _perfos_h */
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
deleted file mode 100644
index 82b85b3..0000000
--- a/generic/tkZinc.c
+++ /dev/null
@@ -1,9059 +0,0 @@
-/*
- * tkZinc.c -- Zinc widget for the Tk Toolkit. Main module.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Mon Feb 1 12:13:24 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-/*
- * Some functions and code excerpts in this file are from tkCanvas.c
- * and thus copyrighted:
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
- * Copyright (c) 1998-1999 by Scriptics Corporation.
- *
- */
-
-static const char rcs_id[]="$Id$";
-static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-static const char * const zinc_version = "zinc-version-" VERSION;
-
-
-#include "Types.h"
-#include "Geo.h"
-#include "Item.h"
-#include "Group.h"
-#include "WidgetInfo.h"
-#include "tkZinc.h"
-#include "MapInfo.h"
-#ifdef ATC
-#include "OverlapMan.h"
-#include "Track.h"
-#endif
-#include "Transfo.h"
-#include "Image.h"
-#include "Draw.h"
-#include "Color.h"
-#ifndef _WIN32
-#include "perfos.h"
-#endif
-
-#include <GL/glu.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <X11/Xatom.h>
-#if defined(_WIN32) && defined(PTK) && !defined(PTK_800)
-#include <tkPlatDecls.m>
-#endif
-
-
-typedef struct _TagSearchExpr {
- struct _TagSearchExpr *next; /* for linked lists of expressions - used in bindings */
- Tk_Uid uid; /* the uid of the whole expression */
- Tk_Uid *uids; /* expresion compiled to an array of uids */
- int allocated; /* available space for array of uids */
- int length; /* length of expression */
- int index; /* current position in expression evaluation */
- int match; /* this expression matches event's item's tags*/
-} TagSearchExpr;
-
-
-#define SYMBOL_WIDTH 8
-#define SYMBOL_HEIGHT 8
-static unsigned char SYMBOLS_BITS[][SYMBOL_WIDTH*SYMBOL_HEIGHT/8] = {
- { 0x18, 0x18, 0x24, 0x24, 0x5a, 0x5a, 0x81, 0xff },
- { 0xff, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0xff },
- { 0x18, 0x24, 0x42, 0x99, 0x99, 0x42, 0x24, 0x18 },
- { 0x18, 0x3c, 0x5a, 0xff, 0xff, 0x5a, 0x3c, 0x18 },
- { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 },
- { 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c },
- { 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0xff },
- { 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff },
- { 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xff, 0xff },
- { 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff },
- { 0x18, 0x3c, 0x7e, 0xe7, 0xe7, 0x7e, 0x3c, 0x18 },
- { 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18 },
- { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
- { 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c },
- { 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff },
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
- { 0x18, 0x7e, 0x7e, 0xff, 0xff, 0x7e, 0x7e, 0x18 },
- { 0x18, 0x66, 0x42, 0x81, 0x81, 0x42, 0x66, 0x18 },
- { 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 },
- { 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00 },
- { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
- { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 },
-};
-
-static unsigned char dither4x4[4][4] = {
- { 0, 8, 2, 10 },
- { 12, 4, 14, 6 },
- { 3, 11, 1, 9 },
- { 15, 7, 13, 5 }
-};
-
-static unsigned char bitmaps[ZN_NUM_ALPHA_STEPS][32][4];
-
-static Tk_Uid all_uid;
-static Tk_Uid current_uid;
-static Tk_Uid and_uid;
-static Tk_Uid or_uid;
-static Tk_Uid xor_uid;
-static Tk_Uid paren_uid;
-static Tk_Uid end_paren_uid;
-static Tk_Uid neg_paren_uid;
-static Tk_Uid tag_val_uid;
-static Tk_Uid neg_tag_val_uid;
-static Tk_Uid dot_uid;
-static Tk_Uid star_uid;
-
-#ifdef GL
-static ZnGLContextEntry *gl_contexts = NULL;
-#ifndef _WIN32
-static int ZnMajorGlx, ZnMinorGlx;
-static int ZnGLAttribs[] = {
- GLX_RGBA,
- GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 8,
- GLX_GREEN_SIZE, 8,
- GLX_BLUE_SIZE, 8,
- GLX_STENCIL_SIZE, 8,
- /*GLX_ALPHA_SIZE, 8,*/
- GLX_DEPTH_SIZE, 0,
- None
-};
-#endif
-#endif
-
-/*
- * Temporary object lists
- */
- ZnList ZnWorkPoints;
- ZnList ZnWorkXPoints;
- ZnList ZnWorkStrings;
-
-/*
- * Tesselator
- */
- ZnTess ZnTesselator;
-
-
-static void PickCurrentItem _ANSI_ARGS_((ZnWInfo *wi, XEvent *event));
-#ifdef PTK_800
-static int ZnReliefParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnReliefPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-static int ZnGradientParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnGradientPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-static int ZnImageParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static int ZnBitmapParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *ovalue,
- char *widget_rec, int offset));
-static Tcl_Obj *ZnImagePrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset,
- Tcl_FreeProc **free_proc));
-static Tk_CustomOption reliefOption = {
- (Tk_OptionParseProc *) ZnReliefParse,
- (Tk_OptionPrintProc *) ZnReliefPrint,
- NULL
-};
-static Tk_CustomOption gradientOption = {
- (Tk_OptionParseProc *) ZnGradientParse,
- (Tk_OptionPrintProc *) ZnGradientPrint,
- NULL
-};
-static Tk_CustomOption imageOption = {
- (Tk_OptionParseProc *) ZnImageParse,
- (Tk_OptionPrintProc *) ZnImagePrint,
- NULL
-};
-static Tk_CustomOption bitmapOption = {
- (Tk_OptionParseProc *) ZnBitmapParse,
- (Tk_OptionPrintProc *) ZnImagePrint,
- NULL
-};
-#else
-static int ZnSetReliefOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj **ovalue,
- char *widget_rec, int offset, char *old_val_ptr, int flags));
-static Tcl_Obj *ZnGetReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset));
-static void ZnRestoreReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *val_ptr, char *old_val_ptr));
-static int ZnSetGradientOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj **ovalue,
- char *widget_rec, int offset, char *old_val_ptr, int flags));
-static Tcl_Obj *ZnGetGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *widget_rec, int offset));
-static void ZnRestoreGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
- char *val_ptr, char *old_val_ptr));
-static void ZnFreeGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, char *val_ptr));
-
-static Tk_ObjCustomOption reliefOption = {
- "znrelief",
- ZnSetReliefOpt,
- ZnGetReliefOpt,
- ZnRestoreReliefOpt,
- NULL,
- 0
-};
-static Tk_ObjCustomOption gradientOption = {
- "zngradient",
- ZnSetGradientOpt,
- ZnGetGradientOpt,
- ZnRestoreGradientOpt,
- ZnFreeGradientOpt,
- NULL
-};
-#endif
-
-#ifdef PTK_800
-#define BORDER_WIDTH_SPEC 0
-#define BACK_COLOR_SPEC 1
-#define CONFINE_SPEC 2
-#define CURSOR_SPEC 3
-#define FONT_SPEC 4
-#define FORE_COLOR_SPEC 5
-#define FULL_RESHAPE_SPEC 6
-#define HEIGHT_SPEC 7
-#define HIGHLIGHT_BACK_COLOR_SPEC 8
-#define HIGHLIGHT_COLOR_SPEC 9
-#define HIGHLIGHT_THICKNESS_SPEC 10
-#define INSERT_COLOR_SPEC 11
-#define INSERT_OFF_TIME_SPEC 12
-#define INSERT_ON_TIME_SPEC 13
-#define INSERT_WIDTH_SPEC 14
-#define MAP_DISTANCE_SYMBOL_SPEC 15
-#define MAP_TEXT_FONT_SPEC 16
-#define OVERLAP_MANAGER_SPEC 17
-#define PICK_APERTURE_SPEC 18
-#define RELIEF_SPEC 19
-#define RENDER_SPEC 20
-#define RESHAPE_SPEC 21
-#define SCROLL_REGION_SPEC 22
-#define SELECT_COLOR_SPEC 23
-#define SPEED_VECTOR_LENGTH_SPEC 24
-#define TAKE_FOCUS_SPEC 25
-#define TILE_SPEC 26
-#define VISIBLE_HISTORY_SIZE_SPEC 27
-#define MANAGED_HISTORY_SIZE_SPEC 28
-#define TRACK_SYMBOL_SPEC 29
-#define WIDTH_SPEC 30
-#define X_SCROLL_CMD_SPEC 31
-#define X_SCROLL_INCREMENT_SPEC 32
-#define Y_SCROLL_CMD_SPEC 33
-#define Y_SCROLL_INCREMENT_SPEC 34
-#define BBOXES_SPEC 35
-#define BBOXES_COLOR_SPEC 36
-#define LIGHT_ANGLE_SPEC 37
-#define FOLLOW_POINTER_SPEC 38
-#else
-#define CONFIG_FONT 1<<0
-#define CONFIG_MAP_FONT 1<<1
-#define CONFIG_BACK_COLOR 1<<2
-#define CONFIG_REDISPLAY 1<<3
-#define CONFIG_DAMAGE_ALL 1<<4
-#define CONFIG_INVALIDATE_TRACKS 1<<5
-#define CONFIG_INVALIDATE_WPS 1<<6
-#define CONFIG_INVALIDATE_MAPS 1<<7
-#define CONFIG_REQUEST_GEOM 1<<8
-#define CONFIG_OM 1<<9
-#define CONFIG_FOCUS 1<<10
-#define CONFIG_FOCUS_ITEM 1<<11
-#define CONFIG_SCROLL_REGION 1<<12
-#define CONFIG_SET_ORIGIN 1<<13
-#define CONFIG_FOLLOW_POINTER 1<<14
-#define CONFIG_MAP_SYMBOL 1<<15
-#define CONFIG_TRACK_SYMBOL 1<<16
-#define CONFIG_TILE 1<<17
-#define CONFIG_DEBUG 1<<18
-#endif
-
-/*
- * Information used for argv parsing.
- */
-#ifdef PTK_800
-static Tk_ConfigSpec config_specs[] = {
- {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- "2", Tk_Offset(ZnWInfo, border_width), 0, NULL},
- {TK_CONFIG_CUSTOM, "-backcolor", "backColor", "BackColor",
- "#c3c3c3", Tk_Offset(ZnWInfo, back_color), 0, &gradientOption},
- {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
- "1", Tk_Offset(ZnWInfo, confine), 0, NULL},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- "", Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
- Tk_Offset(ZnWInfo, font), 0, NULL},
- {TK_CONFIG_CUSTOM, "-forecolor", "foreColor", "Foreground",
- "Black", Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption},
- {TK_CONFIG_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape",
- "1", Tk_Offset(ZnWInfo, full_reshape), 0, NULL},
- {TK_CONFIG_PIXELS, "-height", "height", "Height",
- "7c", Tk_Offset(ZnWInfo, opt_height), 0, NULL},
- {TK_CONFIG_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground",
- "#c3c3c3", Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption},
- {TK_CONFIG_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor",
- "Black", Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness",
- "2", Tk_Offset(ZnWInfo, highlight_width), 0, NULL},
- {TK_CONFIG_CUSTOM, "-insertbackground", "insertBackground", "Foreground",
- "Black", Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption},
- {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
- "300", Tk_Offset(ZnWInfo, insert_off_time), 0, NULL},
- {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
- "600", Tk_Offset(ZnWInfo, insert_on_time), 0, NULL},
- {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
- "2", Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL},
-#ifdef ATC
- {TK_CONFIG_CUSTOM, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol",
- "AtcSymbol19", Tk_Offset(ZnWInfo, map_distance_symbol),
- TK_CONFIG_NULL_OK, &bitmapOption},
- {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont",
- "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
- Tk_Offset(ZnWInfo, map_text_font), 0, NULL},
- {TK_CONFIG_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1",
- Tk_Offset(ZnWInfo, om_group_id), 0, NULL},
-#endif
- {TK_CONFIG_INT, "-pickaperture", "pickAperture", "PickAperture",
- "1", Tk_Offset(ZnWInfo, pick_aperture), 0, NULL},
- {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief",
- "flat", Tk_Offset(ZnWInfo, relief), 0, &reliefOption},
- {TK_CONFIG_INT, "-render", "render", "Render",
- "0", Tk_Offset(ZnWInfo, render), 0, NULL},
- {TK_CONFIG_BOOLEAN, "-reshape", "reshape", "Reshape",
- "1", Tk_Offset(ZnWInfo, reshape), 0, NULL},
- {TK_CONFIG_LANGARG, "-scrollregion", "scrollRegion", "ScrollRegion",
- "", Tk_Offset(ZnWInfo, region), TK_CONFIG_NULL_OK, NULL},
- {TK_CONFIG_CUSTOM, "-selectbackground", "selectBackground", "Foreground",
- "#a0a0a0", Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption},
-#ifdef ATC
- {TK_CONFIG_DOUBLE, "-speedvectorlength", "speedVectorLength",
- "SpeedVectorLength", "3", Tk_Offset(ZnWInfo, speed_vector_length), 0, NULL},
-#endif
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- NULL, Tk_Offset(ZnWInfo, take_focus), TK_CONFIG_NULL_OK, NULL},
- {TK_CONFIG_CUSTOM, "-tile", "tile", "Tile",
- "", Tk_Offset(ZnWInfo, tile), 0, &imageOption},
-#ifdef ATC
- {TK_CONFIG_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize",
- "6", Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL},
- {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
- "TrackManagedHistorySize", "6", Tk_Offset(ZnWInfo, track_managed_history_size), 0, NULL},
- {TK_CONFIG_CUSTOM, "-tracksymbol", "trackSymbol", "TrackSymbol",
- "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol), TK_CONFIG_NULL_OK, &bitmapOption},
-#endif
- {TK_CONFIG_PIXELS, "-width", "width", "Width",
- "10c", Tk_Offset(ZnWInfo, opt_width), 0, NULL},
- {TK_CONFIG_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- "", Tk_Offset(ZnWInfo, x_scroll_cmd), TK_CONFIG_NULL_OK, NULL},
- {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement",
- "0", Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL},
- {TK_CONFIG_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
- "", Tk_Offset(ZnWInfo, y_scroll_cmd), TK_CONFIG_NULL_OK, NULL},
- {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement",
- "0", Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL},
- /*
- * Debug options.
- */
- {TK_CONFIG_BOOLEAN, "-drawbboxes", "drawBBoxes",
- "DrawBBoxes", "0", Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL},
- {TK_CONFIG_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor",
- "Pink", Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption},
- {TK_CONFIG_INT, "-lightangle", "lightAngle", "LightAngle",
- "120", Tk_Offset(ZnWInfo, light_angle), 0, NULL},
- {TK_CONFIG_BOOLEAN, "-followpointer", "followPointer",
- "FollowPointer", "1", Tk_Offset(ZnWInfo, follow_pointer), 0, NULL},
-
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
-};
-#else
-static Tk_OptionSpec option_specs[] = {
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- "2", -1, Tk_Offset(ZnWInfo, border_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM},
- {TK_OPTION_CUSTOM, "-backcolor", "backColor", "BackColor",
- "#c3c3c3", -1, Tk_Offset(ZnWInfo, back_color), 0, &gradientOption,
- CONFIG_BACK_COLOR|CONFIG_DAMAGE_ALL},
- {TK_OPTION_BOOLEAN, "-confine", "confine", "Confine",
- "1", -1, Tk_Offset(ZnWInfo, confine), 0, NULL, CONFIG_SET_ORIGIN},
- {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
- "", -1, Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL, 0},
- {TK_OPTION_INT, "-debug", "debug", "Debug",
- "0", -1, Tk_Offset(ZnWInfo, debug), 0, NULL, 0},
- {TK_OPTION_FONT, "-font", "font", "Font",
- "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
- -1, Tk_Offset(ZnWInfo, font), 0, NULL, CONFIG_FONT},
- {TK_OPTION_CUSTOM, "-forecolor", "foreColor", "Foreground",
- "Black", -1, Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption, 0},
- {TK_OPTION_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape",
- "1", -1, Tk_Offset(ZnWInfo, full_reshape), 0, NULL, 0},
- {TK_OPTION_PIXELS, "-height", "height", "Height",
- "7c", -1, Tk_Offset(ZnWInfo, opt_height), 0, NULL, CONFIG_REQUEST_GEOM},
- {TK_OPTION_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground",
- "#c3c3c3", -1, Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption,
- CONFIG_REDISPLAY},
- {TK_OPTION_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor",
- "Black", -1, Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption, CONFIG_REDISPLAY},
- {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness",
- "2", -1, Tk_Offset(ZnWInfo, highlight_width), 0, NULL, CONFIG_REQUEST_GEOM|CONFIG_DAMAGE_ALL},
- {TK_OPTION_CUSTOM, "-insertbackground", "insertBackground", "Foreground",
- "Black", -1, Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption, 0},
- {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
- "300", -1, Tk_Offset(ZnWInfo, insert_off_time), 0, NULL, CONFIG_FOCUS},
- {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
- "600", -1, Tk_Offset(ZnWInfo, insert_on_time), 0, NULL, CONFIG_FOCUS},
- {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
- "2", -1, Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL, CONFIG_FOCUS_ITEM},
-#ifdef ATC
- {TK_OPTION_STRING, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol",
- "AtcSymbol19", Tk_Offset(ZnWInfo, map_symbol_obj), -1,
- TK_CONFIG_NULL_OK, NULL, CONFIG_MAP_SYMBOL|CONFIG_INVALIDATE_MAPS},
- {TK_OPTION_FONT, "-maptextfont", "mapTextFont", "MapTextFont",
- "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
- -1, Tk_Offset(ZnWInfo, map_text_font), 0, NULL, CONFIG_MAP_FONT},
- {TK_OPTION_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1",
- -1, Tk_Offset(ZnWInfo, om_group_id), 0, NULL, CONFIG_OM},
-#endif
- {TK_OPTION_INT, "-pickaperture", "pickAperture", "PickAperture",
- "1", -1, Tk_Offset(ZnWInfo, pick_aperture), 0, NULL, 0},
- {TK_OPTION_CUSTOM, "-relief", "relief", "Relief",
- "flat", -1, Tk_Offset(ZnWInfo, relief), 0, &reliefOption, CONFIG_REDISPLAY},
- {TK_OPTION_INT, "-render", "render", "Render",
- "-1", -1, Tk_Offset(ZnWInfo, render), 0, NULL, 0},
- {TK_OPTION_BOOLEAN, "-reshape", "reshape", "Reshape",
- "1", -1, Tk_Offset(ZnWInfo, reshape), 0, NULL, 0},
- {TK_OPTION_STRING, "-scrollregion", "scrollRegion", "ScrollRegion",
- "", Tk_Offset(ZnWInfo, region), -1,
- TK_CONFIG_NULL_OK, NULL, CONFIG_SET_ORIGIN|CONFIG_SCROLL_REGION},
- {TK_OPTION_CUSTOM, "-selectbackground", "selectBackground", "Foreground",
- "#a0a0a0", -1, Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption, 0},
-#ifdef ATC
- {TK_OPTION_DOUBLE, "-speedvectorlength", "speedVectorLength",
- "SpeedVectorLength", "3", -1, Tk_Offset(ZnWInfo, speed_vector_length),
- 0, NULL, CONFIG_INVALIDATE_TRACKS},
-#endif
- {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
- NULL, Tk_Offset(ZnWInfo, take_focus), -1, TK_CONFIG_NULL_OK, NULL, 0},
- {TK_OPTION_STRING, "-tile", "tile", "Tile",
- "", Tk_Offset(ZnWInfo, tile_obj), -1, TK_CONFIG_NULL_OK, NULL, CONFIG_TILE|CONFIG_DAMAGE_ALL},
-#ifdef ATC
- {TK_OPTION_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize",
- "6", -1, Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL, CONFIG_INVALIDATE_TRACKS},
- {TK_OPTION_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
- "TrackManagedHistorySize", "6", -1, Tk_Offset(ZnWInfo, track_managed_history_size),
- 0, NULL, CONFIG_INVALIDATE_TRACKS},
- {TK_OPTION_STRING, "-tracksymbol", "trackSymbol", "TrackSymbol",
- "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol_obj), -1,
- 0, NULL, CONFIG_TRACK_SYMBOL|CONFIG_INVALIDATE_TRACKS|CONFIG_INVALIDATE_WPS},
-#endif
- {TK_OPTION_PIXELS, "-width", "width", "Width",
- "10c", -1, Tk_Offset(ZnWInfo, opt_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM},
-#ifdef PTK
- {TK_OPTION_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- "", -1, Tk_Offset(ZnWInfo, x_scroll_cmd), TK_CONFIG_NULL_OK, NULL, 0},
-#else
- {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- "", Tk_Offset(ZnWInfo, x_scroll_cmd), -1, TK_CONFIG_NULL_OK, NULL, 0},
-#endif
- {TK_OPTION_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement",
- "0", -1, Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL, 0},
-#ifdef PTK
- {TK_OPTION_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
- "", -1, Tk_Offset(ZnWInfo, y_scroll_cmd), TK_CONFIG_NULL_OK, NULL, 0},
-#else
- {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
- "", Tk_Offset(ZnWInfo, y_scroll_cmd), -1, TK_CONFIG_NULL_OK, NULL, 0},
-#endif
- {TK_OPTION_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement",
- "0", -1, Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL, 0},
- /*
- * Debug options.
- */
- {TK_OPTION_BOOLEAN, "-drawbboxes", "drawBBoxes",
- "DrawBBoxes", "0", -1, Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL, 0},
- {TK_OPTION_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor",
- "Pink", -1, Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption, 0},
- {TK_OPTION_INT, "-lightangle", "lightAngle", "LightAngle",
- "120", -1, Tk_Offset(ZnWInfo, light_angle), 0, NULL, CONFIG_DAMAGE_ALL},
- {TK_OPTION_BOOLEAN, "-followpointer", "followPointer",
- "FollowPointer", "1", -1, Tk_Offset(ZnWInfo, follow_pointer), 0, NULL, CONFIG_FOLLOW_POINTER},
-
- {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
-};
-#endif
-
-static void CmdDeleted _ANSI_ARGS_((ClientData client_data));
-static void Event _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
-static void Bind _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
-static int FetchSelection _ANSI_ARGS_((ClientData clientData, int offset,
- char *buffer, int maxBytes));
-static void SelectTo _ANSI_ARGS_((ZnItem item, int field, int index));
-static int WidgetObjCmd _ANSI_ARGS_((ClientData client_data,
- Tcl_Interp *, int argc, Tcl_Obj *CONST args[]));
-#ifdef PTK_800
-static int Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi,
- int argc, Tcl_Obj *CONST args[], int flags));
-#else
-static int Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi,
- int argc, Tcl_Obj *CONST args[]));
-#endif
-static void Redisplay _ANSI_ARGS_((ClientData client_data));
-static void Destroy _ANSI_ARGS_((char *mem_ptr));
-static void InitZinc _ANSI_ARGS_((Tcl_Interp *interp));
-static void Focus _ANSI_ARGS_((ZnWInfo *wi, ZnBool got_focus));
-static void Update _ANSI_ARGS_((ZnWInfo *wi));
-static void Repair _ANSI_ARGS_((ZnWInfo *wi));
-
-
-#ifdef PTK_800
-/*
- *----------------------------------------------------------------------
- *
- * ZnReliefParse
- * ZnReliefPrint --
- * Converter for the -relief option.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnReliefParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- ZnReliefStyle *relief_ptr = (ZnReliefStyle *) (widget_rec + offset);
- ZnReliefStyle relief;
- char *value = Tcl_GetString(ovalue);
- int result = TCL_OK;
-
- if (value != NULL) {
- result = ZnGetRelief((ZnWInfo *) widget_rec, value, &relief);
- if (result == TCL_OK) {
- *relief_ptr = relief;
- }
- }
- return result;
-}
-
-static Tcl_Obj *
-ZnReliefPrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
- Tcl_FreeProc **free_proc)
-{
- ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset);
- return Tcl_NewStringObj(ZnNameOfRelief(relief), -1);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnGradientParse
- * ZnGradientPrint --
- * Converter for the -*color* options.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnGradientParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- ZnGradient **grad_ptr = (ZnGradient **) (widget_rec + offset);
- ZnGradient *grad, *prev_grad;
- char *value = Tcl_GetString(ovalue);
-
- prev_grad = *grad_ptr;
- if ((value != NULL) && (*value != '\0')) {
- grad = ZnGetGradient(interp, tkwin, value);
- if (grad == NULL) {
- return TCL_ERROR;
- }
- if (prev_grad != NULL) {
- ZnFreeGradient(prev_grad);
- }
- *grad_ptr = grad;
- }
- return TCL_OK;
-}
-
-static Tcl_Obj *
-ZnGradientPrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
- Tcl_FreeProc **free_proc)
-{
- ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset);
- return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnBitmapParse
- * ZnImageParse
- * ZnImagePrint --
- * Converter for the -*image* options.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnBitmapParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- ZnImage *image_ptr = (ZnImage *) (widget_rec + offset);
- ZnImage image, prev_image;
- char *value = Tcl_GetString(ovalue);
- ZnWInfo *wi = (ZnWInfo*) widget_rec;
- ZnBool is_bmap = True;
-
- prev_image = *image_ptr;
- if ((value != NULL) && (*value != '\0')) {
- image = ZnGetImage(wi, value, NULL, NULL);
- if ((image == ZnUnspecifiedImage) ||
- ! (is_bmap = ZnImageIsBitmap(image))) {
- if (!is_bmap) {
- ZnFreeImage(image, NULL, NULL);
- }
- return TCL_ERROR;
- }
- if (prev_image != NULL) {
- ZnFreeImage(prev_image, NULL, NULL);
- }
- *image_ptr = image;
- }
- else if (prev_image != NULL) {
- ZnFreeImage(prev_image, NULL, NULL);
- *image_ptr = NULL;
- }
-
- return TCL_OK;
-}
-
-static void
-ZnImageUpdate(void *client_data)
-{
- ZnWInfo *wi = (ZnWInfo*) client_data;
-
- ZnDamageAll(wi);
-}
-
-static int
-ZnImageParse(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj *ovalue,
- char *widget_rec,
- int offset)
-{
- ZnImage *image_ptr = (ZnImage *) (widget_rec + offset);
- ZnImage image, prev_image;
- char *value = Tcl_GetString(ovalue);
- ZnWInfo *wi = (ZnWInfo*) widget_rec;
-
- prev_image = *image_ptr;
- if ((value != NULL) && (*value != '\0')) {
- image = ZnGetImage(wi, value, ZnImageUpdate, wi);
- if (image == NULL) {
- return TCL_ERROR;
- }
- if (prev_image != NULL) {
- ZnFreeImage(prev_image, ZnImageUpdate, wi);
- }
- *image_ptr = image;
- }
- else if (prev_image != NULL) {
- ZnFreeImage(prev_image, ZnImageUpdate, wi);
- *image_ptr = NULL;
- }
- return TCL_OK;
-}
-
-static Tcl_Obj *
-ZnImagePrint(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset,
- Tcl_FreeProc **free_proc)
-{
- ZnImage image = *(ZnImage *) (widget_rec + offset);
- return Tcl_NewStringObj(image?ZnNameOfImage(image):"", -1);
-}
-#else
-/*
- *----------------------------------------------------------------------
- *
- * ZnSetReliefOpt
- * ZnGetReliefOpt
- * ZnRestoreReliefOpt --
- * Converter for the -relief option.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnSetReliefOpt(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj **ovalue,
- char *widget_rec,
- int offset,
- char *old_val_ptr,
- int flags)
-{
- ZnReliefStyle *relief_ptr;
- ZnReliefStyle relief;
- char *value = Tcl_GetString(*ovalue);
-
- if (ZnGetRelief((ZnWInfo *) widget_rec, value, &relief) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (offset >= 0) {
- relief_ptr = (ZnReliefStyle *) (widget_rec + offset);
- *((ZnReliefStyle *) old_val_ptr) = *relief_ptr;
- *relief_ptr = relief;
- }
- return TCL_OK;
-}
-
-static Tcl_Obj *
-ZnGetReliefOpt(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset)
-{
- ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset);
- return Tcl_NewStringObj(ZnNameOfRelief(relief), -1);
-}
-
-static void
-ZnRestoreReliefOpt(ClientData client_data,
- Tk_Window tkwin,
- char *val_ptr,
- char *old_val_ptr)
-{
- *(ZnReliefStyle *) val_ptr = *(ZnReliefStyle *) old_val_ptr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnSetGradientOpt
- * ZnGetGradientOpt
- * ZnRestoreGradientOpt --
- * Converter for the -*color* options.
- *
- *----------------------------------------------------------------------
- */
-static int
-ZnSetGradientOpt(ClientData client_data,
- Tcl_Interp *interp,
- Tk_Window tkwin,
- Tcl_Obj **ovalue,
- char *widget_rec,
- int offset,
- char *old_val_ptr,
- int flags)
-{
- ZnGradient **grad_ptr;
- ZnGradient *grad;
- char *value = Tcl_GetString(*ovalue);
-
- if (offset >= 0) {
- if (*value == '\0') {
- grad = NULL;
- }
- else {
- grad = ZnGetGradient(interp, tkwin, value);
- if (grad == NULL) {
- return TCL_ERROR;
- }
- }
- grad_ptr = (ZnGradient **) (widget_rec + offset);
- *(ZnGradient **) old_val_ptr = *grad_ptr;
- *grad_ptr = grad;
- }
- return TCL_OK;
-}
-
-static Tcl_Obj *
-ZnGetGradientOpt(ClientData client_data,
- Tk_Window tkwin,
- char *widget_rec,
- int offset)
-{
- ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset);
- return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1);
-}
-
-static void
-ZnRestoreGradientOpt(ClientData client_data,
- Tk_Window tkwin,
- char *val_ptr,
- char *old_val_ptr)
-{
- if (*(ZnGradient **) val_ptr != NULL) {
- ZnFreeGradient(*(ZnGradient **) val_ptr);
- }
- *(ZnGradient **) val_ptr = *(ZnGradient **) old_val_ptr;
-}
-
-static void
-ZnFreeGradientOpt(ClientData client_data,
- Tk_Window tkwin,
- char *val_ptr)
-{
- if (*(ZnGradient **) val_ptr != NULL) {
- ZnFreeGradient(*(ZnGradient **) val_ptr);
- }
-}
-#endif
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnGetAlphaStipple --
- * Need to be handled per screen/dpy toolkit wide, not on a
- * widget basis.
- *
- *----------------------------------------------------------------------
- */
-static Pixmap
-ZnGetAlphaStipple(ZnWInfo *wi,
- unsigned int val)
-{
- if (val >= 255)
- return None;
- else
- return wi->alpha_stipples[(int) (val / 16)];
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnGetInactiveStipple --
- *
- *----------------------------------------------------------------------
- */
-Pixmap
-ZnGetInactiveStipple(ZnWInfo *wi)
-{
- return ZnGetAlphaStipple(wi, 128);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnNeedRedisplay --
- *
- *----------------------------------------------------------------------
- */
-void
-ZnNeedRedisplay(ZnWInfo *wi)
-{
- if (ISCLEAR(wi->flags, ZN_UPDATE_PENDING) && ISSET(wi->flags, ZN_REALIZED)) {
- /*printf("scheduling an update\n");*/
- Tcl_DoWhenIdle(Redisplay, (ClientData) wi);
- SET(wi->flags, ZN_UPDATE_PENDING);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnGetGlContext --
- *
- *----------------------------------------------------------------------
- */
-#ifdef GL
-ZnGLContextEntry *
-ZnGetGLContext(Display *dpy)
-{
- ZnGLContextEntry *context_entry;
-
- for (context_entry = gl_contexts;
- context_entry && context_entry->dpy != dpy;
- context_entry = context_entry->next);
-
- return context_entry;
-}
-
-ZnGLContextEntry *
-ZnGLMakeCurrent(Display *dpy,
- ZnWInfo *wi)
-{
- ZnGLContextEntry *ce;
-
- ce = ZnGetGLContext(dpy);
-
- if (!wi) {
- /* Get a zinc widget from the context struct
- * for this display. If no more are left,
- * returns, nothing can be done. This can
- * happen only when freeing images or fonts
- * after the last zinc on a given display has
- * been deleted. In this case the context should
- * be deleted, freeing all resources including
- * textures.
- */
- ZnWInfo **wip = ZnListArray(ce->widgets);
- int i, num = ZnListSize(ce->widgets);
-
- for (i = 0; i <num; i++, wip++) {
- if ((*wip)->win != NULL) {
- wi = *wip;
- break;
- }
- }
- if (!wi) {
- return NULL;
- }
- }
-#ifdef _WIN32
- ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
- ce->hdc = GetDC(ce->hwnd);
- SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);
-
- if (!wglMakeCurrent(ce->hdc, ce->context)) {
- fprintf(stderr, "Can't make the GL context current: %d\n", GetLastError());
- }
-#else
- glXMakeCurrent(dpy, Tk_WindowId(wi->win), ce->context);
-#endif
- return ce;
-}
-
-void
-ZnGLReleaseContext(ZnGLContextEntry *ce)
-{
- if (ce) {
-#ifdef _WIN32
- wglMakeCurrent(NULL, NULL);
- ReleaseDC(ce->hwnd, ce->hdc);
-#else
- /*glXMakeCurrent(ce->dpy, None, NULL);*/
-#endif
- }
-}
-
-static void
-ZnGLSwapBuffers(ZnGLContextEntry *ce,
- ZnWInfo *wi)
-{
- if (ce) {
-#ifdef _WIN32
- SwapBuffers(ce->hdc);
-#else
- glXSwapBuffers(ce->dpy, Tk_WindowId(wi->win));
-#endif
- }
-}
-#endif
-
-
-#ifdef GL
-static void
-InitRendering1(ZnWInfo *wi)
-{
-
- if (wi->render) {
-# ifndef _WIN32
- ZnGLContextEntry *ce;
- ZnGLContext gl_context;
- XVisualInfo *gl_visual = NULL;
- Colormap colormap = 0;
-
- ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL));
-
- if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
- fprintf(stderr, "GLX version %d.%d\n", ZnMajorGlx, ZnMinorGlx);
- }
-
- /*
- * Look for a matching context already available.
- */
- ce = ZnGetGLContext(wi->dpy);
- if (ce) {
- gl_context = ce->context;
- gl_visual = ce->visual;
- colormap = ce->colormap;
- ZnListAdd(ce->widgets, &wi, ZnListTail);
- }
- else {
- int val;
-
- gl_visual = glXChooseVisual(wi->dpy,
- XScreenNumberOfScreen(wi->screen),
- ZnGLAttribs);
- if (!gl_visual) {
- fprintf(stderr, "No glx visual\n");
- }
- else {
- gl_context = glXCreateContext(wi->dpy, gl_visual,
- NULL, wi->render==1);
- if (!gl_context) {
- fprintf(stderr, "No glx context\n");
- }
- else {
- colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen),
- gl_visual->visual, AllocNone);
- ce = ZnMalloc(sizeof(ZnGLContextEntry));
- ce->context = gl_context;
- ce->visual = gl_visual;
- ce->colormap = colormap;
- ce->dpy = wi->dpy;
- ce->max_tex_size = 64; /* Minimum value is always valid */
- ce->max_line_width = 1;
- ce->max_point_width = 1;
- ce->next = gl_contexts;
- gl_contexts = ce;
- ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
- ZnListAdd(ce->widgets, &wi, ZnListTail);
-
- if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
- fprintf(stderr, " Visual : 0x%x, ",
- (int) gl_visual->visualid);
- glXGetConfig(wi->dpy, gl_visual, GLX_RGBA, &val);
- fprintf(stderr, "RGBA : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_DOUBLEBUFFER, &val);
- fprintf(stderr, "Double Buffer : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_STENCIL_SIZE, &val);
- fprintf(stderr, "Stencil : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_BUFFER_SIZE, &val);
- fprintf(stderr, "depth : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_RED_SIZE, &val);
- fprintf(stderr, "red : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_GREEN_SIZE, &val);
- fprintf(stderr, "green : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_BLUE_SIZE, &val);
- fprintf(stderr, "blue : %d, ", val);
- glXGetConfig(wi->dpy, gl_visual, GLX_ALPHA_SIZE, &val);
- fprintf(stderr, "alpha : %d\n", val);
- fprintf(stderr, " Direct Rendering: %d\n",
- glXIsDirect(wi->dpy, gl_context));
- }
- }
- }
- }
- if (gl_visual && colormap) {
- Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap);
- }
-# endif /* _WIN32 */
- }
-}
-
-static void
-InitRendering2(ZnWInfo *wi)
-{
- ZnGLContextEntry *ce;
- ZnGLContext gl_context;
- GLfloat r[2]; /* Min, Max */
- GLint i[1];
-
- if (wi->render) {
-# ifdef _WIN32
- /*
- * Look for a matching context already available.
- */
- ce = ZnGetGLContext(wi->dpy);
- if (ce) {
- gl_context = ce->context;
- ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
- ce->hdc = GetDC(ce->hwnd);
- ZnListAdd(ce->widgets, &wi, ZnListTail);
- SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);
- }
- else {
- ce = ZnMalloc(sizeof(ZnGLContextEntry));
- ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
- ce->hdc = GetDC(ce->hwnd);
- ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
- ZnListAdd(ce->widgets, &wi, ZnListTail);
-
- memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
- ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- ce->pfd.nVersion = 1;
- ce->pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- ce->pfd.iPixelType = PFD_TYPE_RGBA;
- ce->pfd.cRedBits = 8;
- ce->pfd.cGreenBits = 8;
- ce->pfd.cBlueBits = 8;
- ce->pfd.cAlphaBits = 8;
- ce->pfd.cStencilBits = 8;
- ce->pfd.iLayerType = PFD_MAIN_PLANE;
- ce->ipixel = ChoosePixelFormat(ce->hdc, &ce->pfd);
- /*printf("ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d hdc=%d\n",
- ce->ipixel, ce->pfd.dwFlags,
- PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
- ce->pfd.iPixelType==PFD_TYPE_RGBA,
- ce->hdc);*/
- if (!ce->ipixel ||
- (ce->pfd.cRedBits != 8) || (ce->pfd.cGreenBits != 8) || (ce->pfd.cBlueBits != 8) ||
- (ce->pfd.cStencilBits != 8)) {
- fprintf(stderr, "ChoosePixelFormat failed\n");
- }
-
- if (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE) {
- gl_context = wglCreateContext(ce->hdc);
- if (gl_context) {
- ce->context = gl_context;
- ce->dpy = wi->dpy;
- ce->max_tex_size = 64; /* Minimum value is always valid */
- ce->max_line_width = 1;
- ce->max_point_width = 1;
- ce->next = gl_contexts;
- gl_contexts = ce;
- }
- else {
- fprintf(stderr, "wglCreateContext failed\n");
- ZnFree(ce);
- }
- }
- else {
- ZnFree(ce);
- }
- }
- ReleaseDC(ce->hwnd, ce->hdc);
-#endif
-
- ce = ZnGLMakeCurrent(wi->dpy, wi);
- glGetFloatv(ZN_GL_LINE_WIDTH_RANGE, r);
- ce->max_line_width = r[1];
- glGetFloatv(ZN_GL_POINT_SIZE_RANGE, r);
- ce->max_point_width = r[1];
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, i);
- ce->max_tex_size = (unsigned int) i[0];
-
- if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
- fprintf(stderr, "OpenGL version %s\n",
- (char *) glGetString(GL_VERSION));
- fprintf(stderr, " Rendering engine: %s, ",
- (char *) glGetString(GL_RENDERER));
- fprintf(stderr, " Vendor: %s\n",
- (char *) glGetString(GL_VENDOR));
- fprintf(stderr, " Available extensions: %s\n",
- (char *) glGetString(GL_EXTENSIONS));
- fprintf(stderr, "Max antialiased line width: %g\n",
- ce->max_line_width);
- fprintf(stderr, "Max antialiased point size: %g\n",
- ce->max_point_width);
- fprintf(stderr, "Max texture size: %d\n",
- ce->max_tex_size);
- }
-
- ZnGLReleaseContext(ce);
- }
-}
-#endif /* GL */
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZincObjCmd --
- *
- * This procedure is invoked to process the "zinc" Tcl
- * command. It creates a new "zinc" widget.
- *
- *----------------------------------------------------------------------
- */
-EXTERN int
-ZincObjCmd(ClientData client_data, /* Main window associated with
- * interpreter. */
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- Tcl_Obj *CONST args[]) /* Argument strings. */
-{
- Tk_Window top_w = (Tk_Window) client_data;
- ZnWInfo *wi;
- Tk_Window tkwin;
-#ifndef PTK_800
- Tk_OptionTable opt_table;
-#endif
- unsigned int num;
- ZnBool has_gl = False;
-#ifndef _WIN32
-# if defined(GL) || defined(SHAPE)
- int major_op, first_err, first_evt;
-# endif
-# ifdef GL
- Display *dpy = Tk_Display(top_w);
- Screen *screen = Tk_Screen(top_w);
-# endif
-#endif
-
- InitZinc(interp);
-
-#ifdef GL
-# ifdef _WIN32
- has_gl = True;
-# else
- if (XQueryExtension(dpy, "GLX", &major_op, &first_evt, &first_err)) {
- if (glXQueryExtension(dpy, &first_err, &first_evt)) {
- if (glXQueryVersion(dpy, &ZnMajorGlx, &ZnMinorGlx)) {
- if ((ZnMajorGlx == 1) && (ZnMinorGlx >= 1)) {
- has_gl = True;
- }
- }
- }
- }
- if (has_gl) {
- XVisualInfo *visual = glXChooseVisual(dpy,
- XScreenNumberOfScreen(screen),
- ZnGLAttribs);
- if (visual) {
- XFree(visual);
- }
- else {
- has_gl = False;
- }
- }
-# endif
-#endif
-
- if (argc == 1) {
- Tcl_AppendResult(interp, VERSION, NULL);
- Tcl_AppendResult(interp, " X11", NULL);
-#ifdef GL
-# ifdef _WIN32
- Tcl_AppendResult(interp, " GL", NULL);
-# else
- if (has_gl) {
- Tcl_AppendResult(interp, " GL", NULL);
- }
-# endif
-#endif
- return TCL_OK;
- }
-
- tkwin = Tk_CreateWindowFromPath(interp, top_w, Tcl_GetString(args[1]), NULL);
- if (tkwin == NULL) {
- return TCL_ERROR;
- }
-
-#ifndef PTK_800
- opt_table = Tk_CreateOptionTable(interp, option_specs);
- #endif
-
- Tk_SetClass(tkwin, "Zinc");
-
- /*
- * Allocate and initialize the widget record.
- */
- wi = (ZnWInfo *) ZnMalloc(sizeof(ZnWInfo));
- wi->win = tkwin;
- wi->interp = interp;
- wi->dpy = Tk_Display(tkwin);
- wi->screen = Tk_Screen(tkwin);
- wi->flags = 0;
- wi->render = -1;
- wi->real_top = None;
-
- ASSIGN(wi->flags, ZN_HAS_GL, has_gl);
-#if defined(SHAPE) && !defined(_WIN32)
- ASSIGN(wi->flags, ZN_HAS_X_SHAPE,
- XQueryExtension(wi->dpy, "SHAPE", &major_op, &first_evt, &first_err));
- wi->reshape = wi->full_reshape = True;
-#else
- CLEAR(wi->flags, ZN_HAS_X_SHAPE);
- wi->reshape = wi->full_reshape = False;
-#endif
-
-#ifdef PTK
-#ifdef PTK_800
- wi->cmd = Lang_CreateWidget(interp, tkwin, (Tcl_CmdProc *) WidgetObjCmd,
- (ClientData) wi, CmdDeleted);
-#else
- wi->cmd = Lang_CreateWidget(interp, tkwin, WidgetObjCmd, (ClientData) wi, CmdDeleted);
-#endif
-#else
- wi->cmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), WidgetObjCmd,
- (ClientData) wi, CmdDeleted);
-#endif
-#ifndef PTK_800
- wi->opt_table = opt_table;
-#endif
- wi->binding_table = 0;
- wi->fore_color = NULL;
- wi->back_color = NULL;
- wi->relief_grad = NULL;
- wi->bbox_color = NULL;
- wi->draw_bboxes = 0;
- wi->light_angle = 120;
- wi->follow_pointer = 0;
- wi->border_width = 0;
- wi->relief = ZN_RELIEF_FLAT;
- wi->opt_width = None;
- wi->opt_height = None;
- wi->font = 0;
-#ifdef ATC
- wi->track_visible_history_size = 0;
- wi->track_managed_history_size = 0;
- wi->speed_vector_length = 0;
- wi->map_text_font = 0;
-# ifdef GL
- wi->font_tfi = NULL;
- wi->map_font_tfi = NULL;
-# endif
- wi->map_distance_symbol = ZnUnspecifiedImage;
- wi->track_symbol = ZnUnspecifiedImage;
-# ifndef PTK_800
- wi->map_symbol_obj = NULL;
- wi->track_symbol_obj = NULL;
-# endif
-#endif
- wi->tile = ZnUnspecifiedImage;
-#ifndef PTK_800
- wi->tile_obj = NULL;
-#endif
- wi->cursor = None;
- wi->hot_item = ZN_NO_ITEM;
- wi->hot_prev = ZN_NO_ITEM;
- wi->confine = 0;
- wi->origin.x = wi->origin.y = 0;
- wi->scroll_xo = wi->scroll_yo = 0;
- wi->scroll_xc = wi->scroll_yc = 0;
- wi->x_scroll_incr = wi->y_scroll_incr = 0;
- wi->x_scroll_cmd = wi->y_scroll_cmd = NULL;
- wi->region = NULL;
-
- wi->id_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(wi->id_table, TCL_ONE_WORD_KEYS);
- wi->t_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(wi->t_table, TCL_STRING_KEYS);
-
- wi->obj_id = 1;
- wi->num_items = 0;
-
- wi->top_group = ZnCreateItem(wi, ZnGroup, 0, NULL);
-
-#ifdef ATC
- wi->om_group_id = 0;
- wi->om_group = wi->top_group;
- OmRegister((void *) wi, ZnSendTrackToOm, ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
-#endif
- wi->gc = 0;
- wi->draw_buffer = 0;
- wi->pick_aperture = 0;
- wi->state = 0;
- memset(&wi->pick_event, 0, sizeof(XEvent));
- wi->new_item = wi->current_item = ZN_NO_ITEM;
- wi->new_part = wi->current_part = ZN_NO_PART;
- wi->focus_item = ZN_NO_ITEM;
- wi->focus_field = ZN_NO_PART;
-
- CLEAR(wi->flags, ZN_MONITORING);
-#ifndef _WIN32
- wi->total_draw_chrono = ZnNewChrono("Total draw time");
- wi->this_draw_chrono = ZnNewChrono("Last draw time");
-#endif
- wi->damaged_area_w = wi->damaged_area_h = 0;
-
- /*
- * Text management init.
- */
- wi->text_info.sel_color = NULL;
- wi->text_info.sel_item = ZN_NO_ITEM;
- wi->text_info.sel_field = ZN_NO_PART;
- wi->text_info.sel_first = -1;
- wi->text_info.sel_last = -1;
- wi->text_info.anchor_item = ZN_NO_ITEM;
- wi->text_info.anchor_field = ZN_NO_PART;
- wi->text_info.sel_anchor = 0;
- wi->text_info.insert_color = NULL;
- wi->text_info.insert_width = 0;
- wi->text_info.cursor_on = False;
- wi->insert_on_time = 0;
- wi->insert_off_time = 0;
- wi->blink_handler = NULL;
- wi->take_focus = NULL;
- wi->highlight_width = 0;
- wi->highlight_color = NULL;
- wi->highlight_bg_color = NULL;
- ZnResetBBox(&wi->exposed_area);
- ZnResetBBox(&wi->damaged_area);
-
- ZnInitClipStack(wi);
- ZnInitTransformStack(wi);
-
- for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) {
- char name[TCL_INTEGER_SPACE+12];
-
- sprintf(name, "AlphaStipple%d", num);
- wi->alpha_stipples[num] = Tk_GetBitmap(interp, tkwin, Tk_GetUid(name));
- }
-
- Tk_CreateEventHandler(tkwin,
- ExposureMask|StructureNotifyMask|FocusChangeMask,
- Event, (ClientData) wi);
- Tk_CreateEventHandler(tkwin, KeyPressMask|KeyReleaseMask|
- ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
- LeaveWindowMask|PointerMotionMask|VirtualEventMask,
- Bind, (ClientData) wi);
- Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING,
- FetchSelection, (ClientData) wi, XA_STRING);
-
-#ifdef PTK_800
- if (Configure(interp, wi, argc-2, args+2, 0) != TCL_OK) {
- Tk_DestroyWindow(tkwin);
- return TCL_ERROR;
- }
-#else
- if (Tk_InitOptions(interp, (char *) wi, opt_table, tkwin) != TCL_OK) {
- Tk_DestroyWindow(tkwin);
- return TCL_ERROR;
- }
-
- if (Configure(interp, wi, argc-2, args+2) != TCL_OK) {
- Tk_DestroyWindow(tkwin);
- return TCL_ERROR;
- }
-#endif
-
- wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0;
- wi->damaged_area.corner.x = wi->width = wi->opt_width;
- wi->damaged_area.corner.y = wi->height = wi->opt_height;
-
- if (!wi->render) {
- /*
- * Allocate double buffer pixmap/image.
- */
- wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
- wi->width, wi->height, Tk_Depth(wi->win));
- }
-#ifdef GL
- else {
- InitRendering1(wi);
- }
-#endif
-
-#ifdef PTK
- Tcl_SetObjResult(interp, LangWidgetObj(interp, tkwin));
-#else
- Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1));
-#endif
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * EncodeItemPart --
- *
- * Form a ClientData value from an item/part that is suitable
- * as a key in a binding table.
- *
- *----------------------------------------------------------------------
- */
-ClientData
-EncodeItemPart(ZnItem item,
- int part)
-{
- if (part >= 0) {
- ZnFieldSet fs;
- if (!item->class->GetFieldSet) {
- return item;
- }
- fs = item->class->GetFieldSet(item);
- return (ClientData) (ZnFIELD.GetFieldStruct(fs, part % (int) ZnFIELD.NumFields(fs)));
- }
- else if (part == ZN_NO_PART) {
- return item;
- }
- return (ClientData) (((char *) item)-part);
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * All tag search procs below are lifted from tkCanvas.c, then
- * modified to match our needs.
- *
- *--------------------------------------------------------------
- */
-
-/*
- *--------------------------------------------------------------
- *
- * TagSearchExprInit --
- *
- * This procedure allocates and initializes one
- * TagSearchExpr struct.
- *
- *--------------------------------------------------------------
- */
-static void
-TagSearchExprInit(TagSearchExpr **expr_var)
-{
- TagSearchExpr* expr = *expr_var;
-
- if (! expr) {
- expr = (TagSearchExpr *) ZnMalloc(sizeof(TagSearchExpr));
- expr->allocated = 0;
- expr->uids = NULL;
- expr->next = NULL;
- }
- expr->uid = NULL;
- expr->index = 0;
- expr->length = 0;
- *expr_var = expr;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * TagSearchExprDestroy --
- *
- * This procedure destroys one TagSearchExpr structure.
- *
- *--------------------------------------------------------------
- */
-static void
-TagSearchExprDestroy(TagSearchExpr *expr)
-{
- if (expr) {
- if (expr->uids) {
- ZnFree(expr->uids);
- }
- ZnFree(expr);
- }
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * TagSearchScanExpr --
- *
- * This recursive procedure is called to scan a tag expression
- * and compile it into an array of Tk_Uids.
- *
- * Results:
- * The return value indicates if the tagOrId expression
- * was successfully scanned (syntax).
- * The information at *search is initialized
- * such that a call to ZnTagSearchFirst, followed by
- * successive calls to ZnTagSearchNext will return items
- * that match tag.
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-static int
-TagSearchScanExpr(Tcl_Interp *interp, /* Current interpreter. */
- ZnTagSearch *search, /* Search data */
- TagSearchExpr *expr) /* Compiled expression result */
-{
- int looking_for_tag; /* When true, scanner expects next char(s)
- * to be a tag, else operand expected */
- int found_tag; /* One or more tags found */
- int found_endquote; /* For quoted tag string parsing */
- int negate_result; /* Pending negation of next tag value */
- char *tag; /* tag from tag expression string */
- char c;
-
- negate_result = 0;
- found_tag = 0;
- looking_for_tag = 1;
- while (search->tag_index < search->tag_len) {
- c = search->tag[search->tag_index++];
-
- if (expr->allocated == expr->index) {
- expr->allocated += 15;
- if (expr->uids) {
- expr->uids = (Tk_Uid *) ZnRealloc((char *) expr->uids,
- expr->allocated * sizeof(Tk_Uid));
- }
- else {
- expr->uids = (Tk_Uid *) ZnMalloc(expr->allocated * sizeof(Tk_Uid));
- }
- }
-
- if (looking_for_tag) {
- switch (c) {
- case ' ': /* ignore unquoted whitespace */
- case '\t':
- case '\n':
- case '\r':
- break;
- case '!': /* negate next tag or subexpr */
- if (looking_for_tag > 1) {
- Tcl_AppendResult(interp, "Too many '!' in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- looking_for_tag++;
- negate_result = 1;
- break;
- case '(': /* scan (negated) subexpr recursively */
- if (negate_result) {
- expr->uids[expr->index++] = neg_paren_uid;
- negate_result = 0;
- }
- else {
- expr->uids[expr->index++] = paren_uid;
- }
- if (TagSearchScanExpr(interp, search, expr) != TCL_OK) {
- /* Result string should be already set
- * by nested call to tag_expr_scan() */
- return TCL_ERROR;
- }
- looking_for_tag = 0;
- found_tag = 1;
- break;
- case '"': /* quoted tag string */
- if (negate_result) {
- expr->uids[expr->index++] = neg_tag_val_uid;
- negate_result = 0;
- }
- else {
- expr->uids[expr->index++] = tag_val_uid;
- }
- tag = search->rewrite_buf;
- found_endquote = 0;
- while (search->tag_index < search->tag_len) {
- c = search->tag[search->tag_index++];
- if (c == '\\') {
- c = search->tag[search->tag_index++];
- }
- if (c == '"') {
- found_endquote = 1;
- break;
- }
- *tag++ = c;
- }
- if (! found_endquote) {
- Tcl_AppendResult(interp, "Missing endquote in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (! (tag - search->rewrite_buf)) {
- Tcl_AppendResult(interp,
- "Null quoted tag string in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- *tag++ = '\0';
- expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
- looking_for_tag = 0;
- found_tag = 1;
- break;
- case '&': /* illegal chars when looking for tag */
- case '|':
- case '^':
- case ')':
- Tcl_AppendResult(interp, "Unexpected operator in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- default: /* unquoted tag string */
- if (negate_result) {
- expr->uids[expr->index++] = neg_tag_val_uid;
- negate_result = 0;
- }
- else {
- expr->uids[expr->index++] = tag_val_uid;
- }
- tag = search->rewrite_buf;
- *tag++ = c;
- /* copy rest of tag, including any embedded whitespace */
- while (search->tag_index < search->tag_len) {
- c = search->tag[search->tag_index];
- if ((c == '!') || (c == '&') || (c == '|') || (c == '^') ||
- (c == '(') || (c == ')') || (c == '"')) {
- break;
- }
- *tag++ = c;
- search->tag_index++;
- }
- /* remove trailing whitespace */
- while (1) {
- c = *--tag;
- /* there must have been one non-whitespace char,
- * so this will terminate */
- if ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r')) {
- break;
- }
- }
- *++tag = '\0';
- expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
- looking_for_tag = 0;
- found_tag = 1;
- }
-
- }
- else { /* ! looking_for_tag */
- switch (c) {
- case ' ' : /* ignore whitespace */
- case '\t' :
- case '\n' :
- case '\r' :
- break;
- case '&' : /* AND operator */
- c = search->tag[search->tag_index++];
- if (c != '&') {
- Tcl_AppendResult(interp, "Singleton '&' in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- expr->uids[expr->index++] = and_uid;
- looking_for_tag = 1;
- break;
- case '|' : /* OR operator */
- c = search->tag[search->tag_index++];
- if (c != '|') {
- Tcl_AppendResult(interp, "Singleton '|' in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- expr->uids[expr->index++] = or_uid;
- looking_for_tag = 1;
- break;
- case '^' : /* XOR operator */
- expr->uids[expr->index++] = xor_uid;
- looking_for_tag = 1;
- break;
- case ')' : /* end subexpression */
- expr->uids[expr->index++] = end_paren_uid;
- goto breakwhile;
- default : /* syntax error */
- Tcl_AppendResult(interp,
- "Invalid boolean operator in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
- }
- breakwhile:
- if (found_tag && ! looking_for_tag) {
- return TCL_OK;
- }
- Tcl_AppendResult(interp, "Missing tag in tag search expression",
- (char *) NULL);
- return TCL_ERROR;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * TagSearchEvalExpr --
- *
- * This recursive procedure is called to eval a tag expression.
- *
- * Results:
- * The return value indicates if the tagOrId expression
- * successfully matched the tags of the current item.
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-static int
-TagSearchEvalExpr(TagSearchExpr *expr, /* Search expression */
- ZnItem item) /* Item being test for match */
-{
- int looking_for_tag; /* When true, scanner expects next char(s)
- * to be a tag, else operand expected */
- int negate_result; /* Pending negation of next tag value */
- Tk_Uid uid;
- int result=0; /* Value of expr so far */
- int paren_depth;
-
- negate_result = 0;
- looking_for_tag = 1;
- while (expr->index < expr->length) {
- uid = expr->uids[expr->index++];
- if (looking_for_tag) {
- if (uid == tag_val_uid) {
- /*
- * assert(expr->index < expr->length);
- */
- uid = expr->uids[expr->index++];
- /*
- * set result 1 if tag is found in item's tags
- */
- result = ZnITEM.HasTag(item, uid) ? 1 : 0;
- }
- else if (uid == neg_tag_val_uid) {
- negate_result = ! negate_result;
- /*
- * assert(expr->index < expr->length);
- */
- uid = expr->uids[expr->index++];
- /*
- * set result 1 if tag is found in item's tags
- */
- result = ZnITEM.HasTag(item, uid) ? 1 : 0;
- }
- else if (uid == paren_uid) {
- /*
- * evaluate subexpressions with recursion
- */
- result = TagSearchEvalExpr(expr, item);
- }
- else if (uid == neg_paren_uid) {
- negate_result = ! negate_result;
- /*
- * evaluate subexpressions with recursion
- */
- result = TagSearchEvalExpr(expr, item);
- /*
- * } else {
- * assert(0);
- */
- }
- if (negate_result) {
- result = ! result;
- negate_result = 0;
- }
- looking_for_tag = 0;
- }
- else { /* ! looking_for_tag */
- if (((uid == and_uid) && (!result)) || ((uid == or_uid) && result)) {
- /*
- * short circuit expression evaluation
- *
- * if result before && is 0, or result before || is 1, then
- * the expression is decided and no further evaluation is needed.
- */
- paren_depth = 0;
- while (expr->index < expr->length) {
- uid = expr->uids[expr->index++];
- if ((uid == tag_val_uid) || (uid == neg_tag_val_uid)) {
- expr->index++;
- continue;
- }
- if ((uid == paren_uid) || (uid == neg_paren_uid)) {
- paren_depth++;
- continue;
- }
- if (uid == end_paren_uid) {
- paren_depth--;
- if (paren_depth < 0) {
- break;
- }
- }
- }
- return result;
-
- }
- else if (uid == xor_uid) {
- /*
- * if the previous result was 1 then negate the next result.
- */
- negate_result = result;
- }
- else if (uid == end_paren_uid) {
- return result;
- /*
- * } else {
- * assert(0);
- */
- }
- looking_for_tag = 1;
- }
- }
- /*
- * assert(! looking_for_tag);
- */
- return result;
-}
-
-
-static ZnItem
-LookupGroupFromPath(ZnItem start,
- Tk_Uid *names,
- unsigned int num_names)
-{
- Tk_Uid name, *tags;
- unsigned int count;
- ZnBool recursive;
- ZnItem result, current = ZnGroupHead(start);
-
- if (num_names == 0) {
- return start;
- }
-
- name = names[1];
- recursive = (names[0] == star_uid);
- /* printf("LookupGroupFromPath; group: %d, nom: %s, recursive: %s\n",
- start->id, name, names[0]);*/
- while (current != ZN_NO_ITEM) {
- if ((current->class == ZnGroup) && (current->tags)) {
- tags = ZnListArray(current->tags);
- count = ZnListSize(current->tags);
- for (; count > 0; tags++, count--) {
- if (name == *tags) {
- if (num_names > 2) {
- result = LookupGroupFromPath(current, names+2, num_names-2);
- return result;
- }
- else {
- return current;
- }
- }
- }
- /*
- * This group doesn't match try to search depth first.
- */
- if (recursive) {
- result = LookupGroupFromPath(current, names, num_names);
- if (result != ZN_NO_ITEM) {
- return result;
- }
- }
- }
- current = current->next;
- }
-
- return ZN_NO_ITEM;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnTagSearchScan --
- *
- * This procedure is called to initiate an enumeration of
- * all items in a given zinc that contain a tag that matches
- * the tagOrId expression.
- *
- * Results:
- * The return value indicates if the tagOrId expression
- * was successfully scanned (syntax).
- * The information at *search is initialized such that a
- * call to ZnTagSearchFirst, followed by successive calls
- * to ZnTagSearchNext will return items that match tag.
- *
- * Side effects:
- * search is linked into a list of searches in progress
- * in zinc, so that elements can safely be deleted while
- * the search is in progress.
- *
- *--------------------------------------------------------------
- */
-static int
-ZnTagSearchScan(ZnWInfo *wi,
- Tcl_Obj *tag_obj, /* Object giving tag value, NULL
- * is the same as 'all'. */
- ZnTagSearch **search_var) /* Record describing tag search;
- * will be initialized here. */
-{
- Tk_Uid tag;
- int i;
- ZnTagSearch *search;
- ZnItem group = wi->top_group;
- ZnBool recursive = True;
-
- if (tag_obj) {
- tag = Tcl_GetString(tag_obj);
- }
- else {
- tag = all_uid;
- }
-
- /*
- * Initialize the search.
- */
- if (*search_var) {
- search = *search_var;
- }
- else {
- /* Allocate primary search struct on first call */
- *search_var = search = (ZnTagSearch *) ZnMalloc(sizeof(ZnTagSearch));
- search->expr = NULL;
-
- /* Allocate buffer for rewritten tags (after de-escaping) */
- search->rewrite_buf_alloc = 100;
- search->rewrite_buf = ZnMalloc(search->rewrite_buf_alloc);
- search->item_stack = ZnListNew(16, sizeof(ZnItem));
- }
- TagSearchExprInit(&(search->expr));
-
- /* How long is the tagOrId ? */
- search->tag_len = strlen(tag);
-
- /*
- * Short-circuit impossible searches for null tags and
- * mark the search as 'over' for ZnTagSearchFirst and
- * ZnTagSearchNext. This test must not be migrated before
- * allocating search structures or special care must be
- * taken in ZnTagSearchDestroy to avoid deallocating unallocated
- * memory.
- */
- if (search->tag_len == 0) {
- search->over = True;
- return TCL_OK;
- }
-
- /*
- * If a path specification exists in the tag, strip it from the
- * tag and search for a matching group.
- */
- if (strpbrk(tag, ".*")) {
- Tk_Uid path;
- char c, *next;
- unsigned int id;
- Tcl_HashEntry *entry;
-
- ZnListEmpty(ZnWorkStrings);
- recursive = False;
- if ((*tag == '.') || (*tag == '*')) {
- recursive = (*tag == '*');
- tag++;
- }
- path = tag;
- while ((next = strpbrk(path, ".*"))) {
- if (isdigit(*path)) {
- if (path == tag) { /* Group id is ok only in first section. */
- c = *next;
- *next = '\0';
- id = strtoul(path, NULL, 10);
- *next = c;
- group = wi->hot_item;
- if ((group == ZN_NO_ITEM) || (group->id != id)) {
- entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
- if (entry != NULL) {
- group = (ZnItem) Tcl_GetHashValue(entry);
- }
- else {
- Tcl_AppendResult(wi->interp, "unknown group in path \"",
- tag, "\"", NULL);
- return TCL_ERROR;
- }
- }
- if (group->class != ZnGroup) {
- Tcl_AppendResult(wi->interp, "item is not a group in path \"",
- tag, "\"", NULL);
- return TCL_ERROR;
- }
- }
- else {
- Tcl_AppendResult(wi->interp, "misplaced group id in path \"",
- tag, "\"", NULL);
- return TCL_ERROR;
- }
- }
- else {
- ZnListAdd(ZnWorkStrings,
- (void *) (recursive ? &star_uid : &dot_uid),
- ZnListTail);
- c = *next;
- *next = '\0';
- path = Tk_GetUid(path);
- *next = c;
- ZnListAdd(ZnWorkStrings, (void *) &path, ZnListTail);
- }
- recursive = (*next == '*');
- path = next+1;
- }
-
- group = LookupGroupFromPath(group,
- ZnListArray(ZnWorkStrings),
- ZnListSize(ZnWorkStrings));
- if (group == ZN_NO_ITEM) {
- Tcl_AppendResult(wi->interp, "path does not lead to a valid group\"",
- tag, "\"", NULL);
- return TCL_ERROR;
- }
-
- /*
- * Adjust tag to strip the path.
- */
- tag = path;
- search->tag_len = strlen(tag);
- /*
- * If the tag consist only in a path description
- * assume that the tag all is implied.
- */
- if (search->tag_len == 0) {
- tag = all_uid;
- search->tag_len = strlen(tag);
- }
- }
-
- /*
- * Make sure there is enough buffer to hold rewritten tags (30%).
- */
- if ((unsigned int)(search->tag_len*1.3) >= search->rewrite_buf_alloc) {
- search->rewrite_buf_alloc = (unsigned int) (search->tag_len*1.3);
- search->rewrite_buf = ZnRealloc(search->rewrite_buf,
- search->rewrite_buf_alloc);
- }
-
- /* Initialize search */
- search->wi = wi;
- search->over = False;
- search->type = 0;
- search->group = group;
- search->recursive = recursive;
- ZnListEmpty(search->item_stack);
-
- /*
- * Find the first matching item in one of several ways. If the tag
- * is a number then it selects the single item with the matching
- * identifier.
- */
- if (isdigit(*tag)) {
- char *end;
-
- search->id = strtoul(tag, &end, 0);
- if (*end == 0) {
- search->type = 1;
- return TCL_OK;
- }
- }
-
- /*
- * Pre-scan tag for at least one unquoted "&&" "||" "^" "!"
- * if not found then use string as simple tag
- */
- for (i = 0; i < search->tag_len; i++) {
- if (tag[i] == '"') {
- i++;
- for ( ; i < search->tag_len; i++) {
- if (tag[i] == '\\') {
- i++;
- continue;
- }
- if (tag[i] == '"') {
- break;
- }
- }
- }
- else {
- if (((tag[i] == '&') && (tag[i+1] == '&')) ||
- ((tag[i] == '|') && (tag[i+1] == '|')) ||
- (tag[i] == '^') || (tag[i] == '!')) {
- search->type = 4;
- break;
- }
- }
- }
-
- search->tag = tag;
- search->tag_index = 0;
- if (search->type == 4) {
- /*
- * an operator was found in the prescan, so
- * now compile the tag expression into array of Tk_Uid
- * flagging any syntax errors found
- */
- if (TagSearchScanExpr(wi->interp, search, search->expr) != TCL_OK) {
- /* Syntax error in tag expression */
- /* Result message set by TagSearchScanExpr */
- return TCL_ERROR;
- }
- search->expr->length = search->expr->index;
- }
- else {
- /*
- * For all other tags convert to a UID.
- */
- search->expr->uid = Tk_GetUid(tag);
-
- if (search->expr->uid == all_uid) {
- /*
- * All items match.
- */
- search->type = 2;
- }
- else {
- /*
- * Optimized single-tag search
- */
- search->type = 3;
- }
- }
- return TCL_OK;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnTagSearchFirst --
- *
- * This procedure is called to get the first item
- * item that matches a preestablished search predicate
- * that was set by TagSearchScan.
- *
- * Results:
- * The return value is a pointer to the first item, or NULL
- * if there is no such item. The information at *search
- * is updated such that successive calls to ZnTagSearchNext
- * will return successive items.
- *
- * Side effects:
- * *search is linked into a list of searches in progress
- * in zinc, so that elements can safely be deleted while
- * the search is in progress.
- *
- *--------------------------------------------------------------
- */
-static ZnItem
-ZnTagSearchFirst(ZnTagSearch *search) /* Record describing tag search */
-{
- ZnItem item, previous;
-
- /* short circuit impossible searches for null tags */
- if (search->over == True) {
- return ZN_NO_ITEM;
- }
-
- /*
- * Find the first matching item in one of several ways. If the tag
- * is a number then it selects the single item with the matching
- * identifier. In this case see if the item being requested is the
- * hot item, in which case the search can be skipped.
- */
- if (search->type == 1) {
- Tcl_HashEntry *entry;
-
- item = search->wi->hot_item;
- previous = search->wi->hot_prev;
- if ((item == ZN_NO_ITEM) || (item->id != search->id) ||
- (previous == ZN_NO_ITEM) || (previous->next != item)) {
- entry = Tcl_FindHashEntry(search->wi->id_table, (char *) search->id);
- if (entry != NULL) {
- item = (ZnItem) Tcl_GetHashValue(entry);
- previous = item->previous;
- }
- else {
- previous = item = ZN_NO_ITEM;
- }
- }
- search->previous = previous;
- search->over = True;
- search->wi->hot_item = item;
- search->wi->hot_prev = previous;
- return item;
- }
-
- if (search->type == 2) {
- /*
- * All items match.
- */
- search->previous = ZN_NO_ITEM;
- search->current = ZnGroupHead(search->group);
- return search->current;
- }
-
- item = ZnGroupHead(search->group);
- previous = ZN_NO_ITEM;
- do {
- while (item != ZN_NO_ITEM) {
- if (search->type == 3) {
- /*
- * Optimized single-tag search
- */
- if (ZnITEM.HasTag(item, search->expr->uid)) {
- search->previous = previous;
- search->current = item;
- return item;
- }
- }
- else {
- /*
- * Type = 4. Search for an item matching
- * the tag expression.
- */
- search->expr->index = 0;
- if (TagSearchEvalExpr(search->expr, item)) {
- search->previous = previous;
- search->current = item;
- return item;
- }
- }
- if ((item->class == ZnGroup) && (search->recursive)) {
- ZnItem prev_group = (ZnItem) search->group;
- /*
- * Explore the hierarchy depth first using the item stack
- * to save the current node.
- */
- /*printf("ZnTagSearchFirst diving for tag '%s', detph %d\n",
- search->tag, ZnListSize(search->item_stack)/2);*/
- search->group = item;
- previous = item;
- if (item == prev_group) {
- item = ZN_NO_ITEM;
- }
- else {
- item = item->next;
- }
- ZnListAdd(search->item_stack, &previous, ZnListTail);
- ZnListAdd(search->item_stack, &item, ZnListTail);
- previous = ZN_NO_ITEM;
- item = ZnGroupHead(search->group);
- }
- else {
- previous = item;
- item = item->next;
- }
- }
- /*
- * Continue search on higher group level.
- */
- /*printf("ZnTagSearchFirst backup for tag, detph %d\n",
- ZnListSize(search->item_stack)/2);*/
- while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
- item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- }
- if (item != ZN_NO_ITEM) {
- search->group = item->parent;
- }
- } while (item != ZN_NO_ITEM);
-
- search->previous = previous;
- search->over = True;
-
- return ZN_NO_ITEM;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnTagSearchNext --
- *
- * This procedure returns successive items that match a given
- * tag; it should be called only after ZnTagSearchFirst has
- * been used to begin a search.
- *
- * Results:
- * The return value is a pointer to the next item that matches
- * the tag expr specified to TagSearchScan, or NULL if no such
- * item exists. *search is updated so that the next call
- * to this procedure will return the next item.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-static ZnItem
-ZnTagSearchNext(ZnTagSearch *search) /* Record describing search in progress. */
-{
- ZnItem item, previous;
-
- if (search->over) {
- return ZN_NO_ITEM;
- }
- /*
- * Find next item in list (this may not actually be a suitable
- * one to return), and return if there are no items left.
- */
- previous = search->previous;
- if (previous == ZN_NO_ITEM) {
- item = ZnGroupHead(search->group);
- }
- else {
- item = previous->next;
- }
-
- if (item != search->current) {
- /*
- * The structure of the list has changed. Probably the
- * previously-returned item was removed from the list.
- * In this case, don't advance previous; just return
- * its new successor (i.e. do nothing here).
- */
- }
- else if ((item->class == ZnGroup) && (search->recursive)) {
- /*
- * Explore the hierarchy depth first using the item stack
- * to save the current node.
- */
- search->group = item;
- previous = item;
- item = item->next;
- /*printf("ZnTagSearchNext diving for all, pushing %d\n",
- item?item->id:0);*/
- ZnListAdd(search->item_stack, &previous, ZnListTail);
- ZnListAdd(search->item_stack, &item, ZnListTail);
- previous = ZN_NO_ITEM;
- item = ZnGroupHead(search->group);
- }
- else {
- previous = item;
- item = previous->next;
- }
-
- if (item == ZN_NO_ITEM) {
- while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
- /*
- * End of list at this level, back up one level.
- */
- item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- }
- if (item != ZN_NO_ITEM) {
- search->group = item->parent;
- /*printf("ZnTagSearchNext popping %d, previous %d, next %d\n",
- item->id, (item->previous)?item->previous->id:0,
- (item->next)?item->next->id:0);*/
- }
- else {
- /*
- * Or finish the search if at top.
- */
- search->over = True;
- return ZN_NO_ITEM;
- }
- }
-
- if (search->type == 2) {
- /*
- * All items match.
- */
- search->previous = previous;
- search->current = item;
- return item;
- }
-
- do {
- while (item != ZN_NO_ITEM) {
- if (search->type == 3) {
- /*
- * Optimized single-tag search
- */
- if (ZnITEM.HasTag(item, search->expr->uid)) {
- search->previous = previous;
- search->current = item;
- return item;
- }
- }
- else {
- /*
- * Else.... evaluate tag expression
- */
- search->expr->index = 0;
- if (TagSearchEvalExpr(search->expr, item)) {
- search->previous = previous;
- search->current = item;
- return item;
- }
- }
- if ((item->class == ZnGroup) && (search->recursive)) {
- /*
- * Explore the hierarchy depth first using the item stack
- * to save the current node.
- */
- /*printf("ZnTagSearchNext diving for tag, depth %d\n",
- ZnListSize(search->item_stack)/2);*/
- search->group = item;
- previous = item;
- item = item->next;
- ZnListAdd(search->item_stack, &previous, ZnListTail);
- ZnListAdd(search->item_stack, &item, ZnListTail);
- previous = ZN_NO_ITEM;
- item = ZnGroupHead(search->group);
- }
- else {
- previous = item;
- item = item->next;
- }
- }
- /*printf("ZnTagSearchNext backup for tag, depth %d\n",
- ZnListSize(search->item_stack)/2);*/
- while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
- item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
- ZnListDelete(search->item_stack, ZnListTail);
- }
- if (item != ZN_NO_ITEM) {
- search->group = item->parent;
- }
- } while (item != ZN_NO_ITEM);
-
- /*
- * Out of fuel.
- */
- search->previous = previous;
- search->over = True;
-
- return ZN_NO_ITEM;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * ZnTagSearchDestroy --
- *
- * This procedure destroys any dynamic structures that
- * may have been allocated by TagSearchScan.
- *
- *--------------------------------------------------------------
- */
-void
-ZnTagSearchDestroy(ZnTagSearch *search) /* Record describing tag search */
-{
- if (search) {
- TagSearchExprDestroy(search->expr);
- ZnListFree(search->item_stack);
- ZnFree(search->rewrite_buf);
- ZnFree(search);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnItemWithTagOrId --
- *
- * Return the first item matching the given tag or id. The
- * function returns the item in 'item' and the operation
- * status as the function's value.
- *
- *----------------------------------------------------------------------
- */
-int
-ZnItemWithTagOrId(ZnWInfo *wi,
- Tcl_Obj *tag_or_id,
- ZnItem *item,
- ZnTagSearch **search_var)
-{
- if (ZnTagSearchScan(wi, tag_or_id, search_var) != TCL_OK) {
- return TCL_ERROR;
- }
- *item = ZnTagSearchFirst(*search_var);
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * LayoutItems --
- *
- * Perform layouts on items. It can position items horizontally,
- * vertically, along a path or with respect to a reference item.
- * It can also align on a grid, evenly space items and resize
- * items to a common reference.
- *
- *----------------------------------------------------------------------
- */
-static int
-LayoutItems(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST args[])
-{
- int index/*, result*/;
- /*ZnItem item;*/
-#ifdef PTK_800
- static char *layout_cmd_strings[] =
- #else
- static CONST char *layout_cmd_strings[] =
-#endif
- {
- "align", "grid", "position", "scale", "space", NULL
- };
- enum layout_cmds {
- ZN_L_ALIGN, ZN_L_GRID, ZN_L_POSITION, ZN_L_SCALE, ZN_L_SPACE
- };
-
- if (Tcl_GetIndexFromObj(wi->interp, args[0], layout_cmd_strings,
- "layout command", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch((enum layout_cmds) index) {
- /*
- * align
- */
- case ZN_L_ALIGN:
- break;
- /*
- * grid
- */
- case ZN_L_GRID:
- break;
- /*
- * position
- */
- case ZN_L_POSITION:
- break;
- /*
- * scale
- */
- case ZN_L_SCALE:
- break;
- /*
- * space
- */
- case ZN_L_SPACE:
- break;
- }
-
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SetOrigin --
- *
- * This procedure is invoked to translate the viewed area so
- * that the given point is displayed in the top left corner.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Zinc will be redisplayed to reflect the change in ciew.
- * The scrollbars will be updated if there are any.
- * The top group transform is modified to achieve the effect,
- * it is not a good idea to mix view control and application
- * control of the top group transform.
- *
- *----------------------------------------------------------------------
- */
-static void
-SetOrigin(ZnWInfo *wi,
- ZnReal x_origin,
- ZnReal y_origin)
-{
- int left, right, top, bottom, delta;
-
- /*
- * If scroll increments have been set, round the window origin
- * to the nearest multiple of the increments.
- */
- if (wi->x_scroll_incr > 0) {
- if (x_origin >= 0) {
- x_origin += wi->x_scroll_incr/2;
- }
- else {
- x_origin = (-x_origin) + wi->x_scroll_incr/2;
- }
- }
- if (wi->y_scroll_incr > 0) {
- if (y_origin >= 0) {
- y_origin += wi->y_scroll_incr/2;
- }
- else {
- y_origin = (-y_origin) + wi->y_scroll_incr/2;
- }
- }
-
- /*
- * Adjust the origin if necessary to keep as much as possible of the
- * canvas in the view. The variables left, right, etc. keep track of
- * how much extra space there is on each side of the view before it
- * will stick out past the scroll region. If one side sticks out past
- * the edge of the scroll region, adjust the view to bring that side
- * back to the edge of the scrollregion (but don't move it so much that
- * the other side sticks out now). If scroll increments are in effect,
- * be sure to adjust only by full increments.
- */
- if (wi->confine && (wi->region != NULL)) {
- left = (int) (x_origin - wi->scroll_xo);
- right = (int) (wi->scroll_xc - (x_origin + Tk_Width(wi->win)));
- top = (int) (y_origin - wi->scroll_yo);
- bottom = (int) (wi->scroll_yc - (y_origin + Tk_Height(wi->win)));
- if ((left < 0) && (right > 0)) {
- delta = (right > -left) ? -left : right;
- if (wi->x_scroll_incr > 0) {
- delta -= delta % wi->x_scroll_incr;
- }
- x_origin += delta;
- }
- else if ((right < 0) && (left > 0)) {
- delta = (left > -right) ? -right : left;
- if (wi->x_scroll_incr > 0) {
- delta -= delta % wi->x_scroll_incr;
- }
- x_origin -= delta;
- }
- if ((top < 0) && (bottom > 0)) {
- delta = (bottom > -top) ? -top : bottom;
- if (wi->y_scroll_incr > 0) {
- delta -= delta % wi->y_scroll_incr;
- }
- y_origin += delta;
- }
- else if ((bottom < 0) && (top > 0)) {
- delta = (top > -bottom) ? -bottom : top;
- if (wi->y_scroll_incr > 0) {
- delta -= delta % wi->y_scroll_incr;
- }
- y_origin -= delta;
- }
- }
-
- /*
- * If the requested origin is not already set, translate the
- * top group and update the scrollbars.
- */
- if ((wi->origin.x != x_origin) || (wi->origin.y != y_origin)) {
- wi->origin.x = x_origin;
- wi->origin.y = y_origin;
- ZnITEM.ResetTransfo(wi->top_group);
- ZnITEM.TranslateItem(wi->top_group, -x_origin, -y_origin, False);
- SET(wi->flags, ZN_UPDATE_SCROLLBARS);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ScrollFractions --
- *
- * Given the range that's visible in the window and the "100%
- * range", return a list of two real representing the scroll
- * fractions. This procedure is used for both x and y scrolling.
- *
- * Results:
- * Return a string as a Tcl_Obj holding two real numbers
- * describing the scroll fraction (between 0 and 1) corresponding
- * to the arguments.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-#ifdef PTK
-static void
-ScrollFractions(ZnReal view1, /* Lowest coordinate visible in the window. */
- ZnReal view2, /* Highest coordinate visible in the window. */
- ZnReal region1,/* Lowest coordinate in the object. */
- ZnReal region2,/* Highest coordinate in the object. */
- ZnReal *first,
- ZnReal *last)
-#else
-static Tcl_Obj *
-ScrollFractions(ZnReal view1, /* Lowest coordinate visible in the window. */
- ZnReal view2, /* Highest coordinate visible in the window. */
- ZnReal region1,/* Lowest coordinate in the object. */
- ZnReal region2)/* Highest coordinate in the object. */
-#endif
-{
- ZnReal range, f1, f2;
- char buffer[2*TCL_DOUBLE_SPACE+2];
-
- range = region2 - region1;
- if (range <= 0) {
- f1 = 0;
- f2 = 1.0;
- }
- else {
- f1 = (view1 - region1)/range;
- if (f1 < 0) {
- f1 = 0.0;
- }
- f2 = (view2 - region1)/range;
- if (f2 > 1.0) {
- f2 = 1.0;
- }
- if (f2 < f1) {
- f2 = f1;
- }
- }
-#ifdef PTK
- *first = f1;
- *last = f2;
-#else
- sprintf(buffer, "%g %g", f1, f2);
- return Tcl_NewStringObj(buffer, -1);
-#endif
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * UpdateScrollbars --
- *
- * This procedure is invoked whenever zinc has changed in
- * a way that requires scrollbars to be redisplayed (e.g.
- * the view has changed).
- *
- * Results:
- * None.
- *
- * Side effects:
- * If there are scrollbars associated with zinc, then
- * their scrolling commands are invoked to cause them to
- * redisplay. If errors occur, additional Tcl commands may
- * be invoked to process the errors.
- *
- *--------------------------------------------------------------
- */
-static void
-UpdateScrollbars(ZnWInfo *wi)
-{
- int result;
- Tcl_Interp *interp;
- int x_origin, y_origin, width, height;
- int scroll_xo, scroll_xc, scroll_yo, scroll_yc;
-#ifdef PTK
- LangCallback *x_scroll_cmd, *y_scroll_cmd;
-#else
- Tcl_Obj *x_scroll_cmd, *y_scroll_cmd;
-#endif
- Tcl_Obj *fractions;
-
- /*
- * Save all the relevant values from wi, because it might be
- * deleted as part of either of the two calls to Tcl_VarEval below.
- */
- interp = wi->interp;
- Tcl_Preserve((ClientData) interp);
- x_scroll_cmd = wi->x_scroll_cmd;
- if (x_scroll_cmd != NULL) {
- Tcl_Preserve((ClientData) x_scroll_cmd);
- }
- y_scroll_cmd = wi->y_scroll_cmd;
- if (y_scroll_cmd != NULL) {
- Tcl_Preserve((ClientData) y_scroll_cmd);
- }
- x_origin = (int) wi->origin.x;
- y_origin = (int) wi->origin.y;
- width = Tk_Width(wi->win);
- height = Tk_Height(wi->win);
- scroll_xo = wi->scroll_xo;
- scroll_xc = wi->scroll_xc;
- scroll_yo = wi->scroll_yo;
- scroll_yc = wi->scroll_yc;
- CLEAR(wi->flags, ZN_UPDATE_SCROLLBARS);
- if (wi->x_scroll_cmd != NULL) {
-#ifdef PTK
- ZnReal first, last;
- ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc, &first, &last);
- result = LangDoCallback(interp, x_scroll_cmd, 0, 2, " %g %g", first, last);
-#else
- fractions = ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc);
- result = Tcl_VarEval(interp, Tcl_GetString(x_scroll_cmd), " ", Tcl_GetString(fractions), NULL);
- Tcl_DecrRefCount(fractions);
-#endif
- if (result != TCL_OK) {
- Tcl_BackgroundError(interp);
- }
- Tcl_ResetResult(interp);
- Tcl_Release((ClientData) x_scroll_cmd);
- }
-
- if (y_scroll_cmd != NULL) {
-#ifdef PTK
- ZnReal first, last;
- ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc, &first, &last);
- result = LangDoCallback(interp, y_scroll_cmd, 0, 2, " %g %g", first, last);
-#else
- fractions = ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc);
- result = Tcl_VarEval(interp, Tcl_GetString(y_scroll_cmd), " ", Tcl_GetString(fractions), NULL);
- Tcl_DecrRefCount(fractions);
-#endif
- if (result != TCL_OK) {
- Tcl_BackgroundError(interp);
- }
- Tcl_ResetResult(interp);
- Tcl_Release((ClientData) y_scroll_cmd);
- }
- Tcl_Release((ClientData) interp);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnDoItem --
- *
- * Either add a tag to an item or add the item id/part to the
- * interpreter result, depending on the value of tag. If tag
- * is NULL, the item id/part is added to the result, otherwise
- * the tag is added to the item.
- *
- *----------------------------------------------------------------------
- */
-void
-ZnDoItem(Tcl_Interp *interp,
- ZnItem item,
- int part,
- Tk_Uid tag_uid)
-{
- if (tag_uid == NULL) {
- Tcl_Obj *l;
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id));
- if (part != ZN_NO_PART) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(part));
- }
- }
- else {
- /*printf("Adding tag %s to item %d\n", tag_uid, item->id);*/
- ZnITEM.AddTag(item, tag_uid);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * FindArea --
- * Search the items that are enclosed or overlapping a given
- * area of the widget. It is used by FindItems.
- * If tag_uid is not NULL, all the items found are tagged with
- * tag_uid. If tag_uid is NULL, the items found are added to the
- * interp result. If enclosed is 1, the search look for
- * items enclosed in the area. If enclosed is 0, it looks
- * for overlapping and enclosed items.
- * If an error occurs, a message is left in the interp result
- * and TCL_ERROR is returned.
- *
- *----------------------------------------------------------------------
- */
-static int
-FindArea(ZnWInfo *wi,
- Tcl_Obj *CONST args[],
- Tk_Uid tag_uid,
- ZnBool enclosed,
- ZnBool recursive,
- ZnBool override_atomic,
- ZnItem group)
-{
- ZnPos pos;
- ZnBBox area;
- ZnToAreaStruct ta;
- double d;
-
- if (Tcl_GetDoubleFromObj(wi->interp, args[0], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- area.orig.x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, args[1], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- area.orig.y = d;
- if (Tcl_GetDoubleFromObj(wi->interp, args[2], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- area.corner.x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, args[3], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- area.corner.y = d;
- if (area.corner.x < area.orig.x) {
- pos = area.orig.x;
- area.orig.x = area.corner.x;
- area.corner.x = pos;
- }
- if (area.corner.y < area.orig.y) {
- pos = area.orig.y;
- area.orig.y = area.corner.y;
- area.corner.y = pos;
- }
- area.corner.x += 1;
- area.corner.y += 1;
-
- ta.tag_uid = tag_uid;
- ta.enclosed = enclosed;
- ta.in_group = group;
- ta.recursive = recursive;
- ta.override_atomic = override_atomic;
- ta.report = False;
- ta.area = &area;
- wi->top_group->class->ToArea(wi->top_group, &ta);
-
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * FindItems --
- *
- * This procedure interprets the small object query langage for
- * commands like addtag and find.
- * If new_tag is NULL, the procedure collects all the objects
- * matching the request and return them in the interpreter result.
- * If new_tag is non NULL, it is interpreted as the tag to add to
- * all matching objects. In this case the interpreter result is
- * left empty.
- *
- *----------------------------------------------------------------------
- */
-static int
-FindItems(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST args[],
- Tcl_Obj *tag, /* NULL to search or tag to add tag. */
- int first, /* First arg to process in args */
- ZnTagSearch **search_var)
-{
- Tk_Uid tag_uid = NULL;
- int index, result;
- ZnItem item;
- ZnPickStruct ps;
- char *str;
-#ifdef PTK_800
- static char *search_cmd_strings[] =
-#else
- static CONST char *search_cmd_strings[] =
-#endif
- {
- "above", "ancestors", "atpriority", "below", "closest", "enclosed",
- "overlapping", "withtag", "withtype", NULL
- };
- enum search_cmds {
- ZN_S_ABOVE, ZN_S_ANCESTORS, ZN_S_ATPRIORITY, ZN_S_BELOW, ZN_S_CLOSEST,
- ZN_S_ENCLOSED, ZN_S_OVERLAPPING, ZN_S_WITHTAG, ZN_S_WITHTYPE
- };
-
- if (Tcl_GetIndexFromObj(wi->interp, args[first], search_cmd_strings,
- "search command", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (tag) {
- tag_uid = Tk_GetUid(Tcl_GetString(tag));
- }
-
- switch((enum search_cmds) index) {
- /*
- * above
- */
- case ZN_S_ABOVE:
- {
- if (argc != first+2) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
- return TCL_ERROR;
- }
- result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var);
- if (result == TCL_OK) {
- if ((item != ZN_NO_ITEM) && (item->previous != ZN_NO_ITEM)) {
- ZnDoItem(wi->interp, item->previous, ZN_NO_PART, tag_uid);
- }
- }
- else {
- return TCL_ERROR;
- }
- }
- break;
- /*
- * ancestors
- */
- case ZN_S_ANCESTORS:
- {
- Tk_Uid uid = NULL;
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId ?withTag?");
- return TCL_ERROR;
- }
- result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var);
- if (result == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (item) {
- item = item->parent;
- if (argc == first+3) {
- uid = Tk_GetUid(Tcl_GetString(args[first+2]));
- }
- while (item != ZN_NO_ITEM) {
- if (!uid || ZnITEM.HasTag(item, uid)) {
- ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
- }
- item = item->parent;
- }
- }
- }
- break;
- /*
- * atpriority
- */
- case ZN_S_ATPRIORITY:
- {
- int pri;
-
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "pri ?tagOrId?");
- return TCL_ERROR;
- }
- if ((Tcl_GetIntFromObj(wi->interp, args[first+1], &pri) == TCL_ERROR) ||
- (pri < 0)){
- return TCL_ERROR;
- }
-
- /*
- * Go through the item table and collect all items with
- * the given priority.
- */
- if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL,
- search_var) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (item = ZnTagSearchFirst(*search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
- if (item->priority == (unsigned int) pri) {
- ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
- }
- }
- }
- break;
- /*
- * below
- */
- case ZN_S_BELOW:
- {
- ZnItem next;
-
- if (argc != first+2) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
- return TCL_ERROR;
- }
- item = ZN_NO_ITEM;
- if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (next = ZnTagSearchFirst(*search_var);
- next != ZN_NO_ITEM; next = ZnTagSearchNext(*search_var)) {
- item = next;
- }
- if ((item != ZN_NO_ITEM) && (item->next != ZN_NO_ITEM)) {
- ZnDoItem(wi->interp, item->next, ZN_NO_PART, tag_uid);
- }
- }
- break;
- /*
- * closest
- */
- case ZN_S_CLOSEST:
- {
- int halo = 1;
- ZnPoint p;
- double d;
-
- if ((argc < first+3) || (argc > first+6)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x y ?halo? ?start?, ?recursive?");
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, args[first+1], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- p.x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, args[first+2], &d) == TCL_ERROR) {
- return TCL_ERROR;
- }
- p.y = d;
- if (argc > first+3) {
- if (Tcl_GetIntFromObj(wi->interp, args[first+3], &halo) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (halo < 0) {
- halo = 0;
- }
- }
-
- ps.in_group = ZN_NO_ITEM;
- ps.start_item = ZN_NO_ITEM;
- item = ZN_NO_ITEM;
- if (argc > (first+4)) {
- result = ZnItemWithTagOrId(wi, args[first+4], &item, search_var);
- if ((result == TCL_OK) && (item != ZN_NO_ITEM)) {
- if ((item->class == ZnGroup) && !ZnGroupAtomic(item)) {
- ps.in_group = item;
- }
- else {
- ps.in_group = item->parent;
- ps.start_item = item->next;
- }
- }
- }
- ps.recursive = True;
- ps.override_atomic = False;
- if (argc > first+5) {
- result = Tcl_GetBooleanFromObj(wi->interp, args[first+5], &ps.recursive);
- if (result != TCL_OK) {
- str = Tcl_GetString(args[first+5]);
- if (strcmp(str, "override") != 0) {
- Tcl_AppendResult(wi->interp,
- "recursive should be a boolean value or ",
- "override \"", str, "\"", NULL);
- return TCL_ERROR;
- }
- ps.recursive = True;
- ps.override_atomic = True;
- }
- }
- /*
- * We always start the search at the top group to use the
- * transform and clip machinery of the group item. The items
- * are not required to cache the device coords, etc. So we need
- * to setup the correct context before calling the Pick method
- * for each item.
- */
- ps.aperture = halo;
- ps.point = &p;
- wi->top_group->class->Pick(wi->top_group, &ps);
-
- if (ps.a_item != ZN_NO_ITEM) {
- ZnDoItem(wi->interp, ps.a_item, ps.a_part, tag_uid);
- /*printf("first %d %d\n", ps.a_item->id, ps.a_part);*/
- }
- }
- break;
- /*
- * enclosed
- */
- case ZN_S_ENCLOSED:
- {
- if ((argc < first+5) || (argc > first+7)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?");
- return TCL_ERROR;
- }
- item = wi->top_group;
- if (argc > first+5) {
- result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var);
- if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) {
- return TCL_ERROR;
- }
- }
- ps.recursive = True;
- ps.override_atomic = False;
- if (argc > first+6) {
- result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive);
- if (result != TCL_OK) {
- str = Tcl_GetString(args[first+6]);
- if (strcmp(str, "override") != 0) {
- Tcl_AppendResult(wi->interp,
- "recursive should be a boolean value or ",
- "override \"", str, "\"", NULL);
- return TCL_ERROR;
- }
- ps.recursive = True;
- ps.override_atomic = True;
- }
- }
- return FindArea(wi, args+first+1, tag_uid,
- True, ps.recursive, ps.override_atomic,
- item);
- }
- break;
- /*
- * overlapping
- */
- case ZN_S_OVERLAPPING:
- {
- if ((argc < first+5) || (argc > first+7)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?");
- return TCL_ERROR;
- }
- item = wi->top_group;
- if (argc > first+5) {
- result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var);
- if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) {
- return TCL_ERROR;
- }
- }
- ps.recursive = True;
- ps.override_atomic = False;
- if (argc > first+6) {
- result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive);
- if (result != TCL_OK) {
- str = Tcl_GetString(args[first+6]);
- if (strcmp(str, "override") != 0) {
- Tcl_AppendResult(wi->interp,
- "recursive should be a boolean value or ",
- "override \"", str, "\"", NULL);
- return TCL_ERROR;
- }
- ps.recursive = True;
- ps.override_atomic = True;
- }
- }
- return FindArea(wi, args+first+1, tag_uid,
- False, ps.recursive, ps.override_atomic,
- item);
- }
- break;
- /*
- * withtag
- */
- case ZN_S_WITHTAG:
- {
- if (argc != first+2) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
- return TCL_ERROR;
- }
- if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (item = ZnTagSearchFirst(*search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
- ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
- }
- }
- break;
- /*
- * withtype
- */
- case ZN_S_WITHTYPE:
- {
- ZnItemClass cls;
-
- if ((argc != first+2) && (argc != first+3)) {
- Tcl_WrongNumArgs(wi->interp, first+1, args, "itemType ?tagOrId?");
- return TCL_ERROR;
- }
- cls = ZnLookupItemClass(Tcl_GetString(args[first+1]));
- if (!cls) {
- Tcl_AppendResult(wi->interp, "unknown item type \"",
- Tcl_GetString(args[first+1]), "\"", NULL);
- return TCL_ERROR;
- }
-
- /*
- * Go through the item table and collect all items with
- * the given item type.
- */
- if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL,
- search_var) == TCL_ERROR) {
- return TCL_ERROR;
- }
- for (item = ZnTagSearchFirst(*search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
- if (item->class == cls) {
- ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
- }
- }
- }
- break;
- }
-
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ZnParseCoordList --
- *
- *----------------------------------------------------------------------
- */
-int
-ZnParseCoordList(ZnWInfo *wi,
- Tcl_Obj *arg,
- ZnPoint **pts,
- char **controls,
- unsigned int *num_pts,
- ZnBool *old_format)
-{
- Tcl_Obj **elems, **selems;
- int i, result, num_elems, num_selems;
- ZnPoint *p;
- int old_style, len;
- char *str;
- double d;
-
- if (controls) {
- *controls = NULL;
- }
- if (old_format) {
- *old_format = True;
- }
- result = Tcl_ListObjGetElements(wi->interp, arg, &num_elems, &elems);
- if (result == TCL_ERROR) {
- coord_error:
- Tcl_AppendResult(wi->interp, " malformed coord list", NULL);
- return TCL_ERROR;
- }
- if (num_elems == 0) {
- *num_pts = 0;
- *pts = NULL;
- return TCL_OK;
- }
-
- /*
- * If first element is not a sublist, consider the whole list
- * as a flat array of coordinates in the old style. It can still
- * be a single point with or without a control flag.
- * If not, the list consists in sublists describing each point
- * with its control flag.
- */
- result = Tcl_GetDoubleFromObj(wi->interp, elems[0], &d);
- old_style = (result == TCL_OK);
-
- if (old_style) {
- if ((num_elems%2) == 0) {
- *num_pts = num_elems/2;
- ZnListAssertSize(ZnWorkPoints, *num_pts);
- *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
- for (i = 0; i < num_elems; i += 2, p++) {
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i+1], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->y = d;
- /*printf("Parsed a point: %g@%g, ", p->x, p->y);*/
- }
- /*printf("\n");*/
- }
- else if (num_elems == 3) {
- *num_pts = 1;
- ZnListAssertSize(ZnWorkPoints, *num_pts);
- *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
- if (Tcl_GetDoubleFromObj(wi->interp, elems[0], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, elems[1], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->y = d;
- if (controls) {
- if (! *controls) {
- *controls = ZnMalloc(*num_pts * sizeof(char));
- memset(*controls, 0, *num_pts * sizeof(char));
- }
- str = Tcl_GetStringFromObj(elems[2], &len);
- if (len) {
- (*controls)[0] = str[0];
- }
- }
- }
- else {
- goto coord_error;
- }
- }
- else {
- Tcl_ResetResult(wi->interp);
- *num_pts = num_elems;
- ZnListAssertSize(ZnWorkPoints, *num_pts);
- *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
- for (i = 0; i < num_elems; i++, p++) {
- result = Tcl_ListObjGetElements(wi->interp, elems[i], &num_selems, &selems);
- if ((result == TCL_ERROR) || (num_selems < 2) || (num_selems > 3)) {
- goto coord_error;
- }
- if (Tcl_GetDoubleFromObj(wi->interp, selems[0], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->x = d;
- if (Tcl_GetDoubleFromObj(wi->interp, selems[1], &d) == TCL_ERROR) {
- goto coord_error;
- }
- p->y = d;
- if (controls) {
- if (num_selems == 3) {
- if (! *controls) {
- *controls = ZnMalloc(*num_pts * sizeof(char));
- memset(*controls, 0, *num_pts * sizeof(char));
- }
- str = Tcl_GetStringFromObj(selems[2], &len);
- if (len) {
- (*controls)[i] = str[0];
- }
- }
- }
- }
- }
-
- if (old_format) {
- *old_format = old_style;
- }
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Contour --
- *
- *----------------------------------------------------------------------
- */
-static int
-Contour(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST args[],
- ZnTagSearch **search_var)
-{
- ZnPoint *points;
- ZnItem item, shape;
- unsigned int i, j, k,num_points;
- int cmd, cw, result;
- int winding_flag, revert = False;
- long index;
- char *controls;
- ZnBool simple=False;
- ZnPoly poly;
- ZnTransfo t, inv;
- ZnContour *contours;
-
- /* Keep this array in sync with ZnContourCmd in Types.h */
-#ifdef PTK_800
- static char *op_strings[] =
-#else
- static CONST char *op_strings[] =
-#endif
- {
- "add", "remove", NULL
- };
-
- result = ZnItemWithTagOrId(wi, args[2], &item, search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)){
- Tcl_AppendResult(wi->interp, "unknown item \"", Tcl_GetString(args[2]),
- "\"", NULL);
- return TCL_ERROR;
- }
- if (!item->class->Contour) {
- if (item->class->GetClipVertices ||
- item->class->GetContours) {
- Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(1));
- }
- else {
- Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(0));
- }
- return TCL_OK;
- }
- if (argc == 3) {
- /*
- * Requesting the number of contours.
- */
- Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, -1, 0, NULL)));
- return TCL_OK;
- }
- /*
- * Get the sub-command
- */
- if (Tcl_GetIndexFromObj(wi->interp, args[3], op_strings,
- "contour operation", 0, &cmd) != TCL_OK) {
- return TCL_ERROR;
- }
- /*
- * Get the winding flag.
- */
- if ((Tcl_GetIntFromObj(wi->interp, args[4], &winding_flag) != TCL_OK) ||
- (winding_flag < -1) || (winding_flag > 1)) {
- Tcl_AppendResult(wi->interp, " incorrect winding flag, should be -1, 0, 1, \"",
- Tcl_GetString(args[4]), "\"", NULL);
- return TCL_ERROR;
- }
- index = ZnListTail;
- if (((argc == 6) && (cmd == ZN_CONTOUR_REMOVE)) || (argc == 7)) {
- /* Look for an index value. */
- if (Tcl_GetLongFromObj(wi->interp, args[5], &index) != TCL_OK) {
- Tcl_AppendResult(wi->interp, " incorrect contour index \"",
- Tcl_GetString(args[5]), "\"", NULL);
- return TCL_ERROR;
- }
- argc--;
- args++;
- }
-
- if (cmd == ZN_CONTOUR_REMOVE) {
- Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, ZN_CONTOUR_REMOVE, index, NULL)));
- }
- else {
- result = ZnItemWithTagOrId(wi, args[5], &shape, search_var);
- if ((result == TCL_ERROR) || (shape == ZN_NO_ITEM)) {
- Tcl_ResetResult(wi->interp);
- if (ZnParseCoordList(wi, args[5], &points,
- &controls, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- /*
- * Processing contours from an explicit list.
- */
- ZnPolyContour1(&poly, NULL, num_points, False);
- /*
- * Allocate a fresh point array, ZnParseCoordList returns a shared
- * array. The control array is not shared and can be passed along.
- */
- poly.contours[0].points = ZnMalloc(num_points*sizeof(ZnPoint));
- cw = poly.contours[0].cw = !ZnTestCCW(points, num_points);
- if (winding_flag != 0) {
- revert = cw ^ (winding_flag == -1);
- }
- if (revert) {
- /* Revert the contour */
- for (i = 0; i < num_points; i++) {
- poly.contours[0].points[num_points-i-1] = points[i];
- }
- if (controls) {
- char ch;
- for (i = 0, j = num_points-1; i < j; i++, j--) {
- ch = controls[i];
- controls[i] = controls[j];
- controls[j] = ch;
- }
- }
- }
- else {
- memcpy(poly.contours[0].points, points, num_points*sizeof(ZnPoint));
- }
- poly.contours[0].controls = controls;
- }
- else {
- /*
- * Processing contours from an item
- */
- if (winding_flag == 0) {
- Tcl_AppendResult(wi->interp,
- "Must supply an explicit winding direction (-1, 1)\nwhen adding a contour from an item",
- NULL);
- return TCL_ERROR;
- }
- /*
- * If something has changed in the geometry we need to
- * update or the shape will be erroneous.
- */
- Update(wi);
- if (!shape->class->GetContours &&
- !shape->class->GetClipVertices) {
- Tcl_AppendResult(wi->interp, "class: \"", shape->class->name,
- "\" can't give a polygonal shape", NULL);
- return TCL_ERROR;
- }
- if (!shape->class->GetContours) {
- ZnTriStrip tristrip;
- /*
- * If there is no GetContours method try to use
- * the GetClipVertices. It works only for simple
- * shapes (i.e tose returning a bounding box).
- */
- tristrip.num_strips = 0;
- /*
- * GetClipVertices _may_ return a tristrip describing a fan
- * this would lead to strange results. For now, this case
- * should not appear, the items candidates to such a behavior
- * export a GetContours method which has higher precedence.
- */
- simple = shape->class->GetClipVertices(shape, &tristrip);
- ZnPolyContour1(&poly, tristrip.strip1.points, tristrip.strip1.num_points,
- False);
- poly.contours[0].controls = NULL;
- }
- else {
- poly.num_contours = 0;
- simple = shape->class->GetContours(shape, &poly);
- }
- if (poly.num_contours == 0) {
- return TCL_OK;
- }
- /*
- * Compute the tranform to map the device points
- * into the coordinate space of item.
- */
- ZnITEM.GetItemTransform(item, &t);
- ZnTransfoInvert(&t, &inv);
- /*
- * Make a new transformed poly and unshare
- * the contour(s) returned by the item.
- */
- if (simple) {
- ZnPoint p[4];
- p[0] = poly.contours[0].points[0];
- p[2] = poly.contours[0].points[1];
- if (winding_flag == -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;
- }
- else {
- p[1].x = p[0].x;
- p[1].y = p[2].y;
- p[3].x = p[2].x;
- p[3].y = p[0].y;
- }
- points = ZnMalloc(4*sizeof(ZnPoint));
- ZnTransformPoints(&inv, p, points, 4);
- poly.contours[0].points = points;
- poly.contours[0].num_points = 4;
- poly.contours[0].cw = (winding_flag == -1);
- poly.contours[0].controls = NULL;
- }
- else {
- /* Unshare the contour array or use the static storage */
- contours = poly.contours;
- if (poly.num_contours == 1) {
- poly.contours = &poly.contour1;
- }
- else {
- poly.contours = ZnMalloc(poly.num_contours*sizeof(ZnContour));
- }
- for (i = 0; i < poly.num_contours; i++) {
- points = contours[i].points;
- num_points = contours[i].num_points;
- cw = contours[i].cw;
- poly.contours[i].num_points = num_points;
- poly.contours[i].cw = cw;
- if (contours[i].controls) {
- /*
- * The controls array returned by GetContour is shared.
- * Here we unshare it.
- */
- poly.contours[i].controls = ZnMalloc(num_points*sizeof(char));
- }
- /*
- * Unshare the point array.
- */
- poly.contours[i].points = ZnMalloc(num_points*sizeof(ZnPoint));
- ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
-
- if ((((poly.num_contours == 1) && ((winding_flag == -1) ^ cw)) ||
- ((poly.num_contours > 1) && (winding_flag == -1)))) {
- ZnPoint p;
-
- revert = True;
- /* Revert the points */
- poly.contours[i].cw = ! cw;
- for (j = 0, k = num_points-1; j < k; j++, k--) {
- p = poly.contours[i].points[j];
- poly.contours[i].points[j] = poly.contours[i].points[k];
- poly.contours[i].points[k] = p;
- }
-
- /* Revert the controls */
- if (contours[i].controls) {
- for (j = 0; j < num_points; j++) {
- poly.contours[i].controls[num_points-j-1] = contours[i].controls[j];
- }
- }
- }
- else {
- if (contours[i].controls) {
- memcpy(poly.contours[i].controls, contours[i].controls, num_points);
- }
- }
- }
- }
- }
-
- result = item->class->Contour(item, ZN_CONTOUR_ADD, index, &poly);
- if (revert) {
- result = -result;
- }
- Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(result));
-
- if (poly.contours != &poly.contour1) {
- /*
- * Must not use ZnPolyFree: the point and controls arrays
- * are passed along to the item and no longer ours.
- */
- ZnFree(poly.contours);
- }
- }
-
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Coords --
- *
- *----------------------------------------------------------------------
- */
-static int
-Coords(ZnWInfo *wi,
- int argc,
- Tcl_Obj *CONST args[],
- ZnTagSearch **search_var)
-{
- ZnPoint *points;
- ZnItem item;
- unsigned int num_points, i;
- int result, cmd = ZN_COORDS_READ;
- long index, contour = 0;
- char *str, *controls = NULL;
- Tcl_Obj *l, *entries[3];
-
- result = ZnItemWithTagOrId(wi, args[2], &item, search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_AppendResult(wi->interp, " unknown item \"",
- Tcl_GetString(args[2]), "\"", NULL);
- return TCL_ERROR;
- }
- if (!item->class->Coords) {
- Tcl_AppendResult(wi->interp, " ", item->class->name,
- " does not support the coords command", NULL);
- return TCL_ERROR;
- }
- num_points = 0;
- /*printf(" coords: argc=%d, item %d class: %s\n",
- argc, item->id, item->class->name);*/
- if (argc == 3) {
- /* Get all coords of default contour (0). */
- if (item->class->Coords(item, 0, 0, ZN_COORDS_READ_ALL,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- coords_read:
- /*printf(" coords: read %d points, first is %g@%g\n",
- num_points, points->x, points->y);*/
- l = Tcl_GetObjResult(wi->interp);
- if (ISSET(item->class->flags, ZN_CLASS_ONE_COORD)) {
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x));
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y));
- if (controls && *controls) {
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1));
- }
- }
- else {
- for (i = 0; i < num_points; i++, points++) {
- entries[0] = Tcl_NewDoubleObj(points->x);
- entries[1] = Tcl_NewDoubleObj(points->y);
- if (controls && controls[i]) {
- entries[2] = Tcl_NewStringObj(&controls[i], 1);
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(3, entries));
- }
- else {
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(2, entries));
- }
- }
- }
- return TCL_OK;
- }
-
- /*
- * See if it is an ADD or REMOVE op.
- */
- i = 3;
- str = Tcl_GetString(args[3]);
- if ((str[0] == 'a') && (strcmp(str, "add") == 0)) {
- if ((argc < 5) || (argc > 7)) {
- Tcl_WrongNumArgs(wi->interp, 1, args,
- "coords tagOrId add ?contour? ?index? coordList");
- return TCL_ERROR;
- }
- cmd = ZN_COORDS_ADD;
- i++;
- }
- else if ((str[0] == 'r') && (strcmp(str, "remove") == 0)) {
- if ((argc != 5) && (argc != 6)) {
- Tcl_WrongNumArgs(wi->interp, 1, args,
- "coords tagOrId remove ?contour? index");
- return TCL_ERROR;
- }
- cmd = ZN_COORDS_REMOVE;
- i++;
- }
-
- /*
- * Try to see if the next param is a vertex index,
- * a contour index or a coord list.
- */
- /* printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i])); */
- if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) {
- Tcl_ResetResult(wi->interp);
- if (((argc == 5) && (cmd != ZN_COORDS_ADD) && (cmd != ZN_COORDS_REMOVE)) ||
- (argc == 6) || (argc == 7)) {
- Tcl_AppendResult(wi->interp, " incorrect contour index \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- else if ((argc == 5) && (cmd != ZN_COORDS_ADD)) {
- Tcl_AppendResult(wi->interp, " incorrect coord index \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- else if (ZnParseCoordList(wi, args[argc-1], &points,
- &controls, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (cmd == ZN_COORDS_ADD) {
- /* Append coords at end of default contour (0). */
- if (item->class->Coords(item, 0, 0, ZN_COORDS_ADD_LAST,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- else {
- /* Set all coords of default contour (0). */
- if (item->class->Coords(item, 0, 0, ZN_COORDS_REPLACE_ALL,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (controls) {
- ZnFree(controls);
- }
- return TCL_OK;
- }
-
- contour = index;
- if (argc == 4) {
- /* Get all coords of contour. */
- if (item->class->Coords(item, contour, 0, ZN_COORDS_READ_ALL,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- goto coords_read;
- }
- else if ((argc == 5) && (cmd == ZN_COORDS_REMOVE)) {
- /* Remove coord at index in default contour (0). */
- if (item->class->Coords(item, 0, index, ZN_COORDS_REMOVE,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- /*
- * Try to see if the next param is a vertex index or a coord list.
- */
- i++;
- /*printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i]));*/
- if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) {
- Tcl_ResetResult(wi->interp);
- if ((argc == 7) || ((argc == 6) && (cmd != ZN_COORDS_ADD))) {
- Tcl_AppendResult(wi->interp, " incorrect coord index \"",
- Tcl_GetString(args[i]), "\"", NULL);
- return TCL_ERROR;
- }
- else if (ZnParseCoordList(wi, args[argc-1], &points,
- &controls, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (cmd == ZN_COORDS_ADD) {
- /* Append coords at end of contour. */
- if (item->class->Coords(item, contour, 0, ZN_COORDS_ADD_LAST,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- else {
- /* Set all coords of contour. */
- if (item->class->Coords(item, contour, 0, ZN_COORDS_REPLACE_ALL,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- }
- if (controls) {
- ZnFree(controls);
- }
- return TCL_OK;
- }
- if (argc == 5) {
- /* Get coord of contour at index. */
- if (item->class->Coords(item, contour, index, ZN_COORDS_READ,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (num_points) {
- /*printf(" coords: read contour:%d, index:%d, point is %g@%g\n",
- contour, index, points->x, points->y); */
- l = Tcl_GetObjResult(wi->interp);
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x));
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y));
- if (controls && *controls) {
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1));
- }
- }
- return TCL_OK;
- }
- else if ((argc == 6) && (cmd == ZN_COORDS_REMOVE)) {
- /* Remove coord of contour at index. */
- if (item->class->Coords(item, contour, index, ZN_COORDS_REMOVE,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- return TCL_OK;
- }
-
- /* Set a single coord or add coords at index in contour. */
- if (ZnParseCoordList(wi, args[argc-1], &points,
- &controls, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (argc == 6) {
- num_points = 1;
- cmd = ZN_COORDS_REPLACE;
- }
- if (item->class->Coords(item, contour, index, cmd,
- &points, &controls, &num_points) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (controls) {
- ZnFree(controls);
- }
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * WidgetObjCmd --
- *
- * This procedure is invoked to process the Tcl command
- * that corresponds to a widget managed by this module.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *----------------------------------------------------------------------
- */
-static int
-WidgetObjCmd(ClientData client_data, /* Information about the widget. */
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- Tcl_Obj *CONST args[]) /* Arguments. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- int length, result, cmd_index, index;
- ZnItem item, item2;
- int field = ZN_NO_PART;
- unsigned int num = 0, i, j;
- char *end, *str;
- ZnTransfo *t = NULL;
- Tcl_Obj *l;
- ZnTagSearch *search_var = NULL;
- Tcl_HashEntry *entry;
- ZnPoint *points;
- ZnPoint p;
- unsigned int num_points;
- ZnList to_points;
- Tcl_Obj *entries[3];
- char c[] = "c";
- double d;
-
-#ifdef PTK_800
- static char *sub_cmd_strings[] =
-#else
- static CONST char *sub_cmd_strings[] =
-#endif
- {
- "add", "addtag", "anchorxy", "bbox", "becomes", "bind",
- "cget", "chggroup", "clone", "configure", "contour",
- "coords", "currentpart", "cursor", "dchars",
- "dtag", "find", "fit", "focus", "gdelete",
- "gettags", "gname", "group", "hasanchors", "hasfields",
- "hastag", "index", "insert", "itemcget", "itemconfigure",
- "layout", "lower", "monitor", "numparts", "postscript",
- "raise", "remove", "rotate", "scale", "select", "skew",
- "smooth", "tapply", "tcompose", "tdelete", "tget",
- "transform", "translate", "treset", "trestore", "tsave",
- "tset", "type", "vertexat", "xview", "yview", NULL
- };
- enum sub_cmds {
- ZN_W_ADD, ZN_W_ADDTAG, ZN_W_ANCHORXY, ZN_W_BBOX, ZN_W_BECOMES, ZN_W_BIND,
- ZN_W_CGET, ZN_W_CHGGROUP, ZN_W_CLONE, ZN_W_CONFIGURE,
- ZN_W_CONTOUR, ZN_W_COORDS, ZN_W_CURRENTPART, ZN_W_CURSOR, ZN_W_DCHARS,
- ZN_W_DTAG, ZN_W_FIND, ZN_W_FIT, ZN_W_FOCUS, ZN_W_GDELETE,
- ZN_W_GETTAGS, ZN_W_GNAME, ZN_W_GROUP, ZN_W_HASANCHORS, ZN_W_HASFIELDS,
- ZN_W_HASTAG, ZN_W_INDEX, ZN_W_INSERT, ZN_W_ITEMCGET, ZN_W_ITEMCONFIGURE,
- ZN_W_LAYOUT, ZN_W_LOWER, ZN_W_MONITOR, ZN_W_NUMPARTS, ZN_W_POSTSCRIPT,
- ZN_W_RAISE, ZN_W_REMOVE, ZN_W_ROTATE, ZN_W_SCALE, ZN_W_SELECT, ZN_W_SKEW,
- ZN_W_SMOOTH, ZN_W_TAPPLY, ZN_W_TCOMPOSE, ZN_W_TDELETE, ZN_W_TGET,
- ZN_W_TRANSFORM, ZN_W_TRANSLATE, ZN_W_TRESET, ZN_W_TRESTORE, ZN_W_TSAVE,
- ZN_W_TSET, ZN_W_TYPE, ZN_W_VERTEX_AT, ZN_W_XVIEW, ZN_W_YVIEW
- };
-#ifdef PTK_800
- static char *sel_cmd_strings[] =
-#else
- static CONST char *sel_cmd_strings[] =
-#endif
- {
- "adjust", "clear", "from", "item", "to", NULL
- };
- enum sel_cmds {
- ZN_SEL_ADJUST, ZN_SEL_CLEAR, ZN_SEL_FROM, ZN_SEL_ITEM, ZN_SEL_TO
- };
-
-
- if (argc < 2) {
- Tcl_WrongNumArgs(interp, 1, args, "subcommand ?args?");
- return TCL_ERROR;
- }
-
- Tcl_Preserve((ClientData) wi);
-
- if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings,
- "subcommand", 0, &cmd_index) != TCL_OK) {
- goto error;
- }
- result = TCL_OK;
-
- /*printf("executing command \"%s\", argc=%d\n",
- Tcl_GetString(args[1]), argc);*/
- switch((enum sub_cmds) cmd_index) {
- /*
- * add
- */
- case ZN_W_ADD:
- {
- ZnItem group;
- ZnItemClass cls;
-
- if (argc == 2) { /* create subcommand alone, return the list of known
- * object types. */
- ZnItemClass *classes = ZnListArray(ZnItemClassList());
-
- num = ZnListSize(ZnItemClassList());
- l = Tcl_GetObjResult(interp);
- for (i = 0; i < num; i++) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(classes[i]->name, -1));
- }
- goto done;
- }
- if ((argc < 4)) {
- add_err:
- Tcl_WrongNumArgs(interp, 1, args, "add type group ?args?");
- goto error;
- }
- str = Tcl_GetString(args[2]);
- if (str[0] == '-') {
- goto add_err;
- }
- cls = ZnLookupItemClass(str);
- if (!cls) {
- Tcl_AppendResult(interp, "unknown item type \"", str, "\"", NULL);
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[3], &group, &search_var);
- if ((result == TCL_ERROR) || (group == ZN_NO_ITEM) ||
- (group->class != ZnGroup)) {
- Tcl_AppendResult(interp, ", group item expected, got \"",
- Tcl_GetString(args[3]), "\"", NULL);
- goto error;
- }
-
- argc -= 4;
- args += 4;
- item = ZnCreateItem(wi, cls, &argc, &args);
- if (item == ZN_NO_ITEM) {
- goto error;
- }
- ZnITEM.InsertItem(item, group, ZN_NO_ITEM, True);
- if (ZnITEM.ConfigureItem(item, ZN_NO_PART, argc, args, True) == TCL_ERROR) {
- goto error;
- }
- wi->hot_item = item;
- wi->hot_prev = item->previous;
- l = Tcl_NewLongObj(item->id);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * addtag
- */
- case ZN_W_ADDTAG:
- {
- if (argc < 4) {
- Tcl_WrongNumArgs(interp, 1, args, "addtag tag searchCommand ?arg arg ...?");
- goto error;
- }
- result = FindItems(wi, argc, args, args[2], 3, &search_var);
- }
- break;
- /*
- * anchorxy
- */
- case ZN_W_ANCHORXY:
- {
- Tk_Anchor anchor;
-
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "anchorxy tagOrId anchor");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) ||
- ISCLEAR(item->class->flags, ZN_CLASS_HAS_ANCHORS)) {
- Tcl_AppendResult(interp, "unknown item or doesn't support anchors \"",
- Tcl_GetString(args[2]), NULL);
- goto error;
- }
- if (Tk_GetAnchor(interp, Tcl_GetString(args[3]), &anchor)) {
- goto error;
- }
- /*
- * If something has changed in the geometry we need to
- * update or the anchor location will be erroneous.
- */
- Update(wi);
- item->class->GetAnchor(item, anchor, &p);
- l = Tcl_GetObjResult(wi->interp);
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.x));
- Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.y));
- }
- break;
- /*
- * becomes
- */
- case ZN_W_BECOMES:
- {
- Tcl_AppendResult(interp, "Command not yet implemented", NULL);
- goto error;
- }
- break;
- /*
- * bbox
- */
- case ZN_W_BBOX:
- {
- ZnBBox bbox;
- ZnDim width, height;
- ZnFieldSet fs;
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "bbox ?-field fieldNo? ?-label? tagOrId ?tagOrId ...?");
- goto error;
- }
- argc -= 2;
- args += 2;
-
- Update(wi);
- ZnResetBBox(&bbox);
-
- str = Tcl_GetString(args[0]);
- if (*str == '-') {
- if ((strcmp(str, "-field") == 0) && (argc > 2)) {
- if (Tcl_GetIntFromObj(wi->interp, args[1], &field) == TCL_ERROR) {
- goto error;
- }
- argc -= 2;
- args += 2;
- }
- else if ((strcmp(str, "-label") == 0) && (argc > 1)) {
- field = -1;
- argc--;
- args++;
- }
- else {
- Tcl_AppendResult(interp, "bbox option should be -field numField or -label",
- NULL);
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[0], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) ||
- ! item->class->GetFieldSet) {
- Tcl_AppendResult(interp, "unknown item or doesn't support fields \"",
- Tcl_GetString(args[0]), "\"", NULL);
- goto error;
- }
- fs = item->class->GetFieldSet(item);
- if (field >= 0) {
- if ((unsigned int) field >= fs->num_fields) {
- Tcl_AppendResult(interp, "field index is out of bounds", NULL);
- goto error;
- }
- ZnFIELD.GetFieldBBox(fs, field, &bbox);
- }
- else {
- ZnFIELD.GetLabelBBox(fs, &width, &height);
- if (width && height) {
- p.x = ZnNearestInt(fs->label_pos.x);
- p.y = ZnNearestInt(fs->label_pos.y);
- ZnAddPointToBBox(&bbox, p.x, p.y);
- p.x += width;
- p.y += height;
- ZnAddPointToBBox(&bbox, p.x, p.y);
- }
- }
- }
- else {
- for (i = 0; i < (unsigned int) argc; i++) {
- /*
- * Check for options in wrong place amidst tags.
- */
- str = Tcl_GetString(args[i]);
- if (*str == '-') {
- Tcl_AppendResult(interp, "bbox options should be specified before any tag", NULL);
- goto error;
- }
- if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnAddBBoxToBBox(&bbox, &item->item_bounding_box);
- }
- }
- }
-
- if (!ZnIsEmptyBBox(&bbox)) {
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.y));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.y));
- }
- }
- break;
- /*
- * bind
- */
- case ZN_W_BIND:
- {
- ClientData elem = 0;
- int part = ZN_NO_PART;
-
- if ((argc < 3) || (argc > 6)) {
- Tcl_WrongNumArgs(interp, 1, args,
- "bind tagOrId ?part? ?sequence? ?command?");
- goto error;
- }
- /*
- * Test if (a) an itemid or (b) an itemid:part or
- * (c) an item part or (d) a tag is provided.
- */
- str = Tcl_GetString(args[2]);
-
- argc -= 3;
- args += 3;
-
- if (isdigit(str[0])) {
- int id;
-
- id = strtoul(str, &end, 0);
- if ((*end != 0) && (*end != ':')) {
- goto bind_a_tag;
- }
- entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
- if (entry == NULL) {
- Tcl_AppendResult(interp, "item \"", str, "\" doesn't exist", NULL);
- goto error;
- }
- item = elem = Tcl_GetHashValue(entry);
- if (!elem) {
- goto error;
- }
-
- if (*end == ':') {
- /*
- * The part is provided with the id (old method).
- */
- end++;
- part_encode:
- if (item->class->Part) {
- l = Tcl_NewStringObj(end, -1);
- if (item->class->Part(item, &l, &part) == TCL_ERROR) {
- goto error;
- }
- elem = EncodeItemPart(item, part);
- }
- else {
- Tcl_AppendResult(interp, "item \"", str, "\" doesn't have parts", NULL);
- goto error;
- }
- }
- else {
- /*
- * Check if a part is given in the next parameter
- * (alternative method for providing a part).
- */
- if (argc > 3) {
- str = Tcl_GetString(args[0]);
- if (str[0] != '<') {
- end = str;
- argc--;
- args++;
- goto part_encode;
- }
- }
- }
- /*printf("adding element 0x%X to the binding table of item 0x%X\n", elem, item);*/
- }
- else {
- bind_a_tag:
- elem = (ClientData) Tk_GetUid(str);
- }
-
- /*
- * Make a binding table if the widget doesn't already have one.
- */
- if (wi->binding_table == NULL) {
- wi->binding_table = Tk_CreateBindingTable(interp);
- }
-
- if (argc == 2) {
- int append = 0;
- unsigned long mask;
-
- str = Tcl_GetString(args[1]);
- if (str[0] == 0) {
- result = Tk_DeleteBinding(interp, wi->binding_table, elem,
- Tcl_GetString(args[0]));
- goto done;
- }
-#ifdef PTK
- mask = Tk_CreateBinding(interp, wi->binding_table,
- elem, Tcl_GetString(args[0]), args[1], append);
-#else
- if (str[0] == '+') {
- str++;
- append = 1;
- }
- mask = Tk_CreateBinding(interp, wi->binding_table,
- elem, Tcl_GetString(args[0]), str, append);
-#endif
- if (mask == 0) {
- goto error;
- }
- if (mask & (unsigned) ~(ButtonMotionMask | Button1MotionMask |
- Button2MotionMask | Button3MotionMask |
- Button4MotionMask | Button5MotionMask |
- ButtonPressMask | ButtonReleaseMask |
- EnterWindowMask | LeaveWindowMask |
- KeyPressMask | KeyReleaseMask |
- PointerMotionMask | VirtualEventMask)) {
- Tk_DeleteBinding(interp, wi->binding_table, elem, Tcl_GetString(args[3]));
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "requested illegal events; ",
- "only key, button, motion, enter, leave ",
- "and virtual events may be used", NULL);
- goto error;
- }
- }
- else if (argc == 1) {
-#ifdef PTK
- Tcl_Obj *command;
- command = Tk_GetBinding(interp, wi->binding_table, elem,
- Tcl_GetString(args[0]));
- if (command == NULL) {
- char *string = Tcl_GetString(Tcl_GetObjResult(interp));
- /*
- * Ignore missing binding errors. This is a special hack
- * that relies on the error message returned by FindSequence
- * in tkBind.c.
- */
- if (string[0] != '\0') {
- goto error;
- }
- else {
- Tcl_ResetResult(interp);
- }
- }
- else {
- Tcl_SetObjResult(interp, command);
- }
-#else
- CONST char *command;
- command = Tk_GetBinding(interp, wi->binding_table, elem,
- Tcl_GetString(args[0]));
- if (command == NULL) {
- goto error;
- }
- Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
-#endif
- }
- else {
- Tk_GetAllBindings(interp, wi->binding_table, elem);
- }
- }
- break;
- /*
- * cget
- */
- case ZN_W_CGET:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "cget option");
- goto error;
- }
-#ifdef PTK_800
- result = Tk_ConfigureValue(interp, wi->win, config_specs,
- (char *) wi, Tcl_GetString(args[2]), 0);
-#else
- l = Tk_GetOptionValue(interp, (char *) wi, wi->opt_table, args[2], wi->win);
- if (l == NULL) {
- goto error;
- }
- Tcl_SetObjResult(interp, l);
-#endif
- }
- break;
- /*
- * chggroup
- */
- case ZN_W_CHGGROUP:
- {
- ZnItem grp, scan;
- int adjust=0;
- ZnTransfo inv, t, t2, *this_one=NULL;
-
- if ((argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "chggroup tagOrIg group ?adjustTransform?");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[3], &grp, &search_var);
- if ((result == TCL_ERROR) || (grp == ZN_NO_ITEM)|| (grp->class != ZnGroup)) {
- goto error;
- }
- if (item->parent == grp) {
- /*
- * Nothing to be done, the item is already in the
- * target group.
- */
- goto done;
- }
- /*
- * Check the ancestors to find if item is an
- * ancestor of grp, which would lead to a
- * forbidden move.
- */
- for (scan = grp; scan && (scan != item); scan = scan->parent);
- if (scan == item) {
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
- "\" is a descendant of \"", Tcl_GetString(args[2]),
- "\" and can't be used as its parent", NULL);
- goto error;
- }
- if (argc == 5) {
- if (Tcl_GetBooleanFromObj(interp, args[4], &adjust) != TCL_OK) {
- goto error;
- }
- }
- if ((item->parent == grp) || (item->parent == ZN_NO_ITEM)) {
- goto done;
- }
- if (adjust) {
- ZnITEM.GetItemTransform(grp, &t);
- ZnTransfoInvert(&t, &inv);
- ZnITEM.GetItemTransform(item->parent, &t);
- ZnTransfoCompose(&t2, &t, &inv);
- this_one = &t2;
- if (item->transfo) {
- ZnTransfoCompose(&t, item->transfo, &t2);
- this_one = &t;
- }
- }
- ZnITEM.ExtractItem(item);
- ZnITEM.InsertItem(item, grp, ZN_NO_ITEM, True);
- /*
- * The item can be a group in which case we must
- * use the ZN_TRANSFO_FLAG to force an update of
- * the children. In all other case ZN_COORDS_FLAG
- * is enough.
- */
- ZnITEM.Invalidate(item,
- item->class==ZnGroup?ZN_TRANSFO_FLAG:ZN_COORDS_FLAG);
- if (adjust) {
- ZnITEM.SetTransfo(item, this_one);
- }
- }
- break;
- /*
- * clone
- */
- case ZN_W_CLONE:
- {
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "clone tagOrId ?option value ...?");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) ||
- (item == ZN_NO_ITEM) || (item == wi->top_group)) {
- goto error;
- }
- argc -= 3;
- args += 3;
- item2 = ZnITEM.CloneItem(item);
- ZnITEM.InsertItem(item2, item->parent, ZN_NO_ITEM, True);
- if (ZnITEM.ConfigureItem(item2, ZN_NO_PART, argc, args, False) == TCL_ERROR) {
- goto error;
- }
- l = Tcl_NewLongObj(item2->id);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * configure
- */
- case ZN_W_CONFIGURE:
- {
-#ifdef PTK_800
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, wi->win, config_specs,
- (char *) wi, (char *) NULL, 0);
- }
- else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, wi->win, config_specs,
- (char *) wi, Tcl_GetString(args[2]), 0);
- }
- else {
- result = Configure(interp, wi, argc-2, args+2, TK_CONFIG_ARGV_ONLY);
- }
-#else
- if (argc == 2) {
- l = Tk_GetOptionInfo(interp, (char *) wi, wi->opt_table,
- (argc == 3) ? args[2] : NULL, wi->win);
- if (l == NULL) {
- goto error;
- }
- else {
- Tcl_SetObjResult(interp, l);
- }
- }
- else {
- result = Configure(interp, wi, argc-2, args+2);
- }
-#endif
- }
- break;
- /*
- * contour
- */
- case ZN_W_CONTOUR:
- {
- if ((argc < 3) || (argc > 7)) {
- Tcl_WrongNumArgs(interp, 1, args,
- "contour tagOrId ?operator windingFlag? ?index? ?coordListOrTagOrId?");
- goto error;
- }
- if (Contour(wi, argc, args, &search_var) == TCL_ERROR) {
- goto error;
- }
- break;
- }
- /*
- * coords
- */
- case ZN_W_COORDS:
- {
- if ((argc < 3) || (argc > 7)) {
- Tcl_WrongNumArgs(interp, 1, args,
- "coords tagOrId ?add/remove? ?contour? ?index? ?coordList?");
- goto error;
- }
- if (Coords(wi, argc, args, &search_var) == TCL_ERROR) {
- goto error;
- }
- }
- break;
- /*
- * currentpart
- */
- case ZN_W_CURRENTPART:
- {
- ZnBool only_fields = False;
- if ((argc != 2) && (argc != 3)) {
- Tcl_WrongNumArgs(interp, 1, args, "currentpart ?onlyFields?");
- goto error;
- }
- if (argc == 3) {
- if (Tcl_GetBooleanFromObj(interp, args[2], &only_fields) != TCL_OK) {
- goto error;
- }
- }
- if ((wi->current_item != ZN_NO_ITEM) &&
- (wi->current_item->class->Part != NULL) &&
- ((wi->current_part >= 0) || !only_fields)) {
- l = NULL;
- wi->current_item->class->Part(wi->current_item, &l, &wi->current_part);
- Tcl_SetObjResult(interp, l);
- }
- }
- break;
- /*
- * cursor
- */
- case ZN_W_CURSOR:
- {
- if ((argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId ?field? index");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- if (argc == 5) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if ((item->class->Cursor == NULL) ||
- (item->class->Index == NULL)) {
- continue;
- }
- result = (*item->class->Index)(item, field, args[3], &index);
- if (result != TCL_OK) {
- goto error;
- }
-
- (*item->class->Cursor)(item, field, index);
- if ((item == wi->focus_item) && (field == wi->focus_field) &&
- wi->text_info.cursor_on) {
- ZnITEM.Invalidate(item, ZN_DRAW_FLAG);
- }
- }
- }
- break;
- /*
- * dchars
- */
- case ZN_W_DCHARS:
- {
- int first, last;
- ZnTextInfo *ti = &wi->text_info;
-
- if ((argc < 4) || (argc > 6)) {
- Tcl_WrongNumArgs(interp, 1, args, "dchars tagOrId ?field? first ?last?");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- if (argc == 6) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if ((item->class->Index == NULL) ||
- (item->class->DeleteChars == NULL)) {
- continue;
- }
- result = (*item->class->Index)(item, field, args[3], &first);
- if (result != TCL_OK) {
- goto error;
- }
- if (argc == 5) {
- result = (*item->class->Index)(item, field, args[4], &last);
- if (result != TCL_OK) {
- goto error;
- }
- }
- else {
- last = first;
- }
- (*item->class->DeleteChars)(item, field, &first, &last);
-
- /*
- * Update indexes for the selection to reflect the
- * change.
- */
- if ((ti->sel_item == item) && (ti->sel_field == field)) {
- int count = last + 1 - first;
- if (ti->sel_first > first) {
- ti->sel_first -= count;
- if (ti->sel_first < first) {
- ti->sel_first = first;
- }
- }
- if (ti->sel_last >= first) {
- ti->sel_last -= count;
- if (ti->sel_last < (first-1)) {
- ti->sel_last = first-1;
- }
- }
- if (ti->sel_first >= ti->sel_last) {
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
- }
- if ((ti->anchor_item == item) && (ti->anchor_field == field) &&
- (ti->sel_anchor > first)) {
- ti->sel_anchor -= count;
- if (ti->sel_anchor < first) {
- ti->sel_anchor = first;
- }
- }
- }
- }
- }
- break;
- /*
- * dtag
- */
- case ZN_W_DTAG:
- {
- Tk_Uid tag;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_WrongNumArgs(interp, 1, args, "dtag tagOrId ?tagToDelete?");
- goto error;
- }
- if (argc == 4) {
- tag = Tk_GetUid(Tcl_GetString(args[3]));
- }
- else {
- tag = Tk_GetUid(Tcl_GetString(args[2]));
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.RemoveTag(item, (char *) tag);
- }
- }
- break;
- /*
- * find
- */
- case ZN_W_FIND:
- {
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "find searchCommand ?arg arg ...?");
- goto error;
- }
- result = FindItems(wi, argc, args, NULL, 2, &search_var);
- }
- break;
- /*
- * fit
- */
- case ZN_W_FIT:
- {
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "fit coordList error");
- goto error;
- }
- if (ZnParseCoordList(wi, args[2], &points,
- NULL, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
- goto error;
- }
- to_points = ZnListNew(32, sizeof(ZnPoint));
- ZnFitBezier(points, num_points, d, to_points);
- points = (ZnPoint *) ZnListArray(to_points);
- num_points = ZnListSize(to_points);
- l = Tcl_GetObjResult(interp);
- for (i = 0; i < num_points; i++, points++) {
- entries[0] = Tcl_NewDoubleObj(points->x);
- entries[1] = Tcl_NewDoubleObj(points->y);
- if (i % 3) {
- entries[2] = Tcl_NewStringObj(c, -1);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries));
- }
- else {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
- }
- }
- ZnListFree(to_points);
- }
- break;
- /*
- * focus
- */
- case ZN_W_FOCUS:
- {
- if (argc > 4) {
- Tcl_WrongNumArgs(interp, 1, args, "focus ?tagOrId? ?field?");
- goto error;
- }
- item = wi->focus_item;
- if (argc == 2) {
- field = wi->focus_field;
- if (item != ZN_NO_ITEM) {
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id));
- if (field != ZN_NO_PART) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(field));
- }
- else {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1));
- }
- }
- break;
- }
- if ((item != ZN_NO_ITEM) && (item->class->Cursor != NULL) &&
- ISSET(wi->flags, ZN_GOT_FOCUS)) {
- ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
- }
- if (Tcl_GetString(args[2])[0] == 0) {
- wi->focus_item = ZN_NO_ITEM;
- wi->focus_field = ZN_NO_PART;
- break;
- }
- if (ZnItemWithTagOrId(wi, args[2], &item, &search_var) == TCL_ERROR) {
- goto error;
- }
- if (argc == 4) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- }
- wi->focus_item = item;
- wi->focus_field = field;
- if (ISSET(wi->flags, ZN_GOT_FOCUS) && (item->class->Cursor != NULL)) {
- ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
- }
- }
- break;
- /*
- * gdelete
- */
- case ZN_W_GDELETE:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "gdelete gName");
- goto error;
- }
- ZnDeleteGradientName(Tcl_GetString(args[2]));
- }
- break;
- /*
- * gettags
- */
- case ZN_W_GETTAGS:
- {
- Tk_Uid *tags;
-
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "gettags tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- if (!item->tags || !ZnListSize(item->tags)) {
- goto done;
- }
- else {
- num = ZnListSize(item->tags);
- tags = (Tk_Uid *) ZnListArray(item->tags);
- l = Tcl_GetObjResult(interp);
- for (i = 0; i < num; i++) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(tags[i], -1));
- }
- }
- }
- break;
- /*
- * gname
- */
- case ZN_W_GNAME:
- {
- ZnBool ok;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_WrongNumArgs(interp, 1, args, "gname ?grad? gName");
- goto error;
- }
- if (argc == 3) {
- l = Tcl_NewBooleanObj(ZnGradientNameExists(Tcl_GetString(args[2])));
- Tcl_SetObjResult(interp, l);
- }
- else {
- ok = ZnNameGradient(interp, wi->win, Tcl_GetString(args[2]),
- Tcl_GetString(args[3]));
- if (!ok) {
- goto error;
- }
- }
- }
- break;
- /*
- * group
- */
- case ZN_W_GROUP:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "group tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- if (item->parent != ZN_NO_ITEM) {
- l = Tcl_NewLongObj(item->parent->id);
- Tcl_SetObjResult(interp, l);
- }
- else {
- /*
- * Top group is its own parent.
- */
- l = Tcl_NewLongObj(item->id);
- Tcl_SetObjResult(interp, l);
- }
- }
- break;
- /*
- * hasanchors
- */
- case ZN_W_HASANCHORS:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "hasanchors tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- l = Tcl_NewBooleanObj(ISSET(item->class->flags, ZN_CLASS_HAS_ANCHORS) ? 1 : 0);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * hasfields
- */
- case ZN_W_HASFIELDS:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "hasfields tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- l = Tcl_NewBooleanObj(item->class->GetFieldSet?1:0);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * hastag
- */
- case ZN_W_HASTAG:
- {
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "hastag tagOrId tag");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- l = Tcl_NewBooleanObj(ZnITEM.HasTag(item,
- Tk_GetUid(Tcl_GetString(args[3]))));
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * index
- */
- case ZN_W_INDEX:
- {
- if ((argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "index tagOrId ?field? string");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- if (argc == 5) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if (item->class->Index != NULL) {
- result = (*item->class->Index)(item, field, args[3], &index);
- if (result != TCL_OK) {
- goto error;
- }
- l = Tcl_NewIntObj(index);
- Tcl_SetObjResult(interp, l);
- goto done;
- }
- }
- Tcl_AppendResult(interp, "can't find an indexable item \"",
- Tcl_GetString(args[2]), "\"", NULL);
- goto error;
- }
- break;
- /*
- * insert
- */
- case ZN_W_INSERT:
- {
- ZnTextInfo *ti = &wi->text_info;
- char *chars;
-
- if ((argc != 5) && (argc != 6)) {
- Tcl_WrongNumArgs(interp, 1, args, "insert tagOrId ?field? before string");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- if (argc == 6) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if ((item->class->Index == NULL) ||
- (item->class->InsertChars == NULL)) {
- continue;
- }
- result = (*item->class->Index)(item, field, args[3], &index);
- if (result != TCL_OK) {
- goto error;
- }
- chars = Tcl_GetString(args[4]);
- (*item->class->InsertChars)(item, field, &index, chars);
- /*
- * Inserting characters invalidates selection indices.
- */
- if ((ti->sel_item == item) && (ti->sel_field == field)) {
- length = strlen(chars);
- if (ti->sel_first >= index) {
- ti->sel_first += length;
- }
- if (ti->sel_last >= index) {
- ti->sel_last += length;
- }
- if ((ti->anchor_item == item) && (ti->anchor_field == field) &&
- (ti->sel_anchor >= index)) {
- ti->sel_anchor += length;
- }
- }
- }
- }
- break;
- /*
- * itemcget
- */
- case ZN_W_ITEMCGET:
- {
- if (argc < 4) {
- itemcget_syntax:
- Tcl_WrongNumArgs(interp, 1, args, "itemcget tagOrId ?field? option");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- if (argc == 5) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- if (argc != 4) {
- goto itemcget_syntax;
- }
- if (ZnITEM.QueryItem(item, field, 1, &args[3]) != TCL_OK) {
- goto error;
- }
- }
- break;
- /*
- * itemconfigure
- */
- case ZN_W_ITEMCONFIGURE:
- {
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args,
- "itemconfigure tagOrId ?field? option value ?option value? ...");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- if ((argc > 3) && (Tcl_GetString(args[3])[0] != '-')) {
- if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[3])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[3]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- argc -= 3;
- args += 3;
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if (argc < 2) {
- if (field == ZN_NO_PART) {
- result = ZnAttributesInfo(wi->interp, item, item->class->attr_desc, argc, args);
- }
- else if (item->class->GetFieldSet) {
- ZnFieldSet fs = item->class->GetFieldSet(item);
- if (field < (int) ZnFIELD.NumFields(fs)) {
- result = ZnAttributesInfo(wi->interp, ZnFIELD.GetFieldStruct(fs, field),
- ZnFIELD.attr_desc, argc, args);
- }
- else {
- Tcl_AppendResult(interp, "field index out of bound", NULL);
- goto error;
- }
- }
- else {
- Tcl_AppendResult(interp, "the item does not support fields", NULL);
- goto error;
- }
- goto done;
- }
- else {
- result = ZnITEM.ConfigureItem(item, field, argc, args, False);
- }
- if (result == TCL_ERROR) {
- goto error;
- }
- }
- }
- break;
- /*
- * layout
- */
- case ZN_W_LAYOUT:
- {
- if (argc < 4) {
- Tcl_WrongNumArgs(interp, 1, args,
- "layout operator ?args...? tagOrId ?tagOrId...?");
- goto error;
- }
- if (LayoutItems(wi, argc-2, args+2) == TCL_ERROR) {
- goto error;
- }
- }
- break;
- /*
- * lower
- */
- case ZN_W_LOWER:
- {
- ZnItem first, group, mark = ZN_NO_ITEM;
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "lower tagOrId ?belowThis?");
- goto error;
- }
- if (argc == 4) {
- if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- mark = item;
- }
- if (mark == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "unknown tag or item \"",
- Tcl_GetString(args[3]), "\"", NULL);
- goto error;
- }
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- item = ZnTagSearchFirst(search_var);
- if ((item == ZN_NO_ITEM) || (item == wi->top_group)) {
- goto done;
- }
- first = item;
- if (mark == ZN_NO_ITEM) {
- mark = ZnGroupTail(item->parent);
- }
- group = mark->parent;
- do {
- if ((item->parent == group) && (item != mark)) {
- ZnITEM.UpdateItemPriority(item, mark, False);
- mark = item;
- }
- item = ZnTagSearchNext(search_var);
- }
- while ((item != ZN_NO_ITEM) && (item != first));
- }
- break;
- /*
- * monitor
- */
- case ZN_W_MONITOR:
- {
-#ifndef _WIN32
- ZnBool on_off;
-
- if ((argc != 2) && (argc != 3)) {
- Tcl_WrongNumArgs(interp, 1, args, "monitor ?onOff?");
- goto error;
- }
- if (argc == 3) {
- if (Tcl_GetBooleanFromObj(interp, args[2], &on_off) != TCL_OK) {
- goto error;
- }
- ASSIGN(wi->flags, ZN_MONITORING, on_off);
- if (on_off == True) {
- ZnResetChronos(wi->total_draw_chrono);
- ZnResetChronos(wi->this_draw_chrono);
- }
- }
- if ((argc == 2) || (on_off == False)) {
- long ttime, ltime;
- int num_actions;
- ZnGetChrono(wi->total_draw_chrono, &ttime, &num_actions);
- ZnGetChrono(wi->this_draw_chrono, &ltime, NULL);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(num_actions));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ltime));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));
- /*Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_w));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_h));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));*/
- }
-#endif
- }
- break;
- /*
- * numparts
- */
- case ZN_W_NUMPARTS:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "numparts tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- l = Tcl_NewIntObj((int) item->class->num_parts);
- Tcl_SetObjResult(interp, l);
- }
- break;
- /*
- * postscript
- */
- case ZN_W_POSTSCRIPT:
- {
- if (ZnPostScriptCmd(wi, argc, args) != TCL_OK) {
- goto error;
- }
- }
- break;
- /*
- * raise
- */
- case ZN_W_RAISE:
- {
- ZnItem group, mark = ZN_NO_ITEM;
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "raise tagOrId ?aboveThis?");
- goto error;
- }
- if (argc == 4) {
- /*
- * Find the topmost item with the tag.
- */
- if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
- goto error;
- }
- mark = ZnTagSearchFirst(search_var);
- if (mark == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "unknown tag or item \"",
- Tcl_GetString(args[3]), "\"", NULL);
- goto error;
- }
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- item = ZnTagSearchFirst(search_var);
- if ((item == ZN_NO_ITEM) || (item == wi->top_group)) {
- goto done;
- }
- if (mark == ZN_NO_ITEM) {
- mark = ZnGroupHead(item->parent);
- }
- group = mark->parent;
- for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if (item->parent != group) {
- continue;
- }
- if (item != mark) {
- ZnITEM.UpdateItemPriority(item, mark, True);
- }
- }
- }
- break;
- /*
- * remove
- */
- case ZN_W_REMOVE:
- {
- unsigned int num_fields;
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "remove tagOrId ?tagOrId ...?");
- goto error;
- }
- argc -= 2;
- args += 2;
- for (i = 0; i < (unsigned int) argc; i++) {
- if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if (item == wi->top_group) {
- continue;
- }
- if (wi->binding_table != NULL) {
- Tk_DeleteAllBindings(wi->binding_table, (ClientData) item);
- if (item->class->GetFieldSet) {
- num_fields = ZnFIELD.NumFields(item->class->GetFieldSet(item));
- for (j = 0; j < num_fields; j++) {
- Tk_DeleteAllBindings(wi->binding_table,
- (ClientData) EncodeItemPart(item, j));
- }
- }
- for (j = 0; j < item->class->num_parts; j++) {
- Tk_DeleteAllBindings(wi->binding_table,
- (ClientData) EncodeItemPart(item, -(int)(j+2)));
- }
- }
- ZnITEM.DestroyItem(item);
- }
- }
- }
- break;
- /*
- * rotate
- */
- case ZN_W_ROTATE:
- {
- ZnBool deg=False;
-
- if ((argc < 4) && (argc > 7)) {
- Tcl_WrongNumArgs(interp, 1, args, "rotate tagOrIdOrTransform angle ?degree? ?centerX centerY?");
- goto error;
- }
-
- if (argc > 5) {
- if (Tcl_GetDoubleFromObj(interp, args[argc-2], &d) == TCL_ERROR) {
- goto error;
- }
- p.x = d;
- if (Tcl_GetDoubleFromObj(interp, args[argc-1], &d) == TCL_ERROR) {
- goto error;
- }
- p.y = d;
- }
- if ((argc == 5) || (argc == 7)) {
- if (Tcl_GetBooleanFromObj(interp, args[4], &deg) != TCL_OK) {
- goto error;
- }
-
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
- goto error;
- }
-
- if (t) {
- if (argc > 5) {
- ZnTranslate(t, -p.x, -p.y, False);
- }
- if (deg) {
- ZnRotateDeg(t, d);
- }
- else {
- ZnRotateRad(t, d);
- }
- if (argc > 5) {
- ZnTranslate(t, p.x, p.y, False);
- }
- }
- else {
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.RotateItem(item, d, deg, (argc > 5) ? &p : NULL);
- }
- }
- }
- break;
- /*
- * scale
- */
- case ZN_W_SCALE:
- {
- ZnPoint scale;
-
- if ((argc != 5) && (argc != 7)) {
- Tcl_WrongNumArgs(interp, 1, args,
- "scale tagOrIdOrTransform xFactor yFactor ?centerX centerY?");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
- goto error;
- }
- scale.x = d;
- if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
- goto error;
- }
- scale.y = d;
- if (argc == 7) {
- if (Tcl_GetDoubleFromObj(interp, args[5], &d) == TCL_ERROR) {
- goto error;
- }
- p.x = d;
- if (Tcl_GetDoubleFromObj(interp, args[6], &d) == TCL_ERROR) {
- goto error;
- }
- p.y = d;
- }
-
- if (t) {
- if (argc == 7) {
- ZnTranslate(t, -p.x, -p.y, False);
- }
- ZnScale(t, scale.x, scale.y);
- if (argc == 7) {
- ZnTranslate(t, p.x, p.y, False);
- }
- }
- else {
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.ScaleItem(item, scale.x, scale.y, (argc == 7) ? &p : NULL);
- }
- }
- }
- break;
- /*
- * select
- */
- case ZN_W_SELECT:
- {
- ZnTextInfo *ti = &wi->text_info;
-
- if (argc < 3) {
- Tcl_WrongNumArgs(interp, 1, args, "select option ?tagOrId? ?arg?");
- goto error;
- }
- if (argc >= 4) {
- if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if ((item->class->Index != NULL) &&
- (item->class->Selection != NULL)) {
- break;
- }
- }
- if (item == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "can't find an indexable item \"",
- Tcl_GetString(args[3]), "\"", NULL);
- goto error;
- }
- }
- if (Tcl_GetIndexFromObj(interp, args[2], sel_cmd_strings,
- "selection option", 0, &cmd_index) != TCL_OK) {
- goto error;
- }
- if ((argc == 5) || (argc == 6)) {
- if (argc == 6) {
- if (Tcl_GetIntFromObj(interp, args[4], &field) != TCL_OK) {
- field = ZN_NO_PART;
- if (Tcl_GetString(args[4])[0] != 0) {
- Tcl_AppendResult(interp, "invalid field index \"",
- Tcl_GetString(args[4]),
- "\", should be a positive integer", NULL);
- goto error;
- }
- }
- argc--;
- args++;
- }
- result = item->class->Index(item, field, args[4], &index);
- if (result != TCL_OK) {
- goto error;
- }
- }
- switch ((enum sel_cmds) cmd_index) {
- case ZN_SEL_ADJUST:
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "select adjust tagOrId ?field? index");
- goto error;
- }
- if ((ti->sel_item == item) && (ti->sel_field == field)) {
- if (index < (ti->sel_first + ti->sel_last)/2) {
- ti->sel_anchor = ti->sel_last+1;
- }
- else {
- ti->sel_anchor = ti->sel_first;
- }
- }
- SelectTo(item, field, index);
- break;
- case ZN_SEL_CLEAR:
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "select clear");
- goto error;
- }
- if (ti->sel_item != ZN_NO_ITEM) {
- ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
- }
- break;
- case ZN_SEL_FROM:
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "select from tagOrId ?field? index");
- goto error;
- }
- ti->anchor_item = item;
- ti->anchor_field = field;
- ti->sel_anchor = index;
- break;
- case ZN_SEL_ITEM:
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "select item");
- goto error;
- }
- if (ti->sel_item != ZN_NO_ITEM) {
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(ti->sel_item->id));
- if (ti->sel_field != ZN_NO_PART) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ti->sel_field));
- }
- else {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1));
- }
- }
- break;
- case ZN_SEL_TO:
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "select to tagOrId ?field? index");
- goto error;
- }
- SelectTo(item, field, index);
- break;
- }
- }
- break;
- /*
- * Skew
- */
- case ZN_W_SKEW:
- {
- double x_skew, y_skew;
-
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, "skew tagOrIdOrTransform xSkewAngle ySkewAngle");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &x_skew) == TCL_ERROR) {
- goto error;
- }
- if (Tcl_GetDoubleFromObj(interp, args[4], &y_skew) == TCL_ERROR) {
- goto error;
- }
-
- if (t) {
- ZnSkewRad(t, x_skew, y_skew);
- }
- else {
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.SkewItem(item, x_skew, y_skew);
- }
- }
- }
- break;
- /*
- * smooth
- */
- case ZN_W_SMOOTH:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "smooth coordList");
- goto error;
- }
- if (ZnParseCoordList(wi, args[2], &points,
- NULL, &num_points, NULL) == TCL_ERROR) {
- return TCL_ERROR;
- }
- to_points = ZnListNew(32, sizeof(ZnPoint));
- ZnSmoothPathWithBezier(points, num_points, to_points);
- points = (ZnPoint *) ZnListArray(to_points);
- num_points = ZnListSize(to_points);
- l = Tcl_GetObjResult(interp);
- for (i = 0; i < num_points; i++, points++) {
- entries[0] = Tcl_NewDoubleObj(points->x);
- entries[1] = Tcl_NewDoubleObj(points->y);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
- }
- ZnListFree(to_points);
- }
- break;
- /*
- * tapply
- */
- case ZN_W_TAPPLY:
- {
- Tcl_AppendResult(interp, "Command not yet implemented", NULL);
- goto error;
- }
- break;
- /*
- * tcompose
- */
- case ZN_W_TCOMPOSE:
- {
- ZnTransfo *to;
- ZnBool invert=False;
- ZnTransfo res_t, inv_t;
-
- if ((argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "tcompose transformTo aTransform ?invert?");
- goto error;
- }
- if (argc == 5) {
- if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) {
- goto error;
- }
- argc--;
- }
-
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[3]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[3], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
- "\" must be either a tag, ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- t = item->transfo;
- }
-
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- to = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be either a tag, ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- to = item->transfo;
- }
-
- if (invert) {
- ZnTransfoInvert(t, &inv_t);
- ZnTransfoCompose(&res_t, to, &inv_t);
- }
- else {
- ZnTransfoCompose(&res_t, to, t);
- }
-
- if (item != ZN_NO_ITEM) {
- /* Set back the transform in the item */
- ZnITEM.SetTransfo(item, &res_t);
- }
- else {
- ZnTransfoFree(to);
- Tcl_SetHashValue(entry, ZnTransfoDuplicate(&res_t));
- }
-
- break;
- }
- /*
- * tdelete
- */
- case ZN_W_TDELETE:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "tdelete tName");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry == NULL) {
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be a transform name", (char *) NULL);
- goto error;
- }
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- ZnTransfoFree(t);
- Tcl_DeleteHashEntry(entry);
- }
- break;
- /*
- * tget
- */
- case ZN_W_TGET:
- {
- ZnPoint scale, trans;
- ZnReal rotation, skewxy;
- ZnBool raw=1, get_trans=0, get_rot=0;
- ZnBool get_scale=0, get_skew=0;
- ZnTransfo tid;
-
- if ((argc != 3) && (argc != 4)) {
- err_tget:
- Tcl_WrongNumArgs(interp, 1, args, "tget transform ?all|translation|scale|rotation|skew?");
- goto error;
- }
- if (argc == 4) {
- raw = 0;
- str = Tcl_GetString(args[3]);
- length = strlen(str);
- if (strncmp(str, "all", length) == 0) {
- get_scale = get_rot = get_trans = get_skew = 1;
- }
- else if (strncmp(str, "translation", length) == 0) {
- get_trans = 1;
- }
- else if (strncmp(str, "scale", length) == 0) {
- get_scale = 1;
- }
- else if (strncmp(str, "rotation", length) == 0) {
- get_rot = 1;
- }
- else if (strncmp(str, "skew", length) == 0) {
- get_skew = 1;
- }
- else {
- goto err_tget;
- }
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
- "\" must be either a tag, ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- t = item->transfo;
- }
- l = Tcl_GetObjResult(interp);
- if (raw) {
- if (!t) {
- ZnTransfoSetIdentity(&tid);
- t = &tid;
- }
- for (i = 0; i < 6; i++) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(t->_[i/2][i%2]));
- }
- }
- else {
- ZnTransfoDecompose(t, get_scale?&scale:NULL, get_trans?&trans:NULL,
- get_rot?&rotation:NULL, get_skew?&skewxy:NULL);
- if (get_trans) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.y));
- }
- if (get_scale) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.y));
- }
- if (get_rot) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(rotation));
- }
- if (get_skew) {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(skewxy));
- }
- }
- break;
- }
- /*
- * transform
- */
- case ZN_W_TRANSFORM:
- {
- char *controls, *tag;
- ZnPoint *p, xp;
- ZnTransfo *from_t=NULL, *to_t=NULL, *result_t;
- ZnTransfo t1, t2, t3;
- ZnBool old_format;
-
- if ((argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "transform ?tagOrIdFrom? tagOrIdTo coordlist");
- goto error;
- }
-
- if (argc == 5) {
- /*
- * Setup the source transform.
- */
- tag = Tcl_GetString(args[2]);
- if (strcmp(tag, "device") == 0) {
- from_t = &t1;
- ZnTransfoSetIdentity(from_t);
- }
- else {
- entry = Tcl_FindHashEntry(wi->t_table, tag);
- if (entry != NULL) {
- /* from is a named transform */
- from_t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]),
- "\" must be either identity or a tag or ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- ZnITEM.GetItemTransform(item, &t1);
- from_t = &t1;
- }
- }
- }
- /*
- * Setup the destination transform
- */
- tag = Tcl_GetString(args[argc-2]);
- if (strcmp(tag, "device") == 0) {
- to_t = &t2;
- ZnTransfoSetIdentity(to_t);
- }
- else {
- entry = Tcl_FindHashEntry(wi->t_table, tag);
- if (entry != NULL) {
- /* to is a named transform */
- to_t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[argc-2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]),
- "\" must be either identity a tag or ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- ZnITEM.GetItemTransform(item, &t2);
- to_t = &t2;
- }
- }
- ZnTransfoInvert(to_t, &t3);
- to_t = &t3;
- result_t = to_t;
-
- if (argc == 5) {
- ZnTransfoCompose(&t2, from_t, to_t);
- result_t = &t2;
- }
- /*ZnPrintTransfo(&t);
- ZnPrintTransfo(&inv);*/
-
- if (ZnParseCoordList(wi, args[argc-1], &p,
- &controls, &num_points, &old_format) == TCL_ERROR) {
- Tcl_AppendResult(interp, " invalid coord list \"",
- Tcl_GetString(args[argc-1]), "\"", NULL);
- goto error;
- }
- l = Tcl_GetObjResult(interp);
- if (old_format) {
- for (i = 0; i < num_points; i++, p++) {
- ZnTransformPoint(result_t, p, &xp);
- /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.x));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.y));
- /* The next case only applies for a one point
- * list with a control flag.
- */
- if (controls && controls[i]) {
- c[0] = controls[i];
- Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(c, -1));
- }
- }
- }
- else {
- for (i = 0; i < num_points; i++, p++) {
- ZnTransformPoint(result_t, p, &xp);
- /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/
- entries[0] = Tcl_NewDoubleObj(xp.x);
- entries[1] = Tcl_NewDoubleObj(xp.y);
- if (controls && controls[i]) {
- c[0] = controls[i];
- entries[2] = Tcl_NewStringObj(c, -1);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries));
- }
- else {
- Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
- }
- }
- }
- }
- break;
- /*
- * translate
- */
- case ZN_W_TRANSLATE:
- {
- ZnBool abs = False;
-
- if ((argc != 5) && (argc != 6)) {
- Tcl_WrongNumArgs(interp, 1, args, "translate tagOrIdorTransform xAmount yAmount ?abs?");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
- goto error;
- }
- p.x = d;
- if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
- goto error;
- }
- p.y = d;
- if (argc == 6) {
- if (Tcl_GetBooleanFromObj(interp, args[5], &abs) == TCL_ERROR) {
- goto error;
- }
- }
-
- if (t) {
- ZnTranslate(t, p.x, p.y, abs);
- }
- else {
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item =ZnTagSearchNext(search_var)) {
- ZnITEM.TranslateItem(item, p.x, p.y, abs);
- }
- }
- }
- break;
- /*
- * treset
- */
- case ZN_W_TRESET:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "treset tagOrIdOrTransform");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- }
-
- if (t) {
- ZnTransfoSetIdentity(t);
- }
- else {
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.ResetTransfo(item);
- }
- }
- }
- break;
- /*
- * trestore
- */
- case ZN_W_TRESTORE:
- {
- if (argc != 4) {
- Tcl_WrongNumArgs(interp, 1, args, "trestore tagOrId tName");
- goto error;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[argc-1]));
- if (entry == NULL) {
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-1]),
- "\" must be a transform name", (char *) NULL);
- goto error;
- }
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- ZnITEM.SetTransfo(item, t);
- }
- }
- break;
- /*
- * tsave
- */
- case ZN_W_TSAVE:
- {
- int is_ident, new, invert=0;
- ZnTransfo *inv, ident;
- char *from;
-
- if ((argc != 3) && (argc != 4) && (argc != 5)) {
- Tcl_WrongNumArgs(interp, 1, args, "tsave ?tagOrIdOrTransform? tName ?invert?");
- goto error;
- }
- if (argc == 3) {
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- l = Tcl_NewBooleanObj(entry != NULL);
- Tcl_SetObjResult(interp, l);
- goto done;
- }
- from = Tcl_GetString(args[2]);
- is_ident = strcmp(from, "identity") == 0;
- if (is_ident) {
- t = &ident;
- ZnTransfoSetIdentity(t);
- }
- else {
- entry = Tcl_FindHashEntry(wi->t_table, from);
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- }
- else {
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- goto error;
- }
- t = item->transfo;
- }
- }
- if (argc == 5) {
- if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) {
- goto error;
- }
- argc--;
- }
- entry = Tcl_CreateHashEntry(wi->t_table, Tcl_GetString(args[argc-1]), &new);
- if (!new) {
- ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry));
- }
- if (invert && !is_ident) {
- inv = ZnTransfoNew();
- ZnTransfoInvert(t, inv);
- Tcl_SetHashValue(entry, inv);
- }
- else {
- Tcl_SetHashValue(entry, ZnTransfoDuplicate(t));
- }
- }
- break;
- /*
- * tset
- */
- case ZN_W_TSET:
- {
- ZnTransfo new;
-
- if (argc != 9) {
- Tcl_WrongNumArgs(interp, 1, args,
- "tset tagOrIdorTransform m00 m01 m10 m11 m20 m21");
- goto error;
- }
-
- for (i = 0; i < 6; i++) {
- if (Tcl_GetDoubleFromObj(interp, args[3+i], &d) == TCL_ERROR) {
- goto error;
- }
- new._[i/2][i%2] = (float) d;
- }
- entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
- if (entry != NULL) {
- t = (ZnTransfo *) Tcl_GetHashValue(entry);
- *t = new;
- }
- else {
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
- "\" must be either a tag, ",
- "an id or a transform name", (char *) NULL);
- goto error;
- }
- ZnITEM.SetTransfo(item, &new);
- }
- break;
- }
- /*
- * type
- */
- case ZN_W_TYPE:
- {
- if (argc != 3) {
- Tcl_WrongNumArgs(interp, 1, args, "type tagOrId");
- goto error;
- }
- result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
- if (result == TCL_ERROR) {
- goto error;
- }
- if (item != ZN_NO_ITEM) {
- l = Tcl_NewStringObj(item->class->name, -1);
- Tcl_SetObjResult(interp, l);
- }
- }
- break;
- /*
- * vertexat
- */
- case ZN_W_VERTEX_AT:
- {
- int contour, vertex, o_vertex;
-
- if (argc != 5) {
- Tcl_WrongNumArgs(interp, 1, args, " vertexat tagOrId x y");
- goto error;
- }
- if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
- goto error;
- }
- for (item = ZnTagSearchFirst(search_var);
- item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
- if (item->class->PickVertex != NULL) {
- break;
- }
- }
- if (item == ZN_NO_ITEM) {
- Tcl_AppendResult(interp, "can't find a suitable item \"",
- Tcl_GetString(args[2]), "\"", NULL);
- goto error;
- }
- if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
- goto error;
- }
- p.x = d;
- if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
- goto error;
- }
- p.y = d;
- item->class->PickVertex(item, &p, &contour, &vertex, &o_vertex);
- l = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(contour));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(vertex));
- Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(o_vertex));
- break;
- }
-
- /* xview */
- case ZN_W_XVIEW:
- {
- int count, type;
- ZnReal new_x=0.0, fraction;
-
- if (argc == 2) {
-#ifdef PTK
- ZnReal first, last;
- ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win),
- wi->scroll_xo, wi->scroll_xc, &first, &last);
- Tcl_DoubleResults(interp, 2, 0, first, last);
-#else
- Tcl_SetObjResult(interp,
- ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win),
- wi->scroll_xo, wi->scroll_xc));
-#endif
- }
- else {
- type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count);
- switch (type) {
- case TK_SCROLL_ERROR:
- result = TCL_ERROR;
- goto done;
- case TK_SCROLL_MOVETO:
- new_x = (wi->scroll_xo + (int) (fraction * (wi->scroll_xc - wi->scroll_xo) + 0.5));
- break;
- case TK_SCROLL_PAGES:
- new_x = (int) (wi->origin.x + count * 0.9 * Tk_Width(wi->win));
- break;
- case TK_SCROLL_UNITS:
- if (wi->x_scroll_incr > 0) {
- new_x = wi->origin.x + count * wi->x_scroll_incr;
- }
- else {
- new_x = (int) (wi->origin.x + count * 0.1 * Tk_Width(wi->win));
- }
- break;
- }
- SetOrigin(wi, new_x, wi->origin.y);
- }
- break;
- }
-
- /*yview */
- case ZN_W_YVIEW:
- {
- int count, type;
- ZnReal new_y = 0.0, fraction;
-
- if (argc == 2) {
-#ifdef PTK
- ZnReal first, last;
- ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win),
- wi->scroll_yo, wi->scroll_yc, &first, &last);
- Tcl_DoubleResults(interp, 2, 0, first, last);
-#else
- Tcl_SetObjResult(interp,
- ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win),
- wi->scroll_yo, wi->scroll_yc));
-#endif
- }
- else {
- type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count);
- switch (type) {
- case TK_SCROLL_ERROR:
- result = TCL_ERROR;
- goto done;
- case TK_SCROLL_MOVETO:
- new_y = (wi->scroll_yo + (int) (fraction * (wi->scroll_yc - wi->scroll_yo) + 0.5));
- break;
- case TK_SCROLL_PAGES:
- new_y = (int) (wi->origin.y + count * 0.9 * Tk_Height(wi->win));
- break;
- case TK_SCROLL_UNITS:
- if (wi->y_scroll_incr > 0) {
- new_y = wi->origin.y + count * wi->y_scroll_incr;
- }
- else {
- new_y = (int) (wi->origin.y + count * 0.1 * Tk_Height(wi->win));
- }
- break;
- }
- SetOrigin(wi, wi->origin.x, new_y);
- }
- break;
- }
- }
-
- done:
- ZnTagSearchDestroy(search_var);
- Tcl_Release((ClientData) wi);
- return result;
-
- error:
- result = TCL_ERROR;
- goto done;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Configure --
- *
- * This procedure is called to process an args/argc list in
- * conjunction with the Tk option database to configure (or
- * reconfigure) a Zinc widget.
- *
- * Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
- *
- * Side effects:
- * Configuration information, such as colors, border width,
- * etc. get set for the widget; old resources get freed,
- * if there were any.
- *
- *----------------------------------------------------------------------
- */
-#ifdef PTK_800
-static int
-Configure(Tcl_Interp *interp,/* Used for error reporting. */
- ZnWInfo *wi, /* Information about widget. */
- int argc, /* Number of valid entries in args. */
- Tcl_Obj *CONST args[], /* Arguments. */
- int flags) /* Flags to pass to Tk_ConfigureWidget. */
-{
-#define CONFIG_PROBE(offset) (ISSET(config_specs[offset].specFlags, \
- TK_CONFIG_OPTION_SPECIFIED))
- ZnBool init;
- int render;
-
- init = wi->fore_color == NULL;
- render = wi->render;
- if (Tk_ConfigureWidget(interp, wi->win, config_specs, argc,
-#ifdef PTK
- (Tcl_Obj **) args, (char *) wi, flags) != TCL_OK)
-#else
- (CONST char **) args, (char *) wi, flags|TK_CONFIG_OBJS) != TCL_OK)
-#endif
- {
- return TCL_ERROR;
- }
- if (!init) {
- if (wi->render != render) {
- ZnWarning("It is not possible to change the -render option after widget creation.\n");
- }
- wi->render = render;
- }
- /*
- * Reset the render mode if GL is not available. It'll be too late
- * to do this after images or fonts have been allocated.
- */
- if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) {
- fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n");
- wi->render = 0;
- }
-
-#ifdef GL
- if (CONFIG_PROBE(FONT_SPEC) || !wi->font_tfi) {
- if (wi->font_tfi) {
- ZnFreeTexFont(wi->font_tfi);
- }
- wi->font_tfi = ZnGetTexFont(wi, wi->font);
- }
-#ifdef ATC
- if (CONFIG_PROBE(MAP_TEXT_FONT_SPEC) || !wi->map_font_tfi) {
- if (wi->map_font_tfi) {
- ZnFreeTexFont(wi->map_font_tfi);
- }
- wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
- }
-#endif
-#endif
-
- /*
- * Maintain the pick aperture within meaningful bounds.
- */
- if (wi->pick_aperture < 0) {
- wi->pick_aperture = 0;
- }
- if (CONFIG_PROBE(BACK_COLOR_SPEC) || !wi->relief_grad) {
- XColor *color;
- unsigned short alpha;
-
- Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0));
- if (wi->relief_grad) {
- ZnFreeGradient(wi->relief_grad);
- wi->relief_grad = NULL;
- }
- if (wi->relief != ZN_RELIEF_FLAT) {
- color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
- wi->relief_grad = ZnGetReliefGradient(interp, wi->win,
- Tk_NameOfColor(color), alpha);
- }
- }
- if (CONFIG_PROBE(BACK_COLOR_SPEC) || CONFIG_PROBE(LIGHT_ANGLE_SPEC)) {
- ZnDamageAll(wi);
- }
- if (CONFIG_PROBE(RELIEF_SPEC)) {
- ZnNeedRedisplay(wi);
- }
-
- wi->inset = wi->border_width + wi->highlight_width;
- if (CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
- CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC)) {
- ZnDamageAll(wi);
- }
-#ifdef ATC
- if (CONFIG_PROBE(SPEED_VECTOR_LENGTH_SPEC) ||
- CONFIG_PROBE(VISIBLE_HISTORY_SIZE_SPEC) ||
- CONFIG_PROBE(MANAGED_HISTORY_SIZE_SPEC)) {
- ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
- }
- if (CONFIG_PROBE(MAP_DISTANCE_SYMBOL_SPEC)) {
- ZnITEM.InvalidateItems(wi->top_group, ZnMap);
- }
- if (CONFIG_PROBE(TRACK_SYMBOL_SPEC)) {
- ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
- ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint);
- }
-#endif
-
- /*
- * Request the new geometry.
- */
- if (CONFIG_PROBE(WIDTH_SPEC) || CONFIG_PROBE(HEIGHT_SPEC) ||
- CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
- CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC) || ISCLEAR(wi->flags, ZN_REALIZED)) {
- Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height);
- }
-
- if (CONFIG_PROBE(TILE_SPEC)) {
- ZnDamageAll(wi);
- }
-
- /*
- * Update the registration with the overlap manager.
- */
-#ifdef ATC
- if (CONFIG_PROBE(OVERLAP_MANAGER_SPEC)) {
- Tcl_HashEntry *entry;
- ZnItem grp;
-
- if (wi->om_group != ZN_NO_ITEM) {
- OmUnregister((void *) wi);
- wi->om_group = ZN_NO_ITEM;
- }
- if (wi->om_group_id != 0) {
- entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id);
- if (entry != NULL) {
- grp = (ZnItem) Tcl_GetHashValue(entry);
- if (grp->class == ZnGroup) {
- OmRegister((void *) wi, ZnSendTrackToOm,
- ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
- wi->om_group = grp;
- }
- }
- }
- }
-#endif
-
- if (CONFIG_PROBE(INSERT_WIDTH_SPEC) && wi->focus_item) {
- ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
- }
- /*
- * Update the blinking cursor timing if on/off time has changed.
- */
- if (ISSET(wi->flags, ZN_GOT_FOCUS) &&
- (CONFIG_PROBE(INSERT_ON_TIME_SPEC) ||
- CONFIG_PROBE(INSERT_OFF_TIME_SPEC))) {
- Focus(wi, True);
- }
-
- if (CONFIG_PROBE(SCROLL_REGION_SPEC)) {
- /*
- * Compute the scroll region
- */
- wi->scroll_xo = wi->scroll_yo = 0;
- wi->scroll_xc = wi->scroll_yc = 0;
- if (wi->region != NULL) {
- int argc2;
-#ifdef PTK
- Arg *args2;
-#else
- CONST char **args2;
-#endif
-
-#ifdef PTK
- if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK)
-#else
- if (Tcl_SplitList(interp, wi->region, &argc2, &args2) != TCL_OK)
-#endif
- {
- return TCL_ERROR;
- }
- if (argc2 != 4) {
- Tcl_AppendResult(interp, "bad scrollRegion \"", wi->region, "\"", (char *) NULL);
- badRegion:
-#ifndef PTK
- ZnFree(wi->region);
- ZnFree(args2);
-#endif
- wi->region = NULL;
- return TCL_ERROR;
- }
-#ifdef PTK
-#ifdef PTK_800
- if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK))
-#else
- if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK))
-#endif
-#else
- if ((Tk_GetPixels(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK))
-#endif
- {
- goto badRegion;
- }
- }
- }
-
- if (CONFIG_PROBE(SCROLL_REGION_SPEC) ||
- CONFIG_PROBE(CONFINE_SPEC)) {
- SetOrigin(wi, wi->origin.x, wi->origin.y);
- SET(wi->flags, ZN_UPDATE_SCROLLBARS);
- }
-
- if (CONFIG_PROBE(FOLLOW_POINTER_SPEC)) {
- if (wi->follow_pointer) {
- /* Flag has just been turned on, process
- * the last known positional event to update
- * the item under pointer.
- */
- if (wi->pick_event.type == ButtonPress ||
- wi->pick_event.type == ButtonRelease ||
- wi->pick_event.type == MotionNotify ||
- wi->pick_event.type == EnterNotify ||
- wi->pick_event.type == LeaveNotify) {
- Tcl_Preserve((ClientData) wi);
- CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
- PickCurrentItem(wi, &wi->pick_event);
- Tcl_Release((ClientData) wi);
- }
- }
- }
-
- return TCL_OK;
-}
-#else
-static void
-TileUpdate(void *client_data)
-{
- ZnWInfo *wi = (ZnWInfo*) client_data;
-
- ZnDamageAll(wi);
-}
-
-static int
-Configure(Tcl_Interp *interp,/* Used for error reporting. */
- ZnWInfo *wi, /* Information about widget. */
- int argc, /* Number of valid entries in args. */
- Tcl_Obj *CONST args[]) /* Arguments. */
-{
- ZnBool init;
- int render, mask, error;
- Tk_SavedOptions saved_options;
- Tcl_Obj *error_result = NULL;
-
- render = wi->render;
- init = render < 0;
-
- for (error = 0; error <= 1; error++) {
- if (!error) {
- if (Tk_SetOptions(interp, (char *) wi, wi->opt_table, argc, args,
- wi->win, &saved_options, &mask) != TCL_OK) {
- continue;
- }
- }
- else {
- /* Save the error value for later report */
- error_result = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(error_result);
- Tk_RestoreSavedOptions(&saved_options);
- }
-
- if (!init) {
- if (render != wi->render) {
- ZnWarning("It is not possible to change the -render option after widget creation.\n");
- wi->render = render;
- }
- }
- else if (wi->render < 0) {
- wi->render = 0;
- }
- /*
- * Reset the render mode if GL is not available. It'll be too late
- * to do this after images or fonts have been allocated.
- */
- else if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) {
- fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n");
- wi->render = 0;
- }
-
- if ((mask & CONFIG_SCROLL_REGION) || init) {
- /*
- * Compute the scroll region
- */
- wi->scroll_xo = wi->scroll_yo = 0;
- wi->scroll_xc = wi->scroll_yc = 0;
- if (wi->region != NULL) {
- int argc2;
- Tcl_Obj **args2;
-
- if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK) {
- badRegion:
- Tcl_AppendResult(interp, "bad scrollRegion \"",
- Tcl_GetString(wi->region), "\"", (char *) NULL);
- continue;
- }
- if (argc2 != 4) {
- goto badRegion;
- }
-#ifdef PTK_800
- if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) ||
- (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK))
-#else
- if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) ||
- (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK))
-#endif
- {
- goto badRegion;
- }
- }
- }
-
- if ((mask & CONFIG_SET_ORIGIN) || init) {
- SetOrigin(wi, wi->origin.x, wi->origin.y);
- SET(wi->flags, ZN_UPDATE_SCROLLBARS);
- }
-
-#ifdef GL
- if ((mask & CONFIG_FONT) || !wi->font_tfi) {
- if (wi->font_tfi) {
- ZnFreeTexFont(wi->font_tfi);
- }
- wi->font_tfi = ZnGetTexFont(wi, wi->font);
- }
-#ifdef ATC
- if ((mask & CONFIG_MAP_FONT) || !wi->map_font_tfi) {
- if (wi->map_font_tfi) {
- ZnFreeTexFont(wi->map_font_tfi);
- }
- wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
- }
-#endif
-#endif
-
- if ((mask & CONFIG_TILE) || init) {
- char *tile_name;
- if (wi->tile) {
- ZnFreeImage(wi->tile, TileUpdate, wi);
- }
- if (!wi->tile_obj || !*(tile_name = Tcl_GetString(wi->tile_obj))) {
- wi->tile = ZnUnspecifiedImage;
- }
- else {
- wi->tile = ZnGetImage(wi, tile_name, TileUpdate, wi);
- if (wi->tile == ZnUnspecifiedImage) {
- Tcl_AppendResult(interp, "Incorrect tile \"", tile_name, "\"", (char *) NULL);
- continue;
- }
- }
- }
-
-#ifdef ATC
- if ((mask & CONFIG_MAP_SYMBOL) || init) {
- if (wi->map_distance_symbol) {
- ZnFreeImage(wi->map_distance_symbol, NULL, NULL);
- }
- wi->map_distance_symbol = ZnGetImage(wi, Tcl_GetString(wi->map_symbol_obj), NULL, NULL);
- if ((wi->map_distance_symbol == ZnUnspecifiedImage) ||
- ! ZnImageIsBitmap(wi->map_distance_symbol)) {
- Tcl_AppendResult(interp, "Incorrect bitmap \"",
- Tcl_GetString(wi->map_symbol_obj), "\"", (char *) NULL);
- continue;
- }
- }
-
- if ((mask & CONFIG_TRACK_SYMBOL) || init) {
- if (wi->track_symbol) {
- ZnFreeImage(wi->track_symbol, NULL, NULL);
- }
- wi->track_symbol = ZnGetImage(wi, Tcl_GetString(wi->track_symbol_obj), NULL, NULL);
- if ((wi->track_symbol == ZnUnspecifiedImage) ||
- ! ZnImageIsBitmap(wi->track_symbol)) {
- Tcl_AppendResult(interp, "Incorrect bitmap \"",
- Tcl_GetString(wi->track_symbol_obj), "\"", (char *) NULL);
- continue;
-
- }
- }
-#endif
-
- /*
- * Maintain the pick aperture within meaningful bounds.
- */
- if (wi->pick_aperture < 0) {
- wi->pick_aperture = 0;
- }
-
- if ((mask & CONFIG_BACK_COLOR) || !wi->relief_grad) {
- XColor *color;
- unsigned short alpha;
-
- Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0));
- if (wi->relief_grad) {
- ZnFreeGradient(wi->relief_grad);
- wi->relief_grad = NULL;
- }
- if (wi->relief != ZN_RELIEF_FLAT) {
- color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
- wi->relief_grad = ZnGetReliefGradient(interp, wi->win,
- Tk_NameOfColor(color), alpha);
- }
- }
- if (mask & CONFIG_DAMAGE_ALL) {
- ZnDamageAll(wi);
- }
- if ((mask & CONFIG_REDISPLAY) || init) {
- ZnNeedRedisplay(wi);
- }
-
- wi->inset = wi->border_width + wi->highlight_width;
-
-#ifdef ATC
- if (mask & CONFIG_INVALIDATE_TRACKS) {
- ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
- }
- if (mask & CONFIG_INVALIDATE_MAPS) {
- ZnITEM.InvalidateItems(wi->top_group, ZnMap);
- }
- if (mask & CONFIG_INVALIDATE_WPS) {
- ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint);
- }
-#endif
-
- /*
- * Request the new geometry.
- */
- if ((mask & CONFIG_REQUEST_GEOM) || init) {
- Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height);
- }
-
- /*
- * Update the registration with the overlap manager.
- */
-#ifdef ATC
- if (mask & CONFIG_OM) {
- Tcl_HashEntry *entry;
- ZnItem grp;
-
- if (wi->om_group != ZN_NO_ITEM) {
- OmUnregister((void *) wi);
- wi->om_group = ZN_NO_ITEM;
- }
- if (wi->om_group_id != 0) {
- entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id);
- if (entry != NULL) {
- grp = (ZnItem) Tcl_GetHashValue(entry);
- if (grp->class == ZnGroup) {
- OmRegister((void *) wi, ZnSendTrackToOm,
- ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
- wi->om_group = grp;
- }
- }
- }
- }
-#endif
-
- if ((mask & CONFIG_FOCUS_ITEM) && wi->focus_item) {
- ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
- }
- /*
- * Update the blinking cursor timing if on/off time has changed.
- */
- if (ISSET(wi->flags, ZN_GOT_FOCUS) && (mask & CONFIG_FOCUS)) {
- Focus(wi, True);
- }
-
- if (mask & CONFIG_FOLLOW_POINTER) {
- if (wi->follow_pointer) {
- /* Flag has just been turned on, process
- * the last known positional event to update
- * the item under pointer.
- */
- if (wi->pick_event.type == ButtonPress ||
- wi->pick_event.type == ButtonRelease ||
- wi->pick_event.type == MotionNotify ||
- wi->pick_event.type == EnterNotify ||
- wi->pick_event.type == LeaveNotify) {
- Tcl_Preserve((ClientData) wi);
- CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
- PickCurrentItem(wi, &wi->pick_event);
- Tcl_Release((ClientData) wi);
- }
- }
- }
- break;
- }
-
- if (error) {
- Tcl_SetObjResult(interp, error_result);
- Tcl_DecrRefCount(error_result);
- return TCL_ERROR;
- }
- else {
- Tk_FreeSavedOptions(&saved_options);
- return TCL_OK;
- }
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * Focus --
- *
- * This procedure is called whenever a zinc gets or loses the
- * input focus. It's also called whenever the window is
- * reconfigured while it has the focus.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The cursor gets turned on or off.
- *
- *----------------------------------------------------------------------
- */
-static void
-Blink(ClientData client_data)
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
-
- if (ISCLEAR(wi->flags, ZN_GOT_FOCUS) || (wi->insert_off_time == 0)) {
- return;
- }
- if (wi->text_info.cursor_on) {
- wi->text_info.cursor_on = 0;
- wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time,
- Blink, client_data);
- }
- else {
- wi->text_info.cursor_on = 1;
- wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_on_time,
- Blink, client_data);
- }
- if ((wi->focus_item != ZN_NO_ITEM) &&
- (wi->focus_item->class->Cursor != NULL)) {
- ZnITEM.Invalidate(wi->focus_item, ZN_DRAW_FLAG);
- }
-}
-
-static void
-Focus(ZnWInfo *wi,
- ZnBool got_focus)
-{
- Tcl_DeleteTimerHandler(wi->blink_handler);
- if (got_focus) {
- SET(wi->flags, ZN_GOT_FOCUS);
- wi->text_info.cursor_on = 1;
- if (wi->insert_off_time != 0) {
- wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time,
- Blink, (ClientData) wi);
- }
- }
- else {
- CLEAR(wi->flags, ZN_GOT_FOCUS);
- wi->text_info.cursor_on = 0;
- wi->blink_handler = (Tcl_TimerToken) NULL;
- }
- if ((wi->focus_item != ZN_NO_ITEM) &&
- (wi->focus_item->class->Cursor != NULL)){
- ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
- }
- /*printf("focus %s\n", got_focus ? "in" : "out");*/
- if (wi->highlight_width > 0) {
- ZnNeedRedisplay(wi);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Event --
- *
- * This procedure is invoked by the Tk dispatcher for various
- * events on Zincs.
- *
- * Results:
- * None.
- *
- * Side effects:
- * When the window gets deleted, internal structures get
- * cleaned up. When it gets exposed, it is redisplayed.
- *
- *----------------------------------------------------------------------
- */
-static void
-TopEvent(ClientData client_data, /* Information about widget. */
- XEvent *event)
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- if (event->type == ConfigureNotify) {
- /*printf("Window moved\n");*/
- SET(wi->flags, ZN_CONFIGURE_EVENT);
- }
-}
-
-static void
-Event(ClientData client_data, /* Information about widget. */
- XEvent *event) /* Information about event. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- XGCValues values;
- ZnBBox bbox;
-
- /*printf("=============== DEBUT %s %d EVENT ==================\n",
- event->type == MapNotify ? "MAP":
- event->type == Expose? "EXPOSE" :
- event->type == ConfigureNotify ? "CONFIGURE" :
- event->type == VisibilityNotify ? "VISIBILITY" :
- event->type == DestroyNotify ? "DESTROY" :
- "??", event->type);*/
- if (event->type == MapNotify) {
- SET(wi->flags, ZN_CONFIGURE_EVENT);
- if (!wi->gc) {
- SET(wi->flags, ZN_REALIZED);
-#ifdef GL
- InitRendering2(wi);
-#endif
-
- /*
- * Get the work GC and suppress GraphicExpose
- * and NoExpose events reception.
- */
- wi->gc = XCreateGC(wi->dpy, Tk_WindowId(wi->win), 0, NULL);
- values.graphics_exposures = False;
- XChangeGC(wi->dpy, wi->gc, GCGraphicsExposures, &values);
-
- /*
- * Set the real top window above us.
- */
- {
- Window parent, root, *children=NULL;
- Tk_Window top_level;
- int num_children, success;
-
- top_level = wi->win;
- while (!Tk_IsTopLevel(top_level)) {
- top_level = Tk_Parent(top_level);
- }
- success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent,
- &children, &num_children);
- if (!success || (root == parent)) {
- wi->real_top = Tk_WindowId(top_level);
- }
- else {
- wi->real_top = parent;
- }
- /*
- * Needed under glx to suspend update with scissors after
- * a move to synchronise the two buffers. Fix a refresh
- * bug when the window is partially clipped by the display
- * border. Can be usefull under Windows too.
- */
- Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi);
- if (children && success) {
- XFree(children);
- }
- }
- }
- ZnNeedRedisplay(wi);
- }
- else if (event->type == Expose) {
- ZnDim width, height;
-
- SET(wi->flags, ZN_CONFIGURE_EVENT);
-
- bbox.orig.x = (((XExposeEvent*) event)->x);
- bbox.orig.y = (((XExposeEvent*) event)->y);
- width = ((XExposeEvent*) event)->width;
- height = ((XExposeEvent*) event)->height;
- if (bbox.orig.x < 0) {
- width += bbox.orig.x;
- bbox.orig.x = 0;
- }
- if (bbox.orig.y < 0) {
- height += bbox.orig.y;
- bbox.orig.y = 0;
- }
- bbox.corner.x = MIN(wi->width, bbox.orig.x + width);
- bbox.corner.y = MIN(wi->height, bbox.orig.y + height);
-
- /*printf("expose %d %d %d %d\n",
- ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y,
- ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);*/
- /*
- * Add the exposed area to the expose region and
- * schedule an asynchronous redisplay of the window
- * if we are done adding exposed parts.
- */
- ZnAddBBoxToBBox(&wi->exposed_area, &bbox);
- if (/*(((XExposeEvent*) event)->count == 0) &&*/
- !ZnIsEmptyBBox(&wi->exposed_area)) {
- ZnNeedRedisplay(wi);
- }
- }
- /*
- * Resize the double buffer pixmap and prepare to redisplay
- * the whole scene. The transform parameters are not
- * modified as a result of the resize. If the application
- * need such change, it can bind a handler on <Configure>.
- */
- else if (event->type == ConfigureNotify) {
- int int_width, int_height;
-
- SET(wi->flags, ZN_CONFIGURE_EVENT);
-
- int_width = Tk_Width(wi->win);
- int_height = Tk_Height(wi->win);
-
- if ((wi->width != int_width) || (wi->height != int_height)) {
- bbox.orig.x = bbox.orig.y = 0;
- bbox.corner.x = MAX(wi->width, int_width);
- bbox.corner.y = MAX(wi->height, int_height);
- wi->opt_width = wi->width = int_width;
- wi->opt_height = wi->height = int_height;
-
- ZnResetTransformStack(wi);
-
- SET(wi->flags, ZN_UPDATE_SCROLLBARS);
- /*
- * The call below is needed in order to recenter the view if
- * it's confined and the scroll region is smaller than the
- * window.
- */
- SetOrigin(wi, wi->origin.x, wi->origin.y);
-
- ZnDamage(wi, &bbox);
- ZnITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG);
-
- /*
- * Reallocate the double buffer pixmap/image.
- */
- if (!wi->render) {
- /*printf("reallocating double buffer\n");*/
- if (wi->draw_buffer) {
- Tk_FreePixmap(wi->dpy, wi->draw_buffer);
- }
- wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
- int_width, int_height,
- DefaultDepthOfScreen(wi->screen));
- }
- }
- else {
- /*
- * In case of a window reconfiguration following a change
- * of border size, set the exposed area to force a copy
- * of the back buffer to the screen.
- */
- bbox.orig.x = bbox.orig.y = 0;
- bbox.corner.x = Tk_Width(wi->win);
- bbox.corner.y = Tk_Height(wi->win);
- ZnAddBBoxToBBox(&wi->exposed_area, &bbox);
- }
- ZnNeedRedisplay(wi);
- }
- /*
- * Take into account that the window has been actually cancelled.
- * Remove the corresponding widget command, unregister any
- * pending Redisplay and eventually free the widget's memory.
- */
- else if (event->type == DestroyNotify) {
- if (wi->win != NULL) {
- wi->win = NULL;
- CLEAR(wi->flags, ZN_REALIZED);
-#ifdef PTK
- Lang_DeleteWidget(wi->interp, wi->cmd);
-#else
- Tcl_DeleteCommandFromToken(wi->interp, wi->cmd);
-#endif
- }
- if (ISSET(wi->flags, ZN_UPDATE_PENDING)) {
- Tcl_CancelIdleCall(Redisplay, (ClientData) wi);
- }
- Tcl_EventuallyFree((ClientData) wi, Destroy);
- }
- else if (event->type == FocusIn) {
- if (event->xfocus.detail != NotifyInferior) {
- Focus(wi, True);
- }
- }
- else if (event->type == FocusOut) {
- if (event->xfocus.detail != NotifyInferior) {
- Focus(wi, False);
- }
- }
-
- /*printf("=============== FIN %s EVENT ==================\n",
- event->type == MapNotify ? "MAP":
- event->type == Expose? "EXPOSE" :
- event->type == ConfigureNotify ? "CONFIGURE" :
- event->type == VisibilityNotify ? "VISIBILITY" :
- event->type == DestroyNotify ? "DESTROY" :
- "??");*/
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DoEvent --
- *
- * Trigger the bindings associated with an event.
- *
- *----------------------------------------------------------------------
- */
-static void
-DoEvent(ZnWInfo *wi,
- XEvent *event,
- ZnBool bind_item, /* Controls whether item bindings will trigger.
- * Useful for Enter/Leaves between fields */
- ZnBool bind_part) /* Controls whether part bindings will trigger.
- * Useful for precise control of Enter/Leaves
- * during grabs. */
-{
-#define NUM_STATIC 4
- ClientData items[NUM_STATIC], *its;
- static unsigned int worksize = 128, len, num, num_tags;
- static char *workspace = NULL;
- unsigned int i, ptr;
- ClientData *tag_list = NULL;
- ZnItem item;
- int part;
-
-#define BIND_ITEM(test) \
- if (bind_item && (test)) { \
- its[ptr] = (ClientData) all_uid; \
- ptr++; \
- for (i = 0; i < num_tags; i++) { \
- its[ptr] = tag_list[i]; \
- ptr++; \
- } \
- its[ptr] = (ClientData) item; \
- ptr++; \
- }
-
- if (wi->binding_table == NULL) {
- //printf("no bindings\n");
- return;
- }
-
- item = wi->current_item;
- part = wi->current_part;
- if ((event->type == KeyPress) || (event->type == KeyRelease)) {
- item = wi->focus_item;
- part = wi->focus_field;
- }
-
- if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, ZN_NO_PART)) {
- return;
- }
-
- /*
- * Set up an array with all the relevant elements for processing
- * this event. The relevant elements are (a) the event's item/part
- * tag (i.e item:part), (b) the event's item, (c) the tags
- * associated with the event's item, and (d) the tag 'all'.
- */
- num = 0;
- num_tags = 0;
- its = items;
- bind_part = (bind_part &&
- (part != ZN_NO_PART) &&
- item->class->IsSensitive(item, part) &&
- ((wi->current_item != ZN_NO_ITEM) &&
- (wi->current_item->class->num_parts ||
- wi->current_item->class->GetFieldSet)));
-
- //printf("type=%s, current=%d, new=%d --> %s, currentp %d, newp %d\n",
- // event->type==EnterNotify?"<Enter>":
- // event->type==LeaveNotify?"<Leave>":
- // event->type==MotionNotify?"<Motion>":"other",
- // wi->current_item?wi->current_item->id:0,
- // wi->new_item?wi->new_item->id:0,
- // bind_item?"bind":"nobind",
- // wi->current_part, wi->new_part);
- if (bind_item) {
- num += 2;
- }
- if (bind_part) {
- num++;
- if (!workspace) {
- workspace = ZnMalloc(worksize);
- }
- }
- if (item->tags) {
- num_tags = ZnListSize(item->tags);
- if (bind_item) {
- num += num_tags;
- }
- if (bind_part) {
- num += num_tags;
- }
- tag_list = (ClientData *) ZnListArray(item->tags);
- if (num > NUM_STATIC) {
- its = (ClientData *) ZnMalloc(num*sizeof(ClientData));
- }
- }
-
- ptr = 0;
-
- BIND_ITEM(event->type != LeaveNotify);
-
- if (bind_part) {
- /*
- * Add here a binding for each tag suffixed by :part
- */
- for (i = 0; i < num_tags; i++) {
- len = strlen(tag_list[i])+ TCL_INTEGER_SPACE;
- if (worksize < len) {
- worksize = len + 10;
- workspace = ZnRealloc(workspace, len);
- }
- sprintf(workspace, "%s:%d", (char *) tag_list[i], part);
- its[ptr] = (ClientData) Tk_GetUid(workspace);
- ptr++;
- }
- /*
- * Add here a binding for id:part
- */
- its[ptr] = EncodeItemPart(item, part);
- ptr++;
- }
-
- BIND_ITEM(event->type == LeaveNotify);
-
- /*
- * Invoke the binding system.
- */
- if (wi->win != NULL) {
- Tk_BindEvent(wi->binding_table, event, wi->win, (int) num, its);
- }
- if (its != items) {
- ZnFree(its);
- }
-
-#undef BIND_ITEM
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * PickCurrentItem --
- *
- * Finds the topmost item/field that contains the pointer and mark
- * it has the current item. Generates Enter/leave events on the
- * old and new current items/fields has necessary.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The current item/field may change. If it does,
- * then the commands associated with item entry and exit
- * could do just about anything. A binding script could
- * delete the widget, so callers should protect themselves
- * with Tcl_Preserve and Tcl_Release.
- *
- * Note:
- * See the Bind function's note.
- *
- *----------------------------------------------------------------------
- */
-static void
-PickCurrentItem(ZnWInfo *wi,
- XEvent *event)
-{
- int button_down;
- ZnBool enter_item;
- ZnBool grab_release = False;
-
- /*printf("PickCurrent current=%d, new=%d\n",
- wi->current_item?wi->current_item->id:0,
- wi->new_item?wi->new_item->id:0);*/
- /*
- * Check whether or not a button is down. If so, we'll log entry
- * and exit into and out of the current item, but not entry into
- * any other item. This implements a form of grabbing equivalent
- * to what the X server does for windows.
- */
- button_down = wi->state
- & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
- if (!button_down) {
- grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM);
- CLEAR(wi->flags, ZN_GRABBED_ITEM);
- CLEAR(wi->flags, ZN_GRABBED_PART);
- }
-
- /*
- * Save information about this event in the widget. The saved event
- * is used for two purposes:
- *
- * 1. Event bindings: if the current item changes, fake events are
- * generated to allow item-enter and item-leave bindings to trigger.
- * 2. Reselection: if the current item gets deleted, can use the
- * saved event to find a new current item.
- * Translate MotionNotify events into EnterNotify events, since that's
- * what gets reported to item handlers.
- */
- if (event != &wi->pick_event) {
- if ((event->type == MotionNotify) || (event->type == ButtonRelease)) {
- wi->pick_event.xcrossing.type = EnterNotify;
- wi->pick_event.xcrossing.serial = event->xmotion.serial;
- wi->pick_event.xcrossing.send_event = event->xmotion.send_event;
- wi->pick_event.xcrossing.display = event->xmotion.display;
- wi->pick_event.xcrossing.window = event->xmotion.window;
- wi->pick_event.xcrossing.root = event->xmotion.root;
- wi->pick_event.xcrossing.subwindow = None;
- wi->pick_event.xcrossing.time = event->xmotion.time;
- wi->pick_event.xcrossing.x = event->xmotion.x;
- wi->pick_event.xcrossing.y = event->xmotion.y;
- wi->pick_event.xcrossing.x_root = event->xmotion.x_root;
- wi->pick_event.xcrossing.y_root = event->xmotion.y_root;
- wi->pick_event.xcrossing.mode = NotifyNormal;
- wi->pick_event.xcrossing.detail = NotifyNonlinear;
- wi->pick_event.xcrossing.same_screen = event->xmotion.same_screen;
- wi->pick_event.xcrossing.focus = False;
- wi->pick_event.xcrossing.state = event->xmotion.state;
- }
- else {
- wi->pick_event = *event;
- }
- }
-
- /*
- * If this is a recursive call (there's already a partially completed
- * call pending on the stack; it's in the middle of processing a
- * Leave event handler for the old current item) then just return;
- * the pending call will do everything that's needed.
- */
- if (ISSET(wi->flags, ZN_REPICK_IN_PROGRESS)) {
- fprintf(stderr, "PickCurrentItem recursive\n");
- return;
- }
-
- /*
- * A LeaveNotify event automatically means that there's no current
- * object, so the check for closest item can be skipped.
- */
- if (wi->pick_event.type != LeaveNotify) {
- ZnPickStruct ps;
- ZnReal dist;
- ZnPoint p;
-
- p.x = wi->pick_event.xcrossing.x;
- p.y = wi->pick_event.xcrossing.y;
- ps.point = &p;
- ps.in_group = ZN_NO_ITEM;
- ps.start_item = ZN_NO_ITEM;
- ps.aperture = wi->pick_aperture;
- ps.recursive = True;
- ps.override_atomic = False;
- dist = wi->top_group->class->Pick(wi->top_group, &ps);
- if (dist == 0.0) {
- wi->new_item = ps.a_item;
- wi->new_part = ps.a_part;
- }
- else {
- wi->new_item = ZN_NO_ITEM;
- wi->new_part = ZN_NO_PART;
- }
- }
- else {
- wi->new_item = ZN_NO_ITEM;
- wi->new_part = ZN_NO_PART;
- }
- /*
- * This state is needed to do a valid detection
- * of Enter during a grab.
- */
- enter_item = ((wi->new_item != wi->current_item) || ISSET(wi->flags, ZN_GRABBED_ITEM));
-
- /*printf("------ PickCurrentItem current: %d %d, new %d %d\n",
- wi->current_item==ZN_NO_ITEM?0:wi->current_item->id, wi->current_part,
- wi->new_item==ZN_NO_ITEM?0:wi->new_item->id, wi->new_part);*/
-
- if ((wi->new_item == wi->current_item) &&
- (wi->new_part == wi->current_part) &&
- ISCLEAR(wi->flags, ZN_GRABBED_ITEM) &&
- ISCLEAR(wi->flags, ZN_GRABBED_PART)) {
- /*
- * Nothing to do: the current item/part hasn't changed.
- */
- return;
- }
-
- /*
- * Simulate a LeaveNotify event on the previous current item.
- * Remove the "current" tag from the previous current item.
- */
- if ((wi->current_item != ZN_NO_ITEM) &&
- (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) &&
- ISCLEAR(wi->flags, ZN_GRABBED_ITEM))) {
- ZnItem item = wi->current_item;
- /*
- * Actually emit the event only if not releasing a grab
- * on button up.
- */
- if (!grab_release) {
- XEvent event;
- event = wi->pick_event;
- event.type = LeaveNotify;
-
- /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/
- /*
- * If the event's detail happens to be NotifyInferior the
- * binding mechanism will discard the event. To be consistent,
- * always use NotifyAncestor.
- */
- event.xcrossing.detail = NotifyAncestor;
- SET(wi->flags, ZN_REPICK_IN_PROGRESS);
- DoEvent(wi, &event,
- wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART));
- CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS);
- }
-
- /*
- * In all cases, if a grab is not current, remove the current tag.
- *
- * The check on item below is needed because there could be an
- * event handler for <LeaveNotify> that deletes the current item.
- */
- if ((item == wi->current_item) && !button_down) {
- /*printf("^^^ Removing 'current' from %d\n", wi->current_item->id);*/
- ZnITEM.RemoveTag(item, current_uid);
- }
- /*
- * Note: during DoEvent above, it's possible that
- * wi->new_item got reset to NULL because the
- * item was deleted.
- */
- }
-
- /*
- * Special note: it's possible that wi->new_item == wi->current_item
- * here. This can happen, for example, if a grab was set or
- * if there is only a change in the part number.
- */
- if ((wi->new_item != wi->current_item) && button_down) {
- SET(wi->flags, ZN_GRABBED_ITEM);
- }
- else {
- if (button_down) {
- grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM);
- }
- CLEAR(wi->flags, ZN_GRABBED_ITEM);
- wi->current_item = wi->new_item;
- }
- if ((wi->new_part != wi->current_part) && button_down) {
- SET(wi->flags, ZN_GRABBED_PART);
- }
- else {
- CLEAR(wi->flags, ZN_GRABBED_PART);
- wi->current_part = wi->new_part;
- }
-
- if (!grab_release &&
- (ISSET(wi->flags, ZN_GRABBED_PART) || ISSET(wi->flags, ZN_GRABBED_ITEM))) {
- return;
- }
-
- if (wi->current_item != ZN_NO_ITEM) {
- XEvent event;
- /*
- * Add the tag 'current' to the current item under the pointer.
- */
- /*printf("Adding 'current' to %d\n", wi->current_item->id);*/
- ZnDoItem((Tcl_Interp *) NULL, wi->current_item, ZN_NO_PART, current_uid);
- /*
- * Then emit a fake Enter event on it.
- */
- /*printf("== ENTER %d %d ==\n",wi->current_item->id, wi->current_part);*/
- event = wi->pick_event;
- event.type = EnterNotify;
- event.xcrossing.detail = NotifyAncestor;
- DoEvent(wi, &event,
- enter_item, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART)));
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Bind --
- *
- * This procedure is invoked by the Tk dispatcher to handle
- * events associated with bindings on items.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Depends on the command invoked as part of the binding
- * (if there was any).
- *
- * Note:
- * This has been taken as is from the Tk canvas. It might not
- * not be fully adequate for the purpose. But at least this
- * provides two benefits: a/ It is believe to be correct and
- * b/ users are accustomed to its behavior.
- *
- *----------------------------------------------------------------------
- */
-static void
-Bind(ClientData client_data, /* Information about widget. */
- XEvent *event) /* Information about event. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
-
- Tcl_Preserve((ClientData) wi);
-
- /*
- * This code below keeps track of the current modifier state in
- * wi->state. This information is used to defer repicks of
- * the current item while buttons are down.
- */
- if ((event->type == ButtonPress) || (event->type == ButtonRelease)) {
- int mask;
-
- switch (event->xbutton.button) {
- case Button1:
- mask = Button1Mask;
- break;
- case Button2:
- mask = Button2Mask;
- break;
- case Button3:
- mask = Button3Mask;
- break;
- case Button4:
- mask = Button4Mask;
- break;
- case Button5:
- mask = Button5Mask;
- break;
- default:
- mask = 0;
- break;
- }
- /*
- * For button press events, repick the current item using the
- * button state before the event, then process the event. For
- * button release events, first process the event, then repick
- * the current item using the button state *after* the event
- * (the button has logically gone up before we change the
- * current item).
- */
-
- if (event->type == ButtonPress) {
- /*
- * On a button press, first repick the current item using
- * the button state before the event, then process the event.
- */
- wi->state = event->xbutton.state;
- PickCurrentItem(wi, event);
- wi->state ^= mask;
- if (wi->current_item != ZN_NO_ITEM) {
- DoEvent(wi, event, True, True);
- }
- }
- else {
- /*
- * Button release: first process the event, with the button
- * still considered to be down. Then repick the current
- * item under the assumption that the button is no longer down.
- */
- wi->state = event->xbutton.state;
- DoEvent(wi, event, True, True);
- event->xbutton.state ^= mask;
- wi->state = event->xbutton.state;
- PickCurrentItem(wi, event);
- event->xbutton.state ^= mask;
- }
- goto done;
- }
-
- else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) {
- wi->state = event->xcrossing.state;
- PickCurrentItem(wi, event);
- goto done;
- }
-
- else if (event->type == MotionNotify) {
- wi->state = event->xmotion.state;
- if (wi->follow_pointer) {
- PickCurrentItem(wi, event);
- }
- else {
- /* Copy the event for later processing
- * and skip the picking phase.
- */
- wi->pick_event = *event;
- }
- }
-
- DoEvent(wi, event, True, True);
-
-done:
- Tcl_Release((ClientData) wi);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * LostSelection --
- *
- * This procedure is called back by Tk when the selection is
- * grabbed away from a zinc widget.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The existing selection is unhighlighted, and the window is
- * marked as not containing a selection.
- *
- *----------------------------------------------------------------------
- */
-static void
-LostSelection(ClientData client_data)
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- ZnTextInfo *ti = &wi->text_info;
-
- if (ti->sel_item != ZN_NO_ITEM) {
- ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
- }
- ti->sel_item = ZN_NO_ITEM;
- ti->sel_field = ZN_NO_PART;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SelectTo --
- *
- * Modify the selection by moving its un-anchored end. This could
- * make the selection either larger or smaller.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The selection changes.
- *
- *----------------------------------------------------------------------
- */
-static void
-SelectTo(ZnItem item,
- int field,
- int index)
-{
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- int old_first, old_last, old_field;
- ZnItem old_sel_item;
-
- old_first = ti->sel_first;
- old_last = ti->sel_last;
- old_sel_item = ti->sel_item;
- old_field = ti->sel_field;
-
- /*
- * Grab the selection if we don't own it already.
- */
- if (ti->sel_item == ZN_NO_ITEM) {
- Tk_OwnSelection(wi->win, XA_PRIMARY, LostSelection, (ClientData) wi);
- }
- else if ((ti->sel_item != item) || (ti->sel_field != field)) {
- ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
- }
- ti->sel_item = item;
- ti->sel_field = field;
-
- if ((ti->anchor_item != item) || (ti->anchor_field) != field) {
- ti->anchor_item = item;
- ti->anchor_field = field;
- ti->sel_anchor = index;
- }
- if (ti->sel_anchor <= index) {
- ti->sel_first = ti->sel_anchor;
- ti->sel_last = index;
- }
- else {
- ti->sel_first = index;
- ti->sel_last = ti->sel_anchor;
- }
- if ((ti->sel_first != old_first) ||
- (ti->sel_last != old_last) ||
- (item != old_sel_item)) {
- ZnITEM.Invalidate(item, ZN_DRAW_FLAG);
- }
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * FetchSelection --
- *
- * This procedure is invoked by Tk to return part or all of
- * the selection, when the selection is in a zinc widget.
- * This procedure always returns the selection as a STRING.
- *
- * Results:
- * The return value is the number of non-NULL bytes stored
- * at buffer. Buffer is filled (or partially filled) with a
- * NULL-terminated string containing part or all of the selection,
- * as given by offset and maxBytes.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-static int
-FetchSelection( ClientData client_data,
- int offset, /* Offset within selection of first
- * character to be returned. */
- char *buffer, /* Location in which to place
- * selection. */
- int max_bytes) /* Maximum number of bytes to place
- * at buffer, not including terminating
- * NULL character. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- ZnTextInfo *ti = &wi->text_info;
-
- if (ti->sel_item == ZN_NO_ITEM) {
- return -1;
- }
- if (ti->sel_item->class->Selection == NULL) {
- return -1;
- }
- return (*ti->sel_item->class->Selection)(ti->sel_item, ti->sel_field,
- offset, buffer, max_bytes);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * CmdDeleted --
- *
- * This procedure is invoked when a widget command is deleted. If
- * the widget isn't already in the process of being destroyed,
- * this command destroys it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The widget is destroyed.
- *
- *----------------------------------------------------------------------
- */
-static void
-CmdDeleted(ClientData client_data) /* Pointer to widget record for widget. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
-
- if (wi->win != NULL) {
- Tk_DestroyWindow(wi->win);
- wi->win = NULL;
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Destroy --
- *
- * This procedure is invoked by Tk_EventuallyFree or Tk_Release
- * to clean up the internal structure of the widget at a safe time
- * (when no-one is using it anymore).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Everything associated with the widget is freed up.
- *
- *----------------------------------------------------------------------
- */
-static void
-Destroy(char *mem_ptr) /* Info about the widget. */
-{
- ZnWInfo *wi = (ZnWInfo *) mem_ptr;
- unsigned int num;
- Tcl_HashSearch search;
- Tcl_HashEntry *entry;
-#ifdef GL
- unsigned int i;
- ZnGLContextEntry *ce;
- ZnWInfo **wip;
-#endif
-
- /*printf("Destroy begining\n");*/
- /*
- * This procedure could be invoked either because the window was
- * destroyed and the command was then deleted (in which case win
- * is NULL) or because the command was deleted, and then this procedure
- * destroys the widget.
- */
- /*
- * Unregister form the overlap manager.
- */
-#ifdef ATC
- if (wi->om_group != ZN_NO_ITEM) {
- OmUnregister((void *) wi);
- }
-#endif
-
- /*
- * Print remaining items.
- */
-
- /* Free all items. */
- /*fprintf(stderr, "Item count before cleanup: %d\n", wi->num_items);*/
- ZnITEM.DestroyItem(wi->top_group);
- /*fprintf(stderr, "Remaining item count: %d\n", wi->num_items);*/
- /*
- * Remove the redisplay scheduled by the cleanup.
- * It will fire when the widget will be gone and
- * will corrupt memory.
- */
- if (ISSET(wi->flags, ZN_UPDATE_PENDING)) {
- Tcl_CancelIdleCall(Redisplay, (ClientData) wi);
- }
-
- for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) {
- if (wi->alpha_stipples[num] != None) {
- Tk_FreeBitmap(wi->dpy, wi->alpha_stipples[num]);
- wi->alpha_stipples[num] = None;
- }
- }
-
- Tcl_DeleteHashTable(wi->id_table);
- ZnFree(wi->id_table);
-
- /*
- * Free the transform table contents.
- */
- entry = Tcl_FirstHashEntry(wi->t_table, &search);
- while (entry != NULL) {
- ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry));
- entry = Tcl_NextHashEntry(&search);
- }
- Tcl_DeleteHashTable(wi->t_table);
- ZnFree(wi->t_table);
-
- if (wi->binding_table != NULL) {
- Tk_DeleteBindingTable(wi->binding_table);
- }
-
- /* Free the tile */
- if (wi->tile != ZnUnspecifiedImage) {
-#ifdef PTK_800
- ZnFreeImage(wi->tile, ZnImageUpdate, wi);
-#else
- ZnFreeImage(wi->tile, TileUpdate, wi);
-#endif
- wi->tile = ZnUnspecifiedImage;
- }
-
-#ifdef ATC
- /* Free the symbols */
- if (wi->map_distance_symbol != ZnUnspecifiedImage) {
- ZnFreeImage(wi->map_distance_symbol, NULL, NULL);
- wi->map_distance_symbol = ZnUnspecifiedImage;
- }
- if (wi->track_symbol != ZnUnspecifiedImage) {
- ZnFreeImage(wi->track_symbol, NULL, NULL);
- wi->track_symbol = ZnUnspecifiedImage;
- }
-#endif
-
- /* Free the double buffer pixmap/image */
- if (wi->draw_buffer) {
- Tk_FreePixmap(wi->dpy, wi->draw_buffer);
- wi->draw_buffer = 0;
- }
-
-#ifdef PTK_800
- if (wi->fore_color) {
- ZnFreeGradient(wi->fore_color);
- wi->fore_color = NULL;
- }
- if (wi->back_color) {
- ZnFreeGradient(wi->back_color);
- wi->back_color = NULL;
- }
-#endif
- if (wi->relief_grad) {
- ZnFreeGradient(wi->relief_grad);
- wi->relief_grad = NULL;
- }
- if (wi->gc) {
- XFreeGC(wi->dpy, wi->gc);
- wi->gc = 0;
- }
-
- Tcl_DeleteTimerHandler(wi->blink_handler);
-
-#ifdef PTK_800
- Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0);
-#else
- Tk_FreeConfigOptions((char *) wi, wi->opt_table, wi->win);
-#endif
-
-#ifdef GL
- if (wi->font_tfi) {
- ZnFreeTexFont(wi->font_tfi);
- wi->font_tfi = NULL;
- }
-#ifdef ATC
- if (wi->map_font_tfi) {
- ZnFreeTexFont(wi->map_font_tfi);
- wi->map_font_tfi = NULL;
- }
-#endif
- /*
- * Remove the widget from the context list and
- * free the context if no more widgets are active.
- */
- ce = ZnGetGLContext(wi->dpy);
- if (ce) {
- wip = ZnListArray(ce->widgets);
- num = ZnListSize(ce->widgets);
- for (i = 0; i < num; i++, wip++) {
- if (*wip == wi) {
- ZnListDelete(ce->widgets, i);
- }
- }
- /*
- * This code cause spurious X11 server reboots
- * with nvidia drivers (not tested with others
- * though). Thus it has been limited to WIN for
- * the time being.
- */
-#if 1 /*def _WIN32*/
- if (ZnListSize(ce->widgets) == 0) {
- ZnGLContextEntry *prev, *next;
- /*printf("Freeing a GL context\n");*/
- if (ce == gl_contexts) {
- gl_contexts = ce->next;
- }
- else {
- for (prev = gl_contexts, next = gl_contexts->next; next;
- prev = next, next = next->next) {
- if (next == ce) {
- prev->next = next->next;
- break;
- }
- }
- }
-#ifdef _WIN32
- ZnGLReleaseContext(ce);
- wglDeleteContext(ce->context);
-#else
- glXDestroyContext(ce->dpy, ce->context);
- /*
- * This call seems to be a problem for X11/Mesa
- */
- /*XFreeColormap(ce->dpy, ce->colormap);*/
- XFree(ce->visual);
-#endif
- ZnListFree(ce->widgets);
- ZnFree(ce);
- }
-#endif
- }
-#endif
- /*
- if (wi->font) {
- Tk_FreeFont(wi->font);
- }
- if (wi->map_text_font) {
- Tk_FreeFont(wi->map_text_font);
- }*/
-
- /*
- * Should be empty by now.
- */
- ZnFreeTransformStack(wi);
- ZnFreeClipStack(wi);
-
-#ifndef _WIN32
- ZnFreeChrono(wi->total_draw_chrono);
- ZnFreeChrono(wi->this_draw_chrono);
-#endif
-
- ZnFree(wi);
- /*printf("Destroy ending\n");*/
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDamage --
- *
- **********************************************************************************
- */
-void
-ZnDamage(ZnWInfo *wi,
- ZnBBox *damage)
-{
- if ((damage == NULL) || ZnIsEmptyBBox(damage)) {
- return;
- }
-
- /*printf("damaging area: %g %g %g %g\n", damage->orig.x,
- damage->orig.y, damage->corner.x, damage->corner.y);*/
-
- if (ZnIsEmptyBBox(&wi->damaged_area)) {
- wi->damaged_area.orig.x = damage->orig.x;
- wi->damaged_area.orig.y = damage->orig.y;
- wi->damaged_area.corner.x = damage->corner.x;
- wi->damaged_area.corner.y = damage->corner.y;
- ZnNeedRedisplay(wi);
- }
- else {
- wi->damaged_area.orig.x = MIN(wi->damaged_area.orig.x, damage->orig.x);
- wi->damaged_area.orig.y = MIN(wi->damaged_area.orig.y, damage->orig.y);
- wi->damaged_area.corner.x = MAX(wi->damaged_area.corner.x, damage->corner.x);
- wi->damaged_area.corner.y = MAX(wi->damaged_area.corner.y, damage->corner.y);
- }
- /*printf("damaged area: %g %g %g %g\n", wi->damaged_area.orig.x,
- wi->damaged_area.orig.y, wi->damaged_area.corner.x,
- wi->damaged_area.corner.y);*/
-}
-
-void
-ZnDamageAll(ZnWInfo *wi)
-{
- ZnBBox bbox;
-
- bbox.orig.x = bbox.orig.y = 0;
- bbox.corner.x = Tk_Width(wi->win);
- bbox.corner.y = Tk_Height(wi->win);
- ZnDamage(wi, &bbox);
-}
-
-static void
-ClampDamageArea(ZnWInfo *wi)
-{
- int width, height;
-
- if (wi->damaged_area.orig.x < wi->inset) {
- wi->damaged_area.orig.x = wi->inset;
- }
- if (wi->damaged_area.orig.y < wi->inset) {
- wi->damaged_area.orig.y = wi->inset;
- }
- if (wi->damaged_area.corner.x < wi->inset) {
- wi->damaged_area.corner.x = wi->inset;
- }
- if (wi->damaged_area.corner.y < wi->inset) {
- wi->damaged_area.corner.y = wi->inset;
- }
- width = wi->width - wi->inset;
- height = wi->height - wi->inset;
- if (wi->damaged_area.orig.x > width) {
- wi->damaged_area.orig.x = width;
- }
- if (wi->damaged_area.orig.y > height) {
- wi->damaged_area.orig.y = height;
- }
- if (wi->damaged_area.corner.x > width) {
- wi->damaged_area.corner.x = width;
- }
- if (wi->damaged_area.corner.y > height) {
- wi->damaged_area.corner.y = height;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Update --
- *
- **********************************************************************************
- */
-static void
-Update(ZnWInfo *wi)
-{
- /*
- * Give the overlap manager a chance to do its work.
- */
-#ifdef ATC
- if ((wi->om_group != ZN_NO_ITEM) && ZnGroupCallOm(wi->om_group)) {
- ZnPoint scale={1.0,1.0};
- if (wi->om_group->transfo) {
- ZnTransfoDecompose(wi->om_group->transfo, &scale,
- NULL, NULL, NULL);
- }
- OmProcessOverlap((void *) wi, wi->width, wi->height, scale.x);
- ZnGroupSetCallOm(wi->om_group, False);
- }
-#endif
- if (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) ||
- ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) {
- wi->top_group->class->ComputeCoordinates(wi->top_group, False);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * Repair --
- *
- **********************************************************************************
- */
-static void
-Repair(ZnWInfo *wi)
-{
- XGCValues values;
- ZnPoint p[5];
- ZnTriStrip tristrip;
-#ifdef GL
- XColor *color;
- ZnGLContextEntry *ce;
-#endif
- int int_width = Tk_Width(wi->win);
- int int_height = Tk_Height(wi->win);
-
- /*SET(wi->flags, ZN_CONFIGURE_EVENT);*/
- if (wi->render) {
-#ifdef GL
- /* Load deferred font glyphs just before making the context
- * current. Mandatory under Windows (probably due to hdc use conflict).
- */
- ZnGetDeferredGLGlyphs();
-
- ZnGLWaitX();
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
- ClampDamageArea(wi);
- /*
- * Merge the exposed area.
- */
- ZnAddBBoxToBBox(&wi->damaged_area, &wi->exposed_area);
- if (ZnIsEmptyBBox(&wi->damaged_area)) {
- return;
- }
- }
-#endif
-
- /*printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));*/
- ce = ZnGLMakeCurrent(wi->dpy, wi);
- glEnable(GL_POINT_SMOOTH);
- glEnable(GL_LINE_SMOOTH);
-#if 0
- glEnable(GL_POLYGON_SMOOTH); /* expensive ? */
-#endif
-
- glEnable(GL_BLEND);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glClearStencil(0);
- color = ZnGetGradientColor(wi->back_color, 0.0, NULL);
- glClearColor((GLfloat) color->red/65536, (GLfloat) color->green/65536,
- (GLfloat) color->blue/65536, 0.0);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- /*
- * Init the composite group alpha.
- */
- wi->alpha = 100;
-
- glViewport(0, 0, (GLsizei) int_width, int_height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0, (GLfloat) int_width, (GLfloat) int_height, 0.0, -1.0, 1.0);
- glMatrixMode(GL_MODELVIEW);
-
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
- glEnable(GL_SCISSOR_TEST);
-
- /*
- * Set the damaged area as the scissor area.
- */
- wi->damaged_area.orig.x = ZnNearestInt(wi->damaged_area.orig.x);
- wi->damaged_area.orig.y = ZnNearestInt(wi->damaged_area.orig.y);
- wi->damaged_area.corner.x = ZnNearestInt(wi->damaged_area.corner.x);
- wi->damaged_area.corner.y = ZnNearestInt(wi->damaged_area.corner.y);
- glScissor((int) wi->damaged_area.orig.x,
- int_height - (int) wi->damaged_area.corner.y,
- (int) (wi->damaged_area.corner.x - wi->damaged_area.orig.x),
- (int) (wi->damaged_area.corner.y - wi->damaged_area.orig.y));
- }
- else {
- glDisable(GL_SCISSOR_TEST);
- wi->damaged_area.orig.x = wi->damaged_area.orig.y = wi->inset;
- wi->damaged_area.corner.x = int_width-wi->inset;
- wi->damaged_area.corner.y = int_height-wi->inset;
- }
-#else
- /*
- * We do not use the damaged area set it to the whole area.
- */
- wi->damaged_area.orig.x = wi->damaged_area.orig.y = wi->inset;
- wi->damaged_area.corner.x = int_width-wi->inset;
- wi->damaged_area.corner.y = int_height-wi->inset;
-#endif
-
- /*
- * Clear the GL buffers.
- */
- glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- /*
- * Setup the background tile if needed.
- */
- if (wi->tile != ZnUnspecifiedImage) {
- ZnBBox bbox;
-
- bbox.orig.x = bbox.orig.y = 0.0;
- bbox.corner.x = int_width;
- bbox.corner.y = int_height;
-
- ZnRenderTile(wi, wi->tile, NULL, NULL, NULL, (ZnPoint *) &bbox);
- }
-
- wi->top_group->class->Render(wi->top_group);
-
- if ((wi->border_width > 0) || (wi->highlight_width > 0)) {
- unsigned short alpha;
-
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
- glDisable(GL_SCISSOR_TEST);
- }
-#endif
- if (wi->highlight_width > 0) {
- color = ZnGetGradientColor(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color:
- wi->highlight_bg_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, 100);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- glBegin(GL_QUAD_STRIP);
- glVertex2d(0.0, 0.0);
- glVertex2i(wi->highlight_width, wi->highlight_width);
- glVertex2i(int_width, 0);
- glVertex2i(int_width - wi->highlight_width, wi->highlight_width);
- glVertex2i(int_width, int_height);
- glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width);
- glVertex2i(0, int_height);
- glVertex2i(wi->highlight_width, int_height - wi->highlight_width);
- glVertex2i(0, 0);
- glVertex2i(wi->highlight_width, wi->highlight_width);
- glEnd();
- }
- if (wi->border_width > 0) {
- if (wi->relief != ZN_RELIEF_FLAT) {
- p[4].x = p[4].y = p[3].y = p[1].x = wi->highlight_width;
- p[0] = p[4];
- p[3].x = p[2].x = int_width - wi->highlight_width;
- p[2].y = p[1].y = int_height - wi->highlight_width;
- ZnRenderPolygonRelief(wi, wi->relief, wi->relief_grad,
- False, p, 5, (ZnReal) wi->border_width);
- }
- else {
- color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, 100);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- glBegin(GL_QUAD_STRIP);
- glVertex2d(0.0, 0.0);
- glVertex2i(wi->highlight_width, wi->highlight_width);
- glVertex2i(int_width, 0);
- glVertex2i(int_width - wi->highlight_width, wi->highlight_width);
- glVertex2i(int_width, int_height);
- glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width);
- glVertex2i(0, int_height);
- glVertex2i(wi->highlight_width, int_height - wi->highlight_width);
- glVertex2i(0, 0);
- glVertex2i(wi->highlight_width, wi->highlight_width);
- glEnd();
- }
- }
-
- CLEAR(wi->flags, ZN_CONFIGURE_EVENT);
- }
-
- /* Switch the GL buffers. */
- /* The scissor test might be needed under windows, should be tested.
- * Symptom: when moving the window, the buffer switch results in a
- * shifted display all around the damaged area.
- */
-#ifdef GL_DAMAGE
- if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
- glEnable(GL_SCISSOR_TEST);
- }
-#endif
- ZnGLSwapBuffers(ce, wi);
-
- /*
- * Wait the end of GL update if we need to synchronize
- * to monitor perfs.
- */
- if (ISSET(wi->flags, ZN_MONITORING)) {
- ZnGLWaitGL();
- }
-
- ZnGLReleaseContext(ce);
-#endif
- }
- else {
- XRectangle r, rs[4];
- ZnBBox merge;
-
- ClampDamageArea(wi);
- /*
-m * Merge the damaged area with the exposed area.
- */
- ZnResetBBox(&merge);
- ZnCopyBBox(&wi->damaged_area, &merge);
- ZnAddBBoxToBBox(&merge, &wi->exposed_area);
- if (!ZnIsEmptyBBox(&merge)) {
-
- /* Set the whole damaged area as clip rect. */
- wi->damaged_area.orig.x = r.x = ZnNearestInt(wi->damaged_area.orig.x);
- wi->damaged_area.orig.y = r.y = ZnNearestInt(wi->damaged_area.orig.y);
- wi->damaged_area.corner.x = ZnNearestInt(wi->damaged_area.corner.x);
- wi->damaged_area.corner.y = ZnNearestInt(wi->damaged_area.corner.y);
- r.width = (unsigned short) (wi->damaged_area.corner.x - wi->damaged_area.orig.x);
- r.height = (unsigned short) (wi->damaged_area.corner.y - wi->damaged_area.orig.y);
- p[0] = wi->damaged_area.orig;
- p[1] = wi->damaged_area.corner;
- ZnTriStrip1(&tristrip, p, 2, False);
- ZnPushClip(wi, &tristrip, True, True);
-
- /* Fill the background of the double buffer pixmap. */
- if (wi->tile == ZnUnspecifiedImage) {
- values.foreground = ZnGetGradientPixel(wi->back_color, 0.0);
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
- }
- else {
- values.fill_style = FillTiled;
- values.tile = ZnImagePixmap(wi->tile, wi->win);
- values.ts_x_origin = values.ts_y_origin = 0;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin,
- &values);
- }
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height);
-
- /* Draw the items */
- wi->top_group->class->Draw(wi->top_group);
-
- ZnPopClip(wi, True);
-
- /*
- * Send the merged area back to screen.
- */
- merge.orig.x = MAX(merge.orig.x, wi->inset);
- merge.orig.y = MAX(merge.orig.y, wi->inset);
- merge.corner.x = MIN(merge.corner.x, int_width-wi->inset);
- merge.corner.y = MIN(merge.corner.y, int_height-wi->inset);
- ZnBBox2XRect(&merge, &r);
- XCopyArea(wi->dpy,
- wi->draw_buffer, Tk_WindowId(wi->win), wi->gc,
- r.x, r.y, r.width, r.height, r.x, r.y);
- }
-
- /*
- * Redraw the borders.
- */
- if (wi->border_width > 0) {
- Pixmap save;
-
- save = wi->draw_buffer;
- wi->draw_buffer = Tk_WindowId(wi->win);
- if (wi->relief_grad != ZN_RELIEF_FLAT) {
- r.x = r.y = wi->highlight_width;
- r.width = int_width - 2*wi->highlight_width;
- r.height = int_height - 2*wi->highlight_width;
- ZnDrawRectangleRelief(wi, wi->relief, wi->relief_grad, &r,
- (ZnDim) wi->border_width);
- }
- else {
- XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(wi->back_color, 0.0));
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- rs[0].x = rs[0].y = wi->highlight_width;
- rs[0].width = int_width - 2*wi->highlight_width;
- rs[0].height = wi->border_width;
- rs[1].x = int_width - wi->highlight_width - wi->border_width;
- rs[1].y = 0;
- rs[1].width = wi->border_width;
- rs[1].height = int_height - 2*wi->highlight_width;
- rs[2].x = 0;
- rs[2].y = int_height - wi->highlight_width - wi->border_width;
- rs[2].width = rs[0].width;
- rs[2].height = wi->border_width;
- rs[3].x = rs[3].y = wi->highlight_width;
- rs[3].width = wi->border_width;
- rs[3].height = rs[1].height;
- XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4);
- }
- wi->draw_buffer = save;
- }
- if (wi->highlight_width > 0) {
- XSetForeground(wi->dpy, wi->gc,
- ZnGetGradientPixel(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color:
- wi->highlight_bg_color, 0.0));
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- rs[0].x = rs[0].y = 0;
- rs[0].width = int_width;
- rs[0].height = wi->highlight_width;
- rs[1].x = int_width - wi->highlight_width;
- rs[1].y = 0;
- rs[1].width = wi->highlight_width;
- rs[1].height = int_height;
- rs[2].x = 0;
- rs[2].y = int_height - wi->highlight_width;
- rs[2].width = int_width;
- rs[2].height = wi->highlight_width;
- rs[3].x = rs[3].y = 0;
- rs[3].width = wi->highlight_width;
- rs[3].height = int_height;
- XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4);
- }
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Redisplay --
- *
- * This procedure redraws the contents of a Zinc window.
- * It is invoked as a do-when-idle handler, so it only runs
- * when there's nothing else for the application to do.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Information appears on the screen.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-Redisplay(ClientData client_data) /* Information about the widget. */
-{
- ZnWInfo *wi = (ZnWInfo *) client_data;
-
- CLEAR(wi->flags, ZN_UPDATE_PENDING);
- if (ISCLEAR(wi->flags, ZN_REALIZED) || !Tk_IsMapped(wi->win)) {
- return;
- }
-
- if (ISSET(wi->flags, ZN_MONITORING)) {
-#ifndef _WIN32
- ZnXStartChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
- ZnResetChronos(wi->this_draw_chrono);
- ZnXStartChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
-#endif
- }
-
- do {
- /*
- * Update the items.
- */
- Update(wi);
-
- /*
- * Do enter/leave processing after the overlap manager
- * has finished with the items. Do it has many times
- * as needed, each round may trigger callbacks that
- * result in moved items and so forth. It can even
- * lead to the widget destruction, this is the reason
- * for Tcl_Preserve/Tcl_Release.
- */
- if (ISSET(wi->flags, ZN_INTERNAL_NEED_REPICK)) {
- Tk_Window tkwin;
-
- if (wi->follow_pointer) {
- Tcl_Preserve((ClientData) wi);
- CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
- PickCurrentItem(wi, &wi->pick_event);
- tkwin = wi->win;
- Tcl_Release((ClientData) wi);
- if (tkwin == NULL) {
- return;
- }
- }
- else if (ISCLEAR(wi->top_group->inv_flags, ZN_COORDS_FLAG) &&
- ISCLEAR(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) {
- /* Don't repick now but escape the loop if
- * the geometry is updated. */
- break;
- }
- }
- }
- while (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) ||
- ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG) ||
- ISSET(wi->flags, ZN_INTERNAL_NEED_REPICK));
-
- /*
- * Repair the scene where it is no longer up to date,
- * then send the merged area back to the screen.
- */
- Repair(wi);
-
- /*
- * Reset the exposed & damaged areas.
- */
- ZnResetBBox(&wi->exposed_area);
- ZnResetBBox(&wi->damaged_area);
-
- if (ISSET(wi->flags, ZN_MONITORING)) {
-#ifndef _WIN32
- ZnXStopChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
- ZnXStopChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
-#endif
- }
-
- if (ISSET(wi->flags, ZN_UPDATE_SCROLLBARS)) {
- UpdateScrollbars(wi);
- }
-}
-
-#ifndef _WIN32
-#define CALLBACK
-#endif
-
-static void CALLBACK
-ZnTessBegin(GLenum type,
- void *data)
-{
- ZnPoly *outlines = data;
- ZnTriStrip *tristrips = data;
-
- ZnListEmpty(ZnWorkPoints);
- ZnTesselator.type = type;
- if (type == GL_LINE_LOOP) {
- outlines->num_contours++;
- outlines->contours = ZnRealloc(outlines->contours,
- outlines->num_contours * sizeof(ZnContour));
- }
- else {
- tristrips->num_strips++;
- tristrips->strips = ZnRealloc(tristrips->strips,
- tristrips->num_strips * sizeof(ZnStrip));
- tristrips->strips[tristrips->num_strips-1].fan = (type==GL_TRIANGLE_FAN);
- }
- //printf("Début de fragment de type: %s\n",
- //(type == GL_TRIANGLE_FAN) ? "FAN" :
- //(type == GL_TRIANGLE_STRIP) ? "STRIP" :
- //(type == GL_TRIANGLES) ? "TRIANGLES" :
- //(type == GL_LINE_LOOP) ? "LINE LOOP" : "");
-}
-
-static void CALLBACK
-ZnTessVertex(void *vertex_data,
- void *data)
-{
- ZnTriStrip *tristrips = data;
- ZnPoint p;
- int size;
-
- p.x = ((GLdouble *) vertex_data)[0];
- p.y = ((GLdouble *) vertex_data)[1];
- //printf("Sommet en %g %g\n", p.x, p.y);
- size = ZnListSize(ZnWorkPoints);
- if ((ZnTesselator.type == GL_TRIANGLES) && (size == 3)) {
- tristrips->strips[tristrips->num_strips-1].num_points = size;
- tristrips->strips[tristrips->num_strips-1].points = ZnMalloc(size * sizeof(ZnPoint));
- memcpy(tristrips->strips[tristrips->num_strips-1].points,
- ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
- //printf("Fin de fragment intermediaire %d, num points: %d\n", tristrips->num_strips-1, size);
- /* Allocate a new fragment */
- ZnListEmpty(ZnWorkPoints);
- tristrips->num_strips++;
- tristrips->strips = ZnRealloc(tristrips->strips,
- tristrips->num_strips * sizeof(ZnStrip));
- tristrips->strips[tristrips->num_strips-1].fan = False;
- }
- ZnListAdd(ZnWorkPoints, &p, ZnListTail);
-}
-
-static void CALLBACK
-ZnTessEnd(void *data)
-{
- ZnPoly *outlines = data;
- ZnTriStrip *tristrips = data;
- unsigned int size = ZnListSize(ZnWorkPoints);
- unsigned int num;
-
- if (ZnTesselator.type == GL_LINE_LOOP) {
- /* Add the last point to close the outline */
- size++;
- num = outlines->num_contours;
- outlines->contours[num-1].num_points = size;
- outlines->contours[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
- memcpy(outlines->contours[num-1].points,
- ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
- outlines->contours[num-1].points[size-1] = outlines->contours[num-1].points[0];
- outlines->contours[num-1].cw = !ZnTestCCW(outlines->contours[num-1].points, size);
- }
- else {
- num = tristrips->num_strips;
- tristrips->strips[num-1].num_points = size;
- tristrips->strips[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
- memcpy(tristrips->strips[num-1].points,
- ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
- }
- //printf("Fin de fragment %d, num points: %d\n", num, size);
-}
-
-static void CALLBACK
-ZnTessCombine(GLdouble coords[3],
- void *vertex_data[4],
- GLfloat weight[4],
- void **out_data,
- void *data)
-{
- ZnCombineData *cdata;
-
- cdata = ZnMalloc(sizeof(ZnCombineData));
- cdata->v[0] = coords[0];
- cdata->v[1] = coords[1];
- cdata->next = ZnTesselator.combine_list;
- ZnTesselator.combine_list = cdata;
- *out_data = &cdata->v;
- ZnTesselator.combine_length++;
- //printf("Création d'un nouveau sommet en %g %g\n",
- //cdata->v[0], cdata->v[1]);
-}
-
-static void CALLBACK
-ZnTessError(GLenum errno,
- void *data)
-{
- fprintf(stderr, "Tesselation error in curve item: %d\n", errno);
-}
-
-
-static void
-InitZinc(Tcl_Interp *interp) {
- static ZnBool inited = False;
- unsigned int i, x, y, bit;
- char name[TCL_INTEGER_SPACE + 20];
-
- if (inited) {
- return;
- }
-
- /*
- * Add the specific bitmaps.
- */
- for (i = 0; i < sizeof(SYMBOLS_BITS)/(SYMBOL_WIDTH*SYMBOL_HEIGHT/8); i++) {
- sprintf(name, "AtcSymbol%d", i+1);
- Tk_DefineBitmap(interp, Tk_GetUid(name),
- SYMBOLS_BITS[i], SYMBOL_WIDTH, SYMBOL_HEIGHT);
- }
-
- for (i = 0; i < ZN_NUM_ALPHA_STEPS; i++) {
- for (y = 0; y < 4; y++) {
- bitmaps[i][y][0] = 0;
- for (x = 0; x < 4; x++) {
- /*
- * Use the dither4x4 matrix to determine if this bit is on
- */
- bit = (i >= dither4x4[y][x]) ? 1 : 0;
- /*
- * set the bit in the array used to make the X Bitmap
- * mirror the pattern in x & y to make an 8x8 bitmap.
- */
- if (bit) {
- bitmaps[i][y][0] |= (1 << x);
- bitmaps[i][y][0] |= (1 << (4 + x));
- }
- }
- bitmaps[i][y][1] = bitmaps[i][y][2] = bitmaps[i][y][3] = bitmaps[i][y][0];
- bitmaps[i][y+4][0] = bitmaps[i][y+4][1] = bitmaps[i][y][0];
- bitmaps[i][y+4][2] = bitmaps[i][y+4][3] = bitmaps[i][y][0];
- bitmaps[i][y+8][0] = bitmaps[i][y+8][1] = bitmaps[i][y][0];
- bitmaps[i][y+8][2] = bitmaps[i][y+8][3] = bitmaps[i][y][0];
- bitmaps[i][y+12][0] = bitmaps[i][y+12][1] = bitmaps[i][y][0];
- bitmaps[i][y+12][2] = bitmaps[i][y+12][3] = bitmaps[i][y][0];
- bitmaps[i][y+16][0] = bitmaps[i][y+16][1] = bitmaps[i][y][0];
- bitmaps[i][y+16][2] = bitmaps[i][y+16][3] = bitmaps[i][y][0];
- bitmaps[i][y+20][0] = bitmaps[i][y+20][1] = bitmaps[i][y][0];
- bitmaps[i][y+20][2] = bitmaps[i][y+20][3] = bitmaps[i][y][0];
- bitmaps[i][y+24][0] = bitmaps[i][y+24][1] = bitmaps[i][y][0];
- bitmaps[i][y+24][2] = bitmaps[i][y+24][3] = bitmaps[i][y][0];
- bitmaps[i][y+28][0] = bitmaps[i][y+28][1] = bitmaps[i][y][0];
- bitmaps[i][y+28][2] = bitmaps[i][y+28][3] = bitmaps[i][y][0];
- }
- sprintf(name, "AlphaStipple%d", i);
- Tk_DefineBitmap(interp, Tk_GetUid(name), (char *) bitmaps[i], 32, 32);
- }
-
- /*
- * Initialize the temporary lists.
- */
- ZnWorkPoints = ZnListNew(8, sizeof(ZnPoint));
- ZnWorkXPoints = ZnListNew(8, sizeof(XPoint));
- ZnWorkStrings = ZnListNew(8, sizeof(char *));
-
- /*
- * Allocate a GLU tesselator.
- */
- ZnTesselator.tess = gluNewTess();
- ZnTesselator.combine_list = NULL;
- ZnTesselator.combine_length = 0;
- gluTessCallback(ZnTesselator.tess, GLU_TESS_BEGIN_DATA, ZnTessBegin);
- gluTessCallback(ZnTesselator.tess, GLU_TESS_VERTEX_DATA, ZnTessVertex);
- gluTessCallback(ZnTesselator.tess, GLU_TESS_END_DATA, ZnTessEnd);
- gluTessCallback(ZnTesselator.tess, GLU_TESS_COMBINE_DATA, ZnTessCombine);
- gluTessCallback(ZnTesselator.tess, GLU_TESS_ERROR_DATA, ZnTessError);
- gluTessNormal(ZnTesselator.tess, 0.0, 0.0, -1.0);
-
- /*
- * Initialize the item module.
- */
- ZnItemInit();
-
- all_uid = Tk_GetUid("all");
- current_uid = Tk_GetUid("current");
- and_uid = Tk_GetUid("&&");
- or_uid = Tk_GetUid("||");
- xor_uid = Tk_GetUid("^");
- paren_uid = Tk_GetUid("(");
- end_paren_uid = Tk_GetUid(")");
- neg_paren_uid = Tk_GetUid("!(");
- tag_val_uid = Tk_GetUid("!!");
- neg_tag_val_uid = Tk_GetUid("!");
- dot_uid = Tk_GetUid(".");
- star_uid = Tk_GetUid("*");
-
- /*
- * Initialise Overlap manager library.
- */
-#ifdef ATC
- OmInit();
-#endif
-
- inited = True;
-}
-
-#ifdef BUILD_Tkzinc
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * Tkzinc_Init --
- *
- * This procedure is invoked by Tcl_AppInit in tkAppInit.c to
- * initialize the widget.
- *
- *----------------------------------------------------------------------
- */
-EXTERN int
-Tkzinc_Init(Tcl_Interp *interp) /* Used for error reporting. */
-{
-#ifndef PTK
- if (
-# ifdef USE_TCL_STUBS
- Tcl_InitStubs(interp, "8.4", 0)
-# else
- Tcl_PkgRequire(interp, "Tcl", "8.4", 0)
-# endif
- == NULL) {
- return TCL_ERROR;
- }
-
- if (
-# ifdef USE_TK_STUBS
- Tk_InitStubs(interp, "8.4", 0)
-# else
- Tcl_PkgRequire(interp, "Tk", "8.4", 0)
-# endif
- == NULL) {
- return TCL_ERROR;
- }
-#endif
- /*
- * Create additional commands
- */
- Tcl_CreateObjCommand(interp, "zinc", ZincObjCmd,
- (ClientData) Tk_MainWindow(interp),
- (Tcl_CmdDeleteProc *) NULL);
-#ifdef ATC
- Tcl_CreateObjCommand(interp, "mapinfo", ZnMapInfoObjCmd,
- (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "videomap", ZnVideomapObjCmd,
- (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
-#endif
-
-#ifndef PTK
- if (Tcl_PkgProvide(interp, "Tkzinc", VERSION) == TCL_ERROR) {
- return TCL_ERROR;
- }
-#endif
-
- return TCL_OK;
-}
-
-EXTERN int
-Tkzinc_debug_Init(Tcl_Interp *interp) /* Used for error reporting. */
-{
- return Tkzinc_Init(interp);
-}
-
-#ifdef _WIN32
-/*
- *----------------------------------------------------------------------
- *
- * DllEntryPoint --
- *
- * This wrapper function is used by Windows to invoke the
- * initialization code for the DLL. If we are compiling
- * with Visual C++, this routine will be renamed to DllMain.
- * routine.
- *
- * Results:
- * Returns TRUE;
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-BOOL APIENTRY
-DllEntryPoint(HINSTANCE hInst, /* Library instance handle. */
- DWORD reason, /* Reason this function is being called. */
- LPVOID reserved) /* Not used. */
-{
- return TRUE;
-}
-#endif
diff --git a/generic/tkZinc.h b/generic/tkZinc.h
deleted file mode 100644
index 2eb105b..0000000
--- a/generic/tkZinc.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * tkZinc.h -- Header file for Tk zinc widget.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Mon Mar 15 14:02:03 1999
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-#ifndef _tkZinc_h
-#define _tkZinc_h
-
-#include "WidgetInfo.h"
-#include "Item.h"
-#include "List.h"
-#include "MapInfo.h"
-
-#include <GL/glu.h>
-
-typedef struct _ZnTagSearch {
- ZnWInfo *wi;
- ZnItem current; /* Pointer to last item returned. */
- ZnItem previous; /* The item right before the current
- * is tracked so if the current is
- * deleted we don't have to start from the
- * beginning. */
- ZnBool over; /* Non-zero means NextItem should always
- * return NULL. */
- int type; /* search type */
- unsigned int id; /* item id for searches by id */
-
- Tk_Uid tag; /* tag expression string */
- int tag_index; /* current position in string scan */
- int tag_len; /* length of tag expression string */
-
- char *rewrite_buf; /* tag string (after removing escapes) */
- unsigned int rewrite_buf_alloc; /* available space for rewrites */
-
- struct _TagSearchExpr *expr; /* compiled tag expression */
- ZnItem group;
- ZnBool recursive;
- ZnList item_stack;
-} ZnTagSearch;
-
-/*
- * Structure used by the tesselator.
- */
-typedef struct _ZnCombineData {
- ZnReal v[2];
- struct _ZnCombineData *next;
-} ZnCombineData;
-
-typedef struct _ZnTess {
- GLUtesselator *tess;
- ZnCombineData *combine_list;
- int type;
- int combine_length;
-} ZnTess;
-
-extern ZnList ZnWorkPoints;
-extern ZnList ZnWorkXPoints;
-extern ZnList ZnWorkStrings;
-extern ZnTess ZnTesselator;
-
-#ifdef GL
-typedef struct _ZnGLContextEntry {
- ZnGLContext context;
- Display *dpy;
- ZnReal max_line_width;
- ZnReal max_point_width;
- unsigned int max_tex_size;
- ZnList widgets;
-#ifdef _WIN32
- PIXELFORMATDESCRIPTOR pfd;
- int ipixel;
- HWND hwnd; /* Temporary storage between MakeCurrent and Release */
- HDC hdc;
-#else
- XVisualInfo *visual; /* Should these two be managed by screen ? */
- Colormap colormap;
-#endif
- struct _ZnGLContextEntry *next;
-} ZnGLContextEntry;
-
-ZnGLContextEntry *ZnGetGLContext(Display *dpy);
-ZnGLContextEntry *ZnGLMakeCurrent(Display *dpy, ZnWInfo *wi);
-void ZnGLReleaseContext(ZnGLContextEntry *ce);
-#endif
-
-int ZnParseCoordList(ZnWInfo *wi, Tcl_Obj *arg, ZnPoint **pts,
- char **controls, unsigned int *num_pts, ZnBool *old_format);
-int ZnItemWithTagOrId(ZnWInfo *wi, Tcl_Obj *tag_or_id,
- ZnItem *item, ZnTagSearch **search_var);
-void ZnTagSearchDestroy(ZnTagSearch *search);
-void ZnDoItem(Tcl_Interp *interp, ZnItem item, int part, Tk_Uid tag_uid);
-void ZnNeedRedisplay(ZnWInfo *wi);
-void ZnDamage(ZnWInfo *wi, ZnBBox *damage);
-void ZnDamageAll(ZnWInfo *wi);
-
-
-#endif /* _tkZinc_h */