/*
* Map.c -- Implementation of Map item.
*
* Authors : Patrick Lecoanet.
* Creation date :
*
* $Id: Map.c,v 1.63 2005/05/10 07:59:48 lecoanet Exp $
*/
/*
* Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
*
* See the file "Copyright" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "Types.h"
#include "MapInfo.h"
#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "WidgetInfo.h"
#include "tkZinc.h"
#include "Image.h"
#include <memory.h>
#include <stdio.h>
static const char rcsid[] = "$Id: Map.c,v 1.63 2005/05/10 07:59:48 lecoanet Exp $";
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;