From 960cdf29197bc3f5922110cf26627aa9709ac79b Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Fri, 10 Jun 2005 10:29:11 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'bogue40'. --- generic/Arc.c | 1330 ------- generic/Attrs.c | 1109 ------ generic/Attrs.h | 241 -- generic/CharsetISO8859-15.h | 18 - generic/CharsetUTF8.h | 25 - generic/Color.c | 1220 ------ generic/Color.h | 85 - generic/Curve.c | 2260 ----------- generic/Draw.c | 2245 ----------- generic/Draw.h | 119 - generic/Field.c | 2584 ------------ generic/Field.h | 85 - generic/Geo.c | 3276 ---------------- generic/Geo.h | 384 -- generic/Group.c | 1781 --------- generic/Group.h | 35 - generic/Icon.c | 949 ----- generic/Image.c | 1695 -------- generic/Image.h | 72 - generic/Item.c | 2664 ------------- generic/Item.h | 377 -- generic/List.c | 557 --- generic/List.h | 68 - generic/Map.c | 1611 -------- generic/MapInfo.c | 2171 ----------- generic/MapInfo.h | 95 - generic/OverlapMan.c | 1125 ------ generic/OverlapMan.h | 109 - generic/PostScript.c | 1873 --------- generic/PostScript.h | 57 - generic/Rectangle.c | 1026 ----- generic/Reticle.c | 621 --- generic/Tabular.c | 706 ---- generic/Text.c | 2061 ---------- generic/Track.c | 2372 ----------- generic/Track.h | 48 - generic/Transfo.c | 754 ---- generic/Transfo.h | 105 - generic/Triangles.c | 918 ----- generic/Types.h | 197 - generic/WidgetInfo.h | 254 -- generic/Window.c | 809 ---- generic/perfos.c | 345 -- generic/perfos.h | 63 - generic/tkZinc.c | 9059 ------------------------------------------- generic/tkZinc.h | 110 - 46 files changed, 49668 deletions(-) delete mode 100644 generic/Arc.c delete mode 100644 generic/Attrs.c delete mode 100644 generic/Attrs.h delete mode 100644 generic/CharsetISO8859-15.h delete mode 100644 generic/CharsetUTF8.h delete mode 100644 generic/Color.c delete mode 100644 generic/Color.h delete mode 100644 generic/Curve.c delete mode 100644 generic/Draw.c delete mode 100644 generic/Draw.h delete mode 100644 generic/Field.c delete mode 100644 generic/Field.h delete mode 100644 generic/Geo.c delete mode 100644 generic/Geo.h delete mode 100644 generic/Group.c delete mode 100644 generic/Group.h delete mode 100644 generic/Icon.c delete mode 100644 generic/Image.c delete mode 100644 generic/Image.h delete mode 100644 generic/Item.c delete mode 100644 generic/Item.h delete mode 100644 generic/List.c delete mode 100644 generic/List.h delete mode 100644 generic/Map.c delete mode 100644 generic/MapInfo.c delete mode 100644 generic/MapInfo.h delete mode 100644 generic/OverlapMan.c delete mode 100644 generic/OverlapMan.h delete mode 100644 generic/PostScript.c delete mode 100644 generic/PostScript.h delete mode 100644 generic/Rectangle.c delete mode 100644 generic/Reticle.c delete mode 100644 generic/Tabular.c delete mode 100644 generic/Text.c delete mode 100644 generic/Track.c delete mode 100644 generic/Track.h delete mode 100644 generic/Transfo.c delete mode 100644 generic/Transfo.h delete mode 100644 generic/Triangles.c delete mode 100644 generic/Types.h delete mode 100644 generic/WidgetInfo.h delete mode 100644 generic/Window.c delete mode 100644 generic/perfos.c delete mode 100644 generic/perfos.h delete mode 100644 generic/tkZinc.c delete mode 100644 generic/tkZinc.h (limited to 'generic') 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(¢er, 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(¢er, 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, ¢er, 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 -#include -#include - - -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 - - -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 -#include - -#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; inum_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 -#include - -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 -#include - - -#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 -#include - - -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 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 . - * A field is selected if 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 - - -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 , .. - */ -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 , - * the thickness of its outline . 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, ¢er_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, ¢er_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 -#include - - -#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 -#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<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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ®, &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, ¤t_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, ¤t_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, ¤t_clip, ¤t_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 -#include -#ifdef GL -#include -#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 -#include /* For INT_MAX */ -#include -#include -#include - - -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 -#include - - -/* - * 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 -#include -#include - - -/* - ********************************************************************************** - * - * 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 -#include - - -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, ¢er); - 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 -#include -#else -#include -#endif - -#include "MapInfo.h" -#include "tkZinc.h" - -#include -#include - - - -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 *) ¤t_vm, - sizeof(VideoMap)) != sizeof(VideoMap)) { - goto error; - } - cur_id = ntohi((unsigned int) current_vm.id); - while (cur_index != index) { - if (Tcl_Read(chan, (char *) ¤t_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(¤t_vm); - FillMap(map, ¤t_vm); - if ((Tcl_Read(chan, (char *) ¤t_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 *) ¤t_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 *) ¤t_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 -#else -#include "malloc.h" -#endif - -#include -#include -#include - -#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 -#include - -/* - * 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 -#include -#endif -#include -#include -#include -#include - -#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, ¢er); - 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 - -/* - * 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 -#include - - -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 - - -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 -#include - - -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 -#include -#include -#include -#include - -#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 -#include - - -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, ¤t_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 - - -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 -#include - - -/* - * 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 - - -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 -# 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 -# else -# include -# endif -#endif - -#define NEED_REAL_STDIO - -#include -#include -#include -#include -#ifdef PTK -# include -# include -# include -# ifndef PTK_800 -# define Arg Tcl_Obj * -# endif -#else -# include -# include -#endif -#include - - -/* 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 - -# 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 - - -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 -#include -#include -#include -#include -#include - - 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 -#include -#include -#include -#include -#include -#include -#if defined(_WIN32) && defined(PTK) && !defined(PTK_800) -#include -#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 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, <ime, 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], °) != 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 . - */ - 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?"": - // event->type==LeaveNotify?"": - // event->type==MotionNotify?"":"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 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 - -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 */ -- cgit v1.1