From 140e73083c5929efdb0566d9f1464e596013893b Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Wed, 30 Apr 2008 10:18:58 +0300 Subject: [PATCH] Copy over some more code --- src/gtkmap.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 2 deletions(-) diff --git a/src/gtkmap.c b/src/gtkmap.c index 6a8dd86..c16b639 100644 --- a/src/gtkmap.c +++ b/src/gtkmap.c @@ -184,6 +184,10 @@ enum { MAP_ZOOMED_IN, MAP_ZOOMED_OUT, + MAP_PANNED, + + MARKER_CLICK, + LAST_SIGNAL }; @@ -271,6 +275,8 @@ if (priv->gl_config) { } #endif +priv->buffer=NULL; + gtk_widget_set_extension_events(GTK_WIDGET(map), GDK_EXTENSION_EVENTS_ALL); gtk_widget_add_events(GTK_WIDGET(map), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -376,9 +382,11 @@ g_return_val_if_fail(event != NULL, FALSE); map=GTK_MAP(widget); priv=GTK_MAP_GET_PRIVATE(map); +g_return_val_if_fail(priv->buffer, FALSE); + style=widget->style; -gdk_draw_drawable(GDK_DRAWABLE(map->map), +gdk_draw_drawable(GDK_DRAWABLE(map), style->fg_gc[GTK_STATE_NORMAL], priv->buffer, event->area.x + priv->offsetx, @@ -565,6 +573,147 @@ do { while ((dest_dim >>= ratio_p2) > 1); } +static gboolean +gtk_map_render_tile(GtkWidget *widget, guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail) +{ +GtkMap *map; +GtkMapPriv *priv; +GdkPixbuf *pixbuf=NULL; +gint zoff; + +g_return_if_fail(GTK_IS_MAP(widget)); +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +g_return_val_if_fail(priv->buffer, FALSE); + +if (destx > priv->buf_width_pixels || desty > priv->buf_height_pixels) + return FALSE; + +if (tilex > priv->world_size_tiles || tiley > priv->world_size_tiles) + return FALSE; + +/* 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 = (_curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zoff) <= priv->max_zoom && zoff <= TILE_SIZE_P2; zoff += 1) { + pixbuf=gtk_map_tile_load(map, tilex, tiley, zoff, !fast_fail); + if (!pixbuf) { + if (!fast_fail) + fast_fail=TRUE; + } else { + /* Check if we need to blit. */ + if (zoff) { + gtk_map_pixbuf_scale_inplace(pixbuf, zoff, + (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff), + (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff)); + image_cache_invalidate_by_image(priv->icache, pixbuf); + } + } +} + +if (pixbuf) { + gdk_draw_pixbuf(priv->buffer, _gc[COLORABLE_MARK], pixbuf, 0, 0, destx, desty, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS, GDK_RGB_DITHER_NONE, 0, 0); + g_object_unref(pixbuf); + return TRUE; +} +gdk_draw_rectangle(priv->buffer, map->style->black_gc, TRUE, destx, desty, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS); +return TRUE; +} + +gboolean +gtk_map_set_center(GtkWidget *map, guint new_center_unitx, guint new_center_unity) +{ +GtkMap *map; +GtkMapPriv *priv; + +g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); + +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +gint new_base_tilex, new_base_tiley; +guint new_x, new_y; +guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy; + +/* Assure that _center.unitx/y are bounded. */ +BOUND(new_center_unitx, priv->min_center.unitx, priv->max_center.unitx); +BOUND(new_center_unity, priv->min_center.unity, priv->max_center.unity); + +priv->center.unitx = new_center_unitx; +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. */ + +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 + * don't overwrite the old parts when copying, so set up new_x, + * new_y, old_x, old_y, iox, and ioy with that in mind. */ + if (new_base_tiley < priv->base_tiley) { + /* New is lower than old - start at bottom and go up. */ + new_y = buf_height_tiles - 1; + ioy = -1; + } else { + /* New is higher than old - start at top and go down. */ + new_y = 0; + ioy = 1; + } + if (new_base_tilex < priv->base_tilex) { + /* New is righter than old - start at right and go left. */ + base_new_x = buf_width_tiles - 1; + iox = -1; + } else { + /* New is lefter than old - start at left and go right. */ + base_new_x = 0; + iox = 1; + } + + /* Iterate over the y tile values. */ + old_y = new_y + new_base_tiley - priv->base_tiley; + base_old_x = base_new_x + new_base_tilex - priv->base_tilex; + priv->base_tilex = new_base_tilex; + priv->base_tiley = new_base_tiley; + + for (j = 0; j < buf_height_tiles; ++j, new_y += ioy, old_y += ioy) { + new_x = base_new_x; + old_x = base_old_x; + /* Iterate over the x tile values. */ + for (k = 0; k < buf_width_tiles; ++k, new_x += iox, old_x += iox) { + /* Can we get this grid block from the old buffer?. */ + if (old_x >= 0 && old_x < buf_width_tiles && old_y >= 0 && old_y < buf_height_tiles) { + /* Copy from old buffer to new buffer. */ + gdk_draw_drawable(priv->buffer, + _gc[COLORABLE_MARK], + priv->buffer, + old_x * TILE_SIZE_PIXELS, + old_y * TILE_SIZE_PIXELS, + new_x * TILE_SIZE_PIXELS, + new_y * TILE_SIZE_PIXELS, + TILE_SIZE_PIXELS, + TILE_SIZE_PIXELS); + } else { + gtk_map_render_tile(map, new_base_tilex + new_x, + new_base_tiley + new_y, + new_x * TILE_SIZE_PIXELS, + new_y * TILE_SIZE_PIXELS, + map_drag_id!=0 ? TRUE : FALSE); + } + } + } + gtk_map_render_data(map); +} + +MACRO_RECALC_OFFSET(); +MACRO_RECALC_FOCUS_BASE(priv->center_ratio); + +gtk_map_set_mark(&_gps->data); +gtk_map_refresh(map); +} + void gtk_map_refresh(GtkWidget *widget) { @@ -576,7 +725,8 @@ map=GTK_MAP(widget); gtk_widget_queue_draw_area(widget, 0, 0, map->width, map->height); } -gint gtk_map_get_zoom(GtkWidget *map) +gint +gtk_map_get_zoom(GtkWidget *map) { GtkMap *map; GtkMapPriv *priv; @@ -589,6 +739,54 @@ priv=GTK_MAP_GET_PRIVATE(map); return priv->zoom; } +gboolean +gtk_map_set_zoom(GtkWidget *map, gint new_zoom) +{ +GtkMap *map; +GtkMapPriv *priv; + +g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); + +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +if (new_zoom > (priv->max_zoom - 1)) + return FALSE; + +if (new_zoom == priv->zoom) + return FALSE; + +priv->zoom = new_zoom / _curr_repo->view_zoom_steps * _curr_repo->view_zoom_steps; +priv->world_size_tiles = unit2tile(WORLD_SIZE_UNITS); + +/* If we're leading, update the center to reflect new zoom level. */ +MACRO_RECALC_CENTER(_gps->data, priv->center.unitx, priv->center.unity); + +/* Update center bounds to reflect new zoom level. */ +priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth)); +priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight)); +priv->max_center.unitx = WORLD_SIZE_UNITS - grid2unit(priv->screen_grids_halfwidth) - 1; +priv->max_center.unity = WORLD_SIZE_UNITS - grid2unit(priv->screen_grids_halfheight) - 1; + +BOUND(priv->center.unitx, priv->min_center.unitx, priv->max_center.unitx); +BOUND(priv->center.unity, priv->min_center.unity, priv->max_center.unity); + +priv->base_tilex = grid2tile((gint) pixel2grid((gint) unit2pixel((gint) priv->center.unitx)) - (gint) priv->screen_grids_halfwidth); +priv->base_tiley = grid2tile(pixel2grid(unit2pixel(priv->center.unity)) - priv->screen_grids_halfheight); + +/* New zoom level, so we can't reuse the old buffer's pixels. */ +/* Update state variables. */ +MACRO_RECALC_OFFSET(); +MACRO_RECALC_FOCUS_BASE(priv->center_ratio); +MACRO_RECALC_FOCUS_SIZE(priv->center_ratio); + +gtk_map_set_mark(&_gps->data); +gtk_map_refresh(map); + +return TRUE; +} + + gint gtk_map_zoom(GtkWidget *widget, gint zdir) { -- 2.39.5