From f0d04ede8e5a8b9ec243f535b0460e1f7ceed345 Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Fri, 2 May 2008 16:06:27 +0300 Subject: [PATCH] Some more map widget work --- src/gtkmap.c | 143 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 28 deletions(-) diff --git a/src/gtkmap.c b/src/gtkmap.c index 422858a..6b45832 100644 --- a/src/gtkmap.c +++ b/src/gtkmap.c @@ -17,6 +17,7 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -55,6 +56,10 @@ struct _GtkMapPriv /* Map image buffer */ GdkPixmap *buffer; +#ifdef WITH_CAIRO + cairo_t *ct; +#endif + PangoContext *context; PangoLayout *layout; PangoFontDescription *fontdesc; @@ -87,14 +92,14 @@ struct _GtkMapPriv GdkGLConfig* gl_config; #endif + GdkGC *gc_mark; + GdkGC *gc_velvec; + gint mark_x1; gint mark_x2; gint mark_y1; gint mark_y2; - gint mark_minx; - gint mark_miny; - gint mark_width; - gint mark_height; + GdkRectangle mark_rect; guint buf_width_tiles; guint buf_height_tiles; @@ -180,12 +185,15 @@ struct _GtkMapPriv #define unit2y(unit) (unit2pixel(unit) - tile2pixel(priv->base_tiley) - priv->offsety) #define y2unit(y) (pixel2unit(y + priv->offsety) + tile2unit(priv->base_tiley)) -#define leadx2unit (location->unitx + (priv->lead_ratio) * pixel2unit(priv->vel_offsetx)) -#define leady2unit (location->unity + (0.6f*priv->lead_ratio) * pixel2unit(priv->vel_offsety)) +#define leadx2unit (priv->location.unitx + (priv->lead_ratio) * pixel2unit(priv->vel_offsetx)) +#define leady2unit (priv->location.unity + (0.6f*priv->lead_ratio) * pixel2unit(priv->vel_offsety)) #define GTK_MAP_TILE_SIZE_PIXELS (256) #define GTK_MAP_TILE_SIZE_P2 (8) -#define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2)) + +/* #define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2)) */ + +#define GTK_MAP_WORLD_SIZE_UNITS (1<<31) /* Pans are done two "grids" at a time, or 64 pixels. */ #define GTK_MAP_PAN_UNITS (grid2unit(2)) @@ -193,8 +201,8 @@ struct _GtkMapPriv #define GTK_MAP_MACRO_RECALC_CENTER(center_unitx, center_unity) { \ switch(priv->center_mode) { \ case CENTER_LEAD: \ - priv->center.unitx = leadx2unit; \ - priv->center.unity = leady2unit; \ + priv->center.unitx = priv->leadx2unit; \ + priv->center.unity = priv->leady2unit; \ break; \ case CENTER_LATLON: \ priv->center.unitx = priv->location.unitx; \ @@ -207,14 +215,26 @@ struct _GtkMapPriv } \ }; -#define GTK_MAP_RECALC_OFFSET(center) { \ +#define GTK_MAP_MACRO_RECALC_OFFSET(center) { \ priv->offsetx = grid2pixel(unit2grid(center.unitx) - priv->screen_grids_halfwidth - tile2grid(priv->base_tilex)); \ priv->offsety = grid2pixel(unit2grid(center.unity) - priv->screen_grids_halfheight - tile2grid(priv->base_tiley)); \ } -#define GTK_MAP_RECALC_FOCUS_BASE(sens) { \ - priv->focus.unitx = x2unit(priv->screen_width_pixels * sens / 20); \ - priv->focus.unity = y2unit(priv->screen_height_pixels * sens / 20); \ +#define GTK_MAP_MACRO_RECALC_FOCUS_BASE { \ + priv->focus.unitx = x2unit(priv->screen_width_pixels * priv->center_ratio / 20); \ + priv->focus.unity = y2unit(priv->screen_height_pixels * priv->center_ratio / 20); \ +} + +#define GTK_MAP_MACRO_RECALC_FOCUS_SIZE { \ + priv->focus_unitwidth = pixel2unit((10 - priv->center_ratio) * priv->screen_width_pixels / 10); \ + priv->focus_unitheight = pixel2unit((10 - priv->center_ratio) * priv->screen_height_pixels / 10); \ +} + +#define GTK_MAP_MACRO_RECALC_CENTER_BOUNDS() { \ + priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth)); \ + priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight)); \ + priv->max_center.unitx = GTK_MAP_WORLD_SIZE_UNITS-grid2unit(priv->screen_grids_halfwidth) - 1; \ + priv->max_center.unity = GTK_MAP_WORLD_SIZE_UNITS-grid2unit(priv->screen_grids_halfheight) - 1; \ } #define BOUND(x, a, b) { \ @@ -233,6 +253,7 @@ static gboolean gtk_map_expose(GtkWidget *widget, GdkEventExpose *event); static gboolean gtk_map_configure(GtkWidget *widget, GdkEventConfigure *event); static void gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event); +static void gtk_map_draw_mark(GtkWidget *widget, GdkEventExpose *event); static gboolean gtk_map_update_buffer_size(GtkMap *map, gint new_width, gint new_height); @@ -288,9 +309,13 @@ gtk_map_init(GtkMap *map) GtkMapPriv *priv; GdkColor color; -g_debug("MAP: Init"); +g_debug("GTKMAP: Init"); priv=GTK_MAP_GET_PRIVATE(map); +#ifdef WITH_CAIRO +priv->ct=gdk_cairo_create(GTK_WIDGET(map)->window); +#endif + priv->zoom=3; priv->center_mode=CENTER_LATLON; priv->base_tilex=-5; @@ -386,8 +411,8 @@ priv->screen_grids_halfheight = pixel2grid(priv->screen_height_pixels) / 2; priv->scale_rect.x = (priv->screen_width_pixels - SCALE_WIDTH) / 2; priv->scale_rect.width = SCALE_WIDTH; -GTK_MAP_MACRO_RECALC_FOCUS_BASE(priv->center_ratio); -GTK_MAP_MACRO_RECALC_FOCUS_SIZE(priv->center_ratio); +GTK_MAP_MACRO_RECALC_FOCUS_BASE; +GTK_MAP_MACRO_RECALC_FOCUS_SIZE; priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth)); priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight)); @@ -530,16 +555,83 @@ gtk_map_paths_draw(widget, event); gtk_map_markers_draw(widget, event); -gtk_map_mark_draw(widget, event); - gtk_map_speed_draw(widget, event); #endif +gtk_map_mark_draw(widget, event); gtk_map_scale_draw(widget, event); return TRUE; } +static void +gtk_map_draw_mark(GtkWidget *widget, GdkEventExpose *event) +{ +GtkMap *map; +GtkMapPriv *priv; + +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +#if 0 +if (!priv->draw_mark) + return; +#endif + +if (!gdk_rectangle_intersect(&event->area, &priv->mark_rect, &event->area)) + return; + +#ifdef WITH_CAIRO +cairo_arc(priv->ct, priv->mark_x1, priv->marky1, priv->draw_width*2, 0, 2 * M_PI); +cairo_set_source_rgb(priv->ct, 1, 1, 1); +cairo_fill_preserve(priv->ct); +cairo_set_source_rgb(priv->ct, 0, 0, 0); +if (priv->show_velvec) { + cairo_save(priv->ct); + cairo_set_line_width(priv->ct, priv->draw_width); + cairo_move_to(priv->ct, priv->mark_x1, priv->marky1); + cairo_line_to(priv->ct, priv->mark_x2, priv->marky2); + cairo_restore(priv->ct); +} +cairo_stroke(priv->ct); +#else +gdk_draw_arc(widget->window, + priv->gc_mark, + FALSE, + priv->mark_x1 - priv->draw_width, + priv->mark_y1 - priv->draw_width, + 2 * priv->draw_width, + 2 * priv->draw_width, + 0, 360 * 64); + +if (priv->show_velvec) + gdk_draw_line(widget->window, + priv->gc_velvec, + priv->mark_x1, priv->mark_y1, + priv->mark_x2, priv->mark_y2); +#endif +} + +static void +gtk_map_calculate_mark(GtkWidget *widget) +{ +GtkMap *map; +GtkMapPriv *priv; + +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +priv->mark_x1 = unit2x(priv->location.unitx); +priv->mark_y1 = unit2y(priv->location.unity); +priv->mark_x2 = priv->mark_x1 + (priv->show_velvec ? priv->vel_offsetx : 0); +priv->mark_y2 = priv->mark_y1 + (priv->show_velvec ? priv->vel_offsety : 0); + +priv->mark_rect.x= = MIN(priv->mark_x1, priv->mark_x2) - (2 * priv->draw_width); +priv->mark_rect.y = MIN(priv->mark_y1, priv->mark_y2) - (2 * priv->draw_width); +priv->mark_rect.width = abs(priv->mark_x1 - priv->mark_x2) + (4 * priv->draw_width); +priv->mark_rect.height = abs(priv->mark_y1 - priv->mark_y2) + (4 * priv->draw_width); +} + static void gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event) { @@ -654,7 +746,7 @@ priv=GTK_MAP_GET_PRIVATE(map); if (priv->speed<0) return; -buffer=g_snprintf(buffer, sizeof(buffer), "%0.0f %s", priv->speed * priv->units_conv, priv->units_str); +g_snprintf(buffer, sizeof(buffer), "%0.0f %s", priv->speed * priv->units_conv, priv->units_str); map_information_text(10, 10, priv->speed_gc, buffer); } @@ -673,9 +765,7 @@ priv->speed=speed; } /** - * Do an in-place scaling of a pixbuf's pixels at the given ratio from the - * given source location. It would have been nice if gdk_pixbuf provided - * this method, but I guess it's not general-purpose enough. + * Do an in-place scaling of a pixbuf's pixels at the given ratio from the given source location. */ static void gtk_map_pixbuf_scale_inplace(GdkPixbuf *pixbuf, guint ratio_p2, guint src_x, guint src_y) @@ -751,7 +841,6 @@ if (tilex > priv->world_size_tiles || tiley > priv->world_size_tiles) /* g_debug("MAP RT: %u %u (%u) %u %u (%u, %u)", tilex, tiley, priv->world_size_tiles, destx, desty, buf_width_tiles, buf_height_tiles); */ -/* The tile is possible. */ for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zoff) <= priv->max_zoom && zoff <= GTK_MAP_TILE_SIZE_P2; zoff += 1) { pixbuf=gtk_map_tile_load(map, tilex, tiley, zoff, !fast_fail); if (!pixbuf) { @@ -761,8 +850,8 @@ for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zof /* Check if we need to blit. */ if (zoff) { gtk_map_pixbuf_scale_inplace(pixbuf, zoff, - (tilex - ((tilex >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff), - (tiley - ((tiley >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff)); + (tilex - ((tilex >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff), + (tiley - ((tiley >> zoff) << zoff)) << (GTK_MAP_TILE_SIZE_P2 - zoff)); image_cache_invalidate_by_image(priv->icache, pixbuf); } } @@ -813,8 +902,7 @@ priv->center.unity = new_center_unity; new_base_tilex = grid2tile((gint) pixel2grid((gint)unit2pixel((gint) priv->center.unitx)) - (gint)priv->screen_grids_halfwidth); new_base_tiley = grid2tile(pixel2grid(unit2pixel(priv->center.unity)) - priv->screen_grids_halfheight); -/* Same zoom level, so it's likely that we can reuse some of the old - * buffer's pixels. */ +/* Same zoom level, so it's likely that we can reuse some of the old buffer's pixels. */ if (new_base_tilex != priv->base_tilex || new_base_tiley != priv->base_tiley) { /* If copying from old parts to new parts, we need to make sure we @@ -954,7 +1042,6 @@ gtk_map_refresh(map); return TRUE; } - gint gtk_map_zoom(GtkWidget *widget, gint zdir) { -- 2.39.5