diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/Map.c | 1395 |
1 files changed, 1395 insertions, 0 deletions
diff --git a/generic/Map.c b/generic/Map.c new file mode 100644 index 0000000..45644d4 --- /dev/null +++ b/generic/Map.c @@ -0,0 +1,1395 @@ +/* + * Map.c -- Implementation of Map item. + * + * Authors : Patrick Lecoanet. + * Creation date : + * + * $Id$ + */ + +/* + * Copyright (c) 1993 - 1999 CENA, Patrick Lecoanet -- + * + * This code is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this code; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include "Types.h" +#include "MapInfo.h" +#include "Item.h" +#include "Geo.h" +#include "Draw.h" +#include "WidgetInfo.h" +#include "tkRadar.h" +#ifdef PERFOS +#include "perfos.h" +#endif + +#include <memory.h> +#include <malloc.h> +#include <stdio.h> + + +static const char rcsid[] = "$Id$"; +static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; + + +/* + ********************************************************************************** + * + * Specific Map item record + * + ********************************************************************************** + */ + +typedef struct _MapItemStruct { + ItemStruct header; + + /* Public data */ + RadarBool filled; + Pixmap fill_pattern; + RadarColor color; + RadarFont text_font; /* null value -> use radar_map_text_font */ + char *map_info_name; + RadarList symbol_patterns; + + /* Private data */ + MapInfoId map_info; + RadarList vectors; + RadarList dashed_vectors; + RadarList dotted_vectors; + RadarList mixed_vectors; + RadarList arcs; + RadarList dashed_arcs; + RadarList dotted_arcs; + RadarList mixed_arcs; + RadarList marks; + RadarList symbols; + RadarList texts; +#ifdef PERFOS + Chrono chrono_trans; + Chrono chrono_draw; +#endif +} MapItemStruct, *MapItem; + + +static RadarAttrConfig map_attrs[] = { + { RADAR_CONFIG_COLOR, "-color", NULL, + Tk_Offset(MapItemStruct, color), 0, RADAR_DRAW_FLAG, False }, + { RADAR_CONFIG_BOOL, "-composerotation", NULL, + Tk_Offset(MapItemStruct, header.flags), COMPOSE_ROTATION_BIT, + RADAR_COORDS_FLAG, False }, + { RADAR_CONFIG_BOOL, "-composescale", NULL, + Tk_Offset(MapItemStruct, header.flags), COMPOSE_SCALE_BIT, + RADAR_COORDS_FLAG, False }, + { RADAR_CONFIG_BOOL, "-filled", NULL, + Tk_Offset(MapItemStruct, filled), 1, RADAR_COORDS_FLAG, False }, + { RADAR_CONFIG_PATTERN, "-fillpattern", NULL, + Tk_Offset(MapItemStruct, fill_pattern), 0, RADAR_DRAW_FLAG, False }, + { RADAR_CONFIG_FONT, "-font", NULL, + Tk_Offset(MapItemStruct, text_font), 0, RADAR_COORDS_FLAG, False }, + { RADAR_CONFIG_MAP_INFO, "-mapinfo", NULL, + Tk_Offset(MapItemStruct, map_info_name), 0, + RADAR_COORDS_FLAG|RADAR_MAP_INFO_FLAG, False }, + { RADAR_CONFIG_PRI, "-priority", NULL, + Tk_Offset(MapItemStruct, header.priority), 0, + RADAR_DRAW_FLAG|RADAR_REPICK_FLAG, False }, + { RADAR_CONFIG_BOOL, "-sensitive", NULL, + Tk_Offset(MapItemStruct, header.flags), SENSITIVE_BIT, RADAR_REPICK_FLAG, False }, + { RADAR_CONFIG_PATTERNS, "-symbols", NULL, + Tk_Offset(MapItemStruct, symbol_patterns), 0, + RADAR_COORDS_FLAG, False }, + { RADAR_CONFIG_TAGS, "-tags", NULL, + Tk_Offset(MapItemStruct, header.tags), 0, 0, False }, + { RADAR_CONFIG_BOOL, "-visible", NULL, + Tk_Offset(MapItemStruct, header.flags), VISIBLE_BIT, + RADAR_DRAW_FLAG|RADAR_REPICK_FLAG|RADAR_VIS_FLAG, False }, + + { RADAR_CONFIG_END, NULL, NULL, 0, 0, 0 } +}; + + +void +UpdateMapInfo(ClientData client_data, + MapInfoId map_info) +{ + Item item = (Item) client_data; + + /*printf("updating a map 'cause of a change in mapinfo\n");*/ + ITEM.Invalidate(item, RADAR_COORDS_FLAG); +} + + +static void +FreeLists(MapItem map) +{ + if (map->vectors) { + RadarListFree(map->vectors); + } + map->vectors = NULL; + if (map->dashed_vectors) { + RadarListFree(map->dashed_vectors); + } + map->dashed_vectors = NULL; + if (map->dotted_vectors) { + RadarListFree(map->dotted_vectors); + } + map->dotted_vectors = NULL; + if (map->mixed_vectors) { + RadarListFree(map->mixed_vectors); + } + map->mixed_vectors = NULL; + + if (map->arcs) { + RadarListFree(map->arcs); + } + map->arcs = NULL; + if (map->dashed_arcs) { + RadarListFree(map->dashed_arcs); + } + map->dashed_arcs = NULL; + if (map->dotted_arcs) { + RadarListFree(map->dotted_arcs); + } + map->dotted_arcs = NULL; + if (map->mixed_arcs) { + RadarListFree(map->mixed_arcs); + } + map->mixed_arcs = NULL; + + if (map->marks) { + RadarListFree(map->marks); + } + map->marks = NULL; + + if (map->symbols) { + RadarListFree(map->symbols); + } + map->symbols = NULL; + + if (map->texts) { + RadarListFree(map->texts); + } + map->texts = NULL; +} + + +/* + ********************************************************************************** + * + * Init -- + * + ********************************************************************************** + */ +static int +Init(Item item, + int *argc, + Arg **args) +{ + MapItem map = (MapItem) item; + WidgetInfo *wi = item->wi; + + SET(item->flags, VISIBLE_BIT); + CLEAR(item->flags, SENSITIVE_BIT); + SET(item->flags, COMPOSE_ROTATION_BIT); + SET(item->flags, COMPOSE_SCALE_BIT); + item->part_sensitive = 0; + item->priority = DEFAULT_MAP_PRIORITY; + map->filled = False; + map->fill_pattern = RadarUnspecifiedPattern; + map->symbol_patterns = NULL; + map->color = RadarGetColorByValue(wi->win, wi->fore_color); + map->text_font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(wi->map_text_font)); + map->map_info_name = ""; + 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; + +#ifdef PERFOS + map->chrono_trans = NewChrono("Temps de transfo carte"); + map->chrono_draw = NewChrono("Temps de dessin carte"); + RazChronos(); +#endif + + return RADAR_OK; +} + + +/* + ********************************************************************************** + * + * Clone -- + * + ********************************************************************************** + */ + +static void +Clone(Item item) +{ + MapItem map = (MapItem) item; + WidgetInfo *wi = item->wi; + + if (map->vectors) { + map->vectors = RadarListDuplicate(map->vectors); + } + if (map->dashed_vectors) { + map->dashed_vectors = RadarListDuplicate(map->dashed_vectors); + } + if (map->dotted_vectors) { + map->dotted_vectors = RadarListDuplicate(map->dotted_vectors); + } + if (map->mixed_vectors) { + map->mixed_vectors = RadarListDuplicate(map->mixed_vectors); + } + + if (map->arcs) { + map->arcs = RadarListDuplicate(map->arcs); + } + if (map->dashed_arcs) { + map->dashed_arcs = RadarListDuplicate(map->dashed_arcs); + } + if (map->dotted_arcs) { + map->dotted_arcs = RadarListDuplicate(map->dotted_arcs); + } + if (map->mixed_arcs) { + map->mixed_arcs = RadarListDuplicate(map->mixed_arcs); + } + + if (map->marks) { + map->marks = RadarListDuplicate(map->marks); + } + + if (map->symbols) { + map->symbols = RadarListDuplicate(map->symbols); + } + + if (map->texts) { + map->texts = RadarListDuplicate(map->texts); + } + + if (strlen(map->map_info_name) != 0) { + char *text; + text = RadarMalloc((strlen(map->map_info_name) + 1) * sizeof(char)); + strcpy(text, map->map_info_name); + map->map_info_name = text; + map->map_info = Radar_GetMapInfo(wi->interp, map->map_info_name, + UpdateMapInfo, (ClientData) map); + } + + map->color = RadarGetColorByValue(wi->win, map->color); + map->text_font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(map->text_font)); + if (map->fill_pattern != RadarUnspecifiedPattern) { + map->fill_pattern = Tk_GetBitmap(wi->interp, wi->win, + Tk_NameOfBitmap(wi->dpy, map->fill_pattern)); + } + if (map->symbol_patterns) { + Pixmap *pats, *new_pats; + int i, num_pats; + + pats = (Pixmap *) RadarListArray(map->symbol_patterns); + num_pats = RadarListSize(map->symbol_patterns); + map->symbol_patterns = RadarListNew(num_pats, sizeof(Pixmap)); + new_pats = (Pixmap *) RadarListArray(map->symbol_patterns); + for (i = 0; i < num_pats; i++) { + new_pats[i] = Tk_GetBitmap(wi->interp, wi->win, + Tk_NameOfBitmap(wi->dpy, pats[i])); + } + } +} + + +/* + ********************************************************************************** + * + * Destroy -- + * Free the Map storage. + * + ********************************************************************************** + */ +static void +Destroy(Item item) +{ + MapItem map = (MapItem) item; + + FreeLists(map); + RadarFreeColor(map->color); + Tk_FreeFont(map->text_font); + if (map->fill_pattern != RadarUnspecifiedPattern) { + Tk_FreeBitmap(item->wi->dpy, map->fill_pattern); + } + if (map->symbol_patterns) { + Pixmap *pats; + int i, num_pats; + + pats = (Pixmap *) RadarListArray(map->symbol_patterns); + num_pats = RadarListSize(map->symbol_patterns); + for (i = 0; i < num_pats; i++) { + Tk_FreeBitmap(item->wi->dpy, pats[i]); + } + RadarListFree(map->symbol_patterns); + } + if (strlen(map->map_info_name) != 0) { + RadarFree(map->map_info_name); + } + if (map->map_info != NULL) { + Radar_FreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map); + } +} + + +/* + ********************************************************************************** + * + * Configure -- + * + ********************************************************************************** + */ +static int +Configure(Item item, + int argc, + RadarAttrList argv, + int *flags) +{ + WidgetInfo *wi = item->wi; + MapItem map = (MapItem) item; + + if (ITEM_P.ConfigureAttributes((char *) item, -1, argc, argv, flags) == RADAR_ERROR) { + return RADAR_ERROR; + } + + if (ISSET(*flags, RADAR_MAP_INFO_FLAG)) { + MapInfoId map_info; + RadarBool error = False; + + if (strlen(map->map_info_name) != 0) { + map_info = Radar_GetMapInfo(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) { + Radar_FreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map); + } + map->map_info = map_info; + } + else { + return RADAR_ERROR; + } + } + + return RADAR_OK; +} + + +/* + ********************************************************************************** + * + * Query -- + * + ********************************************************************************** + */ +static int +Query(Item item, + int argc, + RadarAttrList argv) +{ + if (ITEM_P.QueryAttribute((char *) item, -1, argv[0]) == RADAR_ERROR) { + return RADAR_ERROR; + } + + return RADAR_OK; +} + + +/* + ********************************************************************************** + * + * ComputeCoordinates -- + * + ********************************************************************************** + */ + +static void +ComputeCoordinates(Item item, + RadarBool force) +{ + WidgetInfo *wi = item->wi; + MapItem map = (MapItem) item; + MapInfoId map_info; + MapInfoLineStyle line_style; + int line_width; + MapInfoTextStyle 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; + RadarPoint *vectors, *dashed_vectors, *dotted_vectors; + RadarPoint *mixed_vectors, *marks; + XArc *arcs, *dashed_arcs, *dotted_arcs, *mixed_arcs; + RadarPoint *symbols, *texts; + RadarPoint from, to, center; + RadarPoint tmp_from, tmp_to; + XArc arc; + RadarBBox bbox, bbox_inter, radar_bbox; + int x_from_w, y_from_w, x_to_w, y_to_w; + int radius, start_angle, extend; + unsigned int radius_w; + MapInfoPoint new_marks; + unsigned int n_new_marks; + RadarFont text_font; + int sym_w2=0, sym_h2=0; + + ResetBBox(&item->item_bounding_box); + + if (map->map_info == NULL) { + return; + } + + radar_bbox.orig.x = radar_bbox.orig.y = 0; + radar_bbox.corner.x = wi->width; + radar_bbox.corner.y = wi->height; + + map_info = map->map_info; + +#ifdef PERFOS + StartUCChrono(map->chrono_trans); +#endif + + 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 = MapInfoNumLines(map_info); + for (i = 0; i < cnt; i++) { + MapInfoGetLine(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL); + switch (line_style) { + case MapInfoLineSimple: + num_points += 2; + break; + case MapInfoLineDashed: + num_dashed_points += 2; + break; + case MapInfoLineDotted: + num_dotted_points += 2; + break; + case MapInfoLineMixed: + num_mixed_points += 2; + break; + case MapInfoLineMarked: + num_points += 2; + MapInfoGetMarks(map_info, i, NULL, &n_new_marks); + num_marks += n_new_marks; + break; + } + } + + cnt = MapInfoNumTexts(map_info); + for (i = 0; i < cnt; i++) { + MapInfoGetText(map_info, i, NULL, &text_style, &line_style, NULL, NULL, NULL); + if (text_style == MapInfoUnderlinedText) { + switch (line_style) { + case MapInfoLineSimple: + case MapInfoLineMarked: + num_points += 2; + break; + case MapInfoLineDotted: + num_dotted_points += 2; + break; + case MapInfoLineMixed: + num_mixed_points += 2; + break; + case MapInfoLineDashed: + num_dashed_points += 2; + break; + } + } + } + + cnt = MapInfoNumArcs(map_info); + for (i = 0; i < cnt; i++) { + MapInfoGetArc(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL, NULL); + switch (line_style) { + case MapInfoLineSimple: + case MapInfoLineMarked: + num_arcs += 2; + break; + case MapInfoLineDotted: + num_dotted_arcs += 2; + break; + case MapInfoLineMixed: + num_mixed_arcs += 2; + break; + case MapInfoLineDashed: + 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 = RadarListNew(num_points, sizeof(RadarPoint)); + } + RadarListAssertSize(map->vectors, num_points); + if (!map->dashed_vectors) { + map->dashed_vectors = RadarListNew(num_dashed_points, sizeof(RadarPoint)); + } + RadarListAssertSize(map->dashed_vectors, num_dashed_points); + if (!map->dotted_vectors) { + map->dotted_vectors = RadarListNew(num_dotted_points, sizeof(RadarPoint)); + } + RadarListAssertSize(map->dotted_vectors, num_dotted_points); + if (!map->mixed_vectors) { + map->mixed_vectors = RadarListNew(num_mixed_points, sizeof(RadarPoint)); + } + RadarListAssertSize(map->mixed_vectors, num_mixed_points); + if (!map->arcs) { + map->arcs = RadarListNew(num_arcs, sizeof(XArc)); + } + RadarListAssertSize(map->arcs, num_arcs); + if (!map->dashed_arcs) { + map->dashed_arcs = RadarListNew(num_dashed_arcs, sizeof(XArc)); + } + RadarListAssertSize(map->dashed_arcs, num_dashed_arcs); + if (!map->dotted_arcs) { + map->dotted_arcs = RadarListNew(num_dotted_arcs, sizeof(XArc)); + } + RadarListAssertSize(map->dotted_arcs, num_dotted_arcs); + if (!map->mixed_arcs) { + map->mixed_arcs = RadarListNew(num_mixed_arcs, sizeof(XArc)); + } + RadarListAssertSize(map->mixed_arcs, num_mixed_arcs); + if (!map->marks) { + map->marks = RadarListNew(num_marks, sizeof(RadarPoint)); + } + RadarListAssertSize(map->marks, num_marks); + if (!map->symbols) { + map->symbols = RadarListNew(MapInfoNumSymbols(map_info), sizeof(RadarPoint)); + } + RadarListAssertSize(map->symbols, MapInfoNumSymbols(map_info)); + if (!map->texts) { + map->texts = RadarListNew(MapInfoNumTexts(map_info), sizeof(RadarPoint)); + } + RadarListAssertSize(map->texts, MapInfoNumTexts(map_info)); + + /* + * Ask the pointers to the actual arrays. + */ + vectors = (RadarPoint *) RadarListArray(map->vectors); + dashed_vectors = (RadarPoint *) RadarListArray(map->dashed_vectors); + dotted_vectors = (RadarPoint *) RadarListArray(map->dotted_vectors); + mixed_vectors = (RadarPoint *) RadarListArray(map->mixed_vectors); + arcs = (XArc *) RadarListArray(map->arcs); + dashed_arcs = (XArc *) RadarListArray(map->dashed_arcs); + dotted_arcs = (XArc *) RadarListArray(map->dotted_arcs); + mixed_arcs = (XArc *) RadarListArray(map->mixed_arcs); + marks = (RadarPoint *) RadarListArray(map->marks); + symbols = (RadarPoint *) RadarListArray(map->symbols); + texts = (RadarPoint *) RadarListArray(map->texts); + + if (num_marks && (wi->map_distance_symbol != RadarUnspecifiedPattern)) { + Tk_SizeOfBitmap(wi->dpy, 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, MapInfoNumTexts(map_info), MapInfoNumSymbols(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 = MapInfoNumLines(map_info); + for (i = 0; i < cnt; i++) { + MapInfoGetLine(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; + RadarTransformPoint(wi->current_transfo, &tmp_from, &from); + RadarTransformPoint(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 (LineInBBox(&from, &to, &radar_bbox) < 0) { + continue; + } + } + + switch (line_style) { + case MapInfoLineSimple: + vectors[num_points] = from; + num_points++; + vectors[num_points] = to; + num_points++; + break; + case MapInfoLineDashed: + if (!map->filled) { + dashed_vectors[num_dashed_points] = from; + num_dashed_points++; + dashed_vectors[num_dashed_points] = to; + num_dashed_points++; + } + break; + case MapInfoLineDotted: + if (!map->filled) { + dotted_vectors[num_dotted_points] = from; + num_dotted_points++; + dotted_vectors[num_dotted_points] = to; + num_dotted_points++; + } + break; + case MapInfoLineMixed: + if (!map->filled) { + mixed_vectors[num_mixed_points] = from; + num_mixed_points++; + mixed_vectors[num_mixed_points] = to; + num_mixed_points++; + } + break; + case MapInfoLineMarked: + if (!map->filled) { + vectors[num_points] = from; + num_points++; + vectors[num_points] = to; + num_points++; + if (wi->map_distance_symbol != RadarUnspecifiedPattern) { + MapInfoGetMarks(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 RadarPoint. + * Will use then RadarTransformPoints. + */ + tmp_from.x = new_marks[j].x; + tmp_from.y = new_marks[j].y; + RadarTransformPoint(wi->current_transfo, &tmp_from, &marks[num_marks]); + AddPointToBBox(&item->item_bounding_box, + marks[num_marks].x-sym_w2, marks[num_marks].y-sym_h2); + AddPointToBBox(&item->item_bounding_box, + marks[num_marks].x+sym_w2, marks[num_marks].x+sym_h2); + num_marks++; + } + } + } + break; + } + } + + cnt = MapInfoNumArcs(map_info); + for (i = 0; i < cnt; i++) { + RadarPoint xp; + + MapInfoGetArc(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; + RadarTransformPoint(wi->current_transfo, &tmp_from, ¢er); + tmp_from.x += radius_w; + tmp_from.y = 0; + RadarTransformPoint(wi->current_transfo, &tmp_from, &xp); + radius = 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; + } + + IntersectBBox(&radar_bbox, &bbox, &bbox_inter); + if (IsEmptyBBox(&bbox_inter)) { + continue; + } + + arc.x = center.x - radius; + arc.y = center.y - radius; + arc.width = 2 * radius; + arc.height = arc.width; + arc.angle1 = start_angle; + arc.angle2 = extend; + + switch (line_style) { + case MapInfoLineSimple: + case MapInfoLineMarked: + 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; + AddBBoxToBBox(&item->item_bounding_box, &bbox); + break; + case MapInfoLineDashed: + 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; + AddBBoxToBBox(&item->item_bounding_box, &bbox); + } + break; + case MapInfoLineDotted: + 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; + AddBBoxToBBox(&item->item_bounding_box, &bbox); + } + break; + case MapInfoLineMixed: + 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; + AddBBoxToBBox(&item->item_bounding_box, &bbox); + } + break; + } + } + + /* + * Truncate arc lists to the real size. + */ + RadarListAssertSize(map->arcs, num_arcs); + RadarListAssertSize(map->dashed_arcs, num_dashed_arcs); + RadarListAssertSize(map->dotted_arcs, num_dotted_arcs); + RadarListAssertSize(map->mixed_arcs, num_mixed_arcs); + +#ifdef PERFOS + StopUCChrono(map->chrono_trans); + PrintChronos(); + RazChronos(); +#endif + + /* If map is filled, only the vectors description is valid. */ + if (!map->filled) { + if (map->symbol_patterns) { + Pixmap sym, *syms = (Pixmap *) RadarListArray(map->symbol_patterns); + int num_syms = RadarListSize(map->symbol_patterns); + + cnt = MapInfoNumSymbols(map_info); + for (i = 0; i < cnt; i++) { + MapInfoGetSymbol(map_info, i, NULL, &x_from_w, &y_from_w, &symbol); + tmp_from.x = x_from_w; + tmp_from.y = y_from_w; + RadarTransformPoint(wi->current_transfo, &tmp_from, &symbols[i]); + sym = syms[symbol%num_syms]; + if (sym != RadarUnspecifiedPattern) { + Tk_SizeOfBitmap(wi->dpy, sym, &sym_w2, &sym_h2); + sym_w2 = (sym_w2+1)/2; + sym_h2 = (sym_h2+1)/2; + AddPointToBBox(&item->item_bounding_box, + symbols[i].x-sym_w2, symbols[i].y-sym_h2); + AddPointToBBox(&item->item_bounding_box, + symbols[i].x+sym_w2, symbols[i].y+sym_h2); + } + } + RadarListAssertSize(map->symbols, cnt); + } + + cnt = MapInfoNumTexts(map_info); + text_font = map->text_font ? map->text_font : wi->map_text_font; + for (i = 0; i < cnt; i++) { + MapInfoGetText(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; + RadarTransformPoint(wi->current_transfo, &tmp_from, &texts[i]); + AddStringToBBox(&item->item_bounding_box, text, text_font, + texts[i].x, texts[i].y); + + if (text_style == MapInfoUnderlinedText) { + GetStringBBox(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 MapInfoLineSimple: + case MapInfoLineMarked: + vectors[num_points] = from; + num_points++; + vectors[num_points] = to; + num_points++; + break; + case MapInfoLineDashed: + dashed_vectors[num_dashed_points] = from; + num_dashed_points++; + dashed_vectors[num_dashed_points] = to; + num_dashed_points++; + break; + case MapInfoLineDotted: + dotted_vectors[num_dotted_points] = from; + num_dotted_points++; + dotted_vectors[num_dotted_points] = to; + num_dotted_points++; + break; + case MapInfoLineMixed: + mixed_vectors[num_mixed_points] = from; + num_mixed_points++; + mixed_vectors[num_mixed_points] = to; + num_mixed_points++; + break; + } + } + } + RadarListAssertSize(map->texts, cnt); + } + + /* + * Truncate line lists to the real size. + */ + RadarListAssertSize(map->vectors, num_points); + RadarListAssertSize(map->dashed_vectors, num_dashed_points); + RadarListAssertSize(map->dotted_vectors, num_dotted_points); + RadarListAssertSize(map->mixed_vectors, num_mixed_points); + RadarListAssertSize(map->marks, num_marks); + + AddPointsToBBox(&item->item_bounding_box, + (RadarPoint *) RadarListArray(map->vectors), + RadarListSize(map->vectors)); + AddPointsToBBox(&item->item_bounding_box, + (RadarPoint *) RadarListArray(map->dashed_vectors), + RadarListSize(map->dashed_vectors)); + AddPointsToBBox(&item->item_bounding_box, + (RadarPoint *) RadarListArray(map->dotted_vectors), + RadarListSize(map->dotted_vectors)); + AddPointsToBBox(&item->item_bounding_box, + (RadarPoint *) RadarListArray(map->mixed_vectors), + RadarListSize(map->mixed_vectors)); +} + + +/* + ********************************************************************************** + * + * ToArea -- + * Tell if the object is entirely outside (-1), + * entirely inside (1) or in between (0). + * + ********************************************************************************** + */ + +static int +ToArea(Item item, + RadarBBox *area, + Tk_Uid tag_uid, + int enclosed, + RadarBool report) +{ + return -1; +} + + +/* + ********************************************************************************** + * + * Draw -- + * + ********************************************************************************** + */ + +static void +Draw(Item item) +{ + WidgetInfo *wi = item->wi; + MapItem map = (MapItem) item; + MapInfoId map_info; + RadarPoint *points; + XPoint *xpoints; + char *text; + char tmp_str[] = "."; + XGCValues values; + unsigned int i, cnt, tst = 0; + int line_width; + + if (map->map_info == NULL) { + return; + } + + map_info = map->map_info; + + values.foreground = RadarPixel(map->color); + + if (map->filled) { + if (RadarListSize(map->vectors) || RadarListSize(map->arcs)) { + if (map->fill_pattern == RadarUnspecifiedPattern) { /* Fill solid */ + values.fill_style = FillSolid; + XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values); + } + else { /* Fill stippled */ + values.fill_style = FillStippled; + values.stipple = map->fill_pattern; + XChangeGC(wi->dpy, wi->gc, + GCFillStyle | GCStipple | GCForeground, &values); + } + + cnt = RadarListSize(map->vectors); + if (cnt) { + xpoints = (XPoint *) alloca(cnt * sizeof(XPoint)); + points = (RadarPoint *) RadarListArray(map->vectors); + for (i = 0; i < cnt; i++) { + xpoints[i].x = points[i].x; + xpoints[i].y = points[i].y; + } + XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, cnt, + Nonconvex, CoordModeOrigin); + } + + if (RadarListSize(map->arcs)) { + XFillArcs(wi->dpy, wi->draw_buffer, wi->gc, + (XArc *) RadarListArray(map->arcs), RadarListSize(map->arcs)); + } + } + } + else { /* Not filled */ + +#ifdef PERFOS + StartUCChrono(map->chrono_draw); +#endif + if (RadarListSize(map->vectors)) { + SetLineStyle(wi->dpy, wi->gc, 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 *) RadarListArray(map->vectors), + RadarListSize(map->vectors)/2);*/ + cnt = RadarListSize(map->vectors); + points = (RadarPoint *) RadarListArray(map->vectors); + for (i = 0; i < cnt; i += 2) { + if (LineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) { + MapInfoGetLine(map_info, i/2, NULL, NULL, &line_width, NULL, + NULL, NULL, NULL); + 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, + points[i].x, points[i].y, points[i+1].x, points[i+1].y); + tst++; + } + } + } + + if (RadarListSize(map->dashed_vectors)) { + SetLineStyle(wi->dpy, wi->gc, 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 *) RadarListArray(map->dashed_vectors), RadarListSize(map->dashed_vectors)/2);*/ + cnt = RadarListSize(map->dashed_vectors); + points = (RadarPoint *) RadarListArray(map->dashed_vectors); + for (i = 0; i < cnt; i += 2) { + if (LineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) { + MapInfoGetLine(map_info, i/2, NULL, NULL, &line_width, NULL, NULL, NULL, NULL); + 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, + points[i].x, points[i].y, points[i+1].x, points[i+1].y); + tst++; + } + } + } + + if (RadarListSize(map->dotted_vectors)) { + SetLineStyle(wi->dpy, wi->gc, 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 *) RadarListArray(map->dotted_vectors), RadarListSize(map->dotted_vectors)/2);*/ + cnt = RadarListSize(map->dotted_vectors); + points = (RadarPoint *) RadarListArray(map->dotted_vectors); + for (i = 0; i < cnt; i += 2) { + if (LineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) { + MapInfoGetLine(map_info, i/2, NULL, NULL, &line_width, NULL, NULL, NULL, NULL); + 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, + points[i].x, points[i].y, points[i+1].x, points[i+1].y); + tst++; + } + } + } + + if (RadarListSize(map->mixed_vectors)) { + SetLineStyle(wi->dpy, wi->gc, 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 *) RadarListArray(map->mixed_vectors), RadarListSize(map->mixed_vectors)/2);*/ + cnt = RadarListSize(map->mixed_vectors); + points = (RadarPoint *) RadarListArray(map->mixed_vectors); + for (i = 0; i < cnt; i += 2) { + if (LineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) { + MapInfoGetLine(map_info, i/2, NULL, NULL, &line_width, NULL, NULL, NULL, NULL); + 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, + points[i].x, points[i].y, points[i+1].x, points[i+1].y); + tst++; + } + } + } + + if (RadarListSize(map->arcs)) { + + SetLineStyle(wi->dpy, wi->gc, LINE_SIMPLE); + values.fill_style = FillSolid; + values.line_width = 0; + XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values); + + /* !! WARNING !! XDrawArcs can't handle an unlimited number of arcs + in releases R4 and older */ + + XDrawArcs(wi->dpy, wi->draw_buffer, wi->gc, + (XArc *) RadarListArray(map->arcs), RadarListSize(map->arcs)); + } + + if (RadarListSize(map->dashed_arcs)) { + + SetLineStyle(wi->dpy, wi->gc, LINE_DASHED); + values.fill_style = FillSolid; + values.line_width = 0; + XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values); + + /* !! WARNING !! XDrawArcs can't handle an unlimited number of arcs + in releases R4 and older */ + + XDrawArcs(wi->dpy, wi->draw_buffer, wi->gc, + (XArc *) RadarListArray(map->dashed_arcs), + RadarListSize(map->dashed_arcs)); + } + + if (RadarListSize(map->dotted_arcs)) { + + SetLineStyle(wi->dpy, wi->gc, LINE_DOTTED); + values.fill_style = FillSolid; + values.line_width = 0; + XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values); + + /* !! WARNING !! XDrawArcs can't handle an unlimited number of arcs + in releases R4 and older */ + + XDrawArcs(wi->dpy, wi->draw_buffer, wi->gc, + (XArc *) RadarListArray(map->dotted_arcs), + RadarListSize(map->dotted_arcs)); + } + + if (RadarListSize(map->mixed_arcs)) { + + SetLineStyle(wi->dpy, wi->gc, LINE_MIXED); + values.fill_style = FillSolid; + values.line_width = 0; + XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values); + + /* !! WARNING !! XDrawArcs can't handle an unlimited number of arcs + in releases R4 and older */ + + XDrawArcs(wi->dpy, wi->draw_buffer, wi->gc, + (XArc *) RadarListArray(map->mixed_arcs), + RadarListSize(map->mixed_arcs)); + } + + if (RadarListSize(map->texts)) { + /* For the Tk widget we don't have to bother with old + * compatibility issues. + */ + values.font = RadarFontId(map->text_font); + values.fill_style = FillSolid; + XChangeGC(wi->dpy, wi->gc, + GCFillStyle | GCFont | GCForeground, &values); + + cnt = RadarListSize(map->texts); + points = (RadarPoint *) RadarListArray(map->texts); + for (i = 0; i < cnt; i++) { + MapInfoGetText(map_info, i, NULL, NULL, NULL, NULL, NULL, &text); + XDrawString(wi->dpy, wi->draw_buffer, wi->gc, + points[i].x, points[i].y, text, strlen(text)); + } + } + + if (RadarListSize(map->symbols) || RadarListSize(map->marks)) { + int w, h, ox, oy; + Pixmap sym; + + values.fill_style = FillStippled; + XChangeGC(wi->dpy, wi->gc, GCFillStyle, &values); + + if (map->symbol_patterns) { + Pixmap *syms = (Pixmap *) RadarListArray(map->symbol_patterns); + int num_syms = RadarListSize(map->symbol_patterns); + + cnt = RadarListSize(map->symbols); + points = (RadarPoint *) RadarListArray(map->symbols); + for (i = 0; i < cnt; i++) { + MapInfoGetSymbol(map_info, i, NULL, NULL, NULL, &(tmp_str[0])); + sym = syms[tmp_str[0]%num_syms]; + if (sym != RadarUnspecifiedPattern) { + Tk_SizeOfBitmap(wi->dpy, sym, &w, &h); + ox = points[i].x-w/2; + oy = points[i].y-h/2; + values.stipple = sym; + 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 != RadarUnspecifiedPattern) { + Tk_SizeOfBitmap(wi->dpy, wi->map_distance_symbol, &w, &h); + cnt = RadarListSize(map->marks); + points = (RadarPoint *) RadarListArray(map->marks); + values.stipple = wi->map_distance_symbol; + XChangeGC(wi->dpy, wi->gc, GCStipple, &values); + for (i = 0; i < cnt; i++) { + ox = points[i].x-w/2; + oy = 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); + } + } + } + } + +#ifdef PERFOS + StopUCChrono(map->chrono_draw); + PrintChronos(); + RazChronos(); +#endif +} + + +/* + ********************************************************************************** + * + * IsSensitive -- + * + ********************************************************************************** + */ +static RadarBool +IsSensitive(Item item, + int item_part) +{ + return (ISSET(item->flags, SENSITIVE_BIT) && + item->parent->class->IsSensitive(item->parent, RADAR_NO_PART)); +} + + +/* + ********************************************************************************** + * + * Pick -- + * 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(Item item, + RadarPoint *p, + Item start_item, + int aperture, + Item *a_item, + int *part) +{ + return 1e40; +} + + +/* + ********************************************************************************** + * + * Coords -- + * Nothing to do for maps (or too complex anyway). + * + ********************************************************************************** + */ +static int +Coords(Item item, + int index, + int cmd, + RadarPoint **pts, + int *num_pts) +{ + Tcl_AppendResult(item->wi->interp, + " maps doesn't support the coords command", NULL); + return RADAR_ERROR; +} + + +/* + ********************************************************************************** + * + * PostScript -- + * + ********************************************************************************** + */ +static void +PostScript(Item item, + PostScriptInfo ps_info) +{ +} + + +/* + ********************************************************************************** + * + * Exported functions struct -- + * + ********************************************************************************** + */ + +static ItemClassStruct MAP_ITEM_CLASS = { + sizeof(MapItemStruct), + False, + False, + False, + "map", + map_attrs, + Init, + Clone, + Destroy, + Configure, + Query, + NULL, + NULL, + NULL, + Coords, + ComputeCoordinates, + ToArea, + Draw, + IsSensitive, + Pick, + PostScript +}; + +RadarItemClassId RadarMap = (RadarItemClassId) &MAP_ITEM_CLASS; |