From fe1cd8467f46fa8208ab657f45099b721e3df15b Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Tue, 26 Feb 2008 16:53:36 +0200 Subject: [PATCH] Use a dynamicaly sized buffer pixmap --- src/map-download.c | 8 +- src/map-poi.c | 13 +-- src/map-poi.h | 3 +- src/map.c | 194 ++++++++++++++++++++++++++++----------------- src/map.h | 15 +--- src/track.c | 28 +++---- 6 files changed, 147 insertions(+), 114 deletions(-) diff --git a/src/map-download.c b/src/map-download.c index 77264c5..30d9ce0 100644 --- a/src/map-download.c +++ b/src/map-download.c @@ -151,7 +151,7 @@ while (_curl_multi && (msg = curl_multi_info_read(_curl_multi, &num_msgs))) { } /* Up to 1 transfer per tile. */ -while (num_transfers < (BUF_WIDTH_TILES * BUF_HEIGHT_TILES) && g_tree_nnodes(pui_tree)) { +while (num_transfers < (4*4) && g_tree_nnodes(pui_tree)) { ProgressUpdateInfo *pui; g_tree_foreach(pui_tree, (GTraverseFunc)get_next_pui, &pui); @@ -406,11 +406,9 @@ if (!pui->retries || g_file_test(pui->dest_str, G_FILE_TEST_EXISTS)) { guint tilex, tiley, tilex_end, tiley_end; for (tilex = pui->tilex << zoom_diff, tilex_end = tilex + (1 << zoom_diff); tilex < tilex_end; tilex++) { for (tiley = pui->tiley << zoom_diff, tiley_end = tiley + (1 << zoom_diff); tiley < tiley_end; tiley++) { - if ((tilex - _base_tilex) < BUF_WIDTH_TILES && (tiley - _base_tiley) < BUF_HEIGHT_TILES) { - map_render_tile(tilex, tiley, ((tilex - _base_tilex) << TILE_SIZE_P2), ((tiley - _base_tiley) << TILE_SIZE_P2), TRUE); + if (map_render_tile(tilex, tiley, ((tilex - _base_tilex) << TILE_SIZE_P2), ((tiley - _base_tiley) << TILE_SIZE_P2), TRUE)==TRUE) { map_render_data(); - gtk_widget_queue_draw_area - (_map_widget, + gtk_widget_queue_draw_area(_map_widget, ((tilex - _base_tilex) << TILE_SIZE_P2) - _offsetx, ((tiley - _base_tiley) << TILE_SIZE_P2) - _offsety, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS); diff --git a/src/map-poi.c b/src/map-poi.c index 318f2ee..cf5c68a 100644 --- a/src/map-poi.c +++ b/src/map-poi.c @@ -191,22 +191,23 @@ return found; * This should be done before rendering track data. */ void -map_render_all_pois(void) +map_render_all_pois(guint width, guint height) { -guint unitx, unity; -gdouble lat1, lat2, lon1, lon2; -gint poix, poiy; GdkPixbuf *pixbuf = NULL; GtkTreeIter iter; +guint unitx, unity; +gint poix, poiy; +gdouble lat1, lat2, lon1, lon2; gboolean valid; if (_poi_zoom <= _zoom) return; unitx = x2unit(0); -unity = y2unit(BUF_HEIGHT_PIXELS); +unity = y2unit(height); unit2latlon(unitx, unity, lat1, lon1); -unitx = x2unit(BUF_WIDTH_PIXELS); + +unitx = x2unit(width); unity = y2unit(0); unit2latlon(unitx, unity, lat2, lon2); diff --git a/src/map-poi.h b/src/map-poi.h index f16050c..72922be 100644 --- a/src/map-poi.h +++ b/src/map-poi.h @@ -30,7 +30,8 @@ gboolean map_poi_init(GtkWidget *map_widget); void map_poi_deinit(void); void map_render_poi(void); -gboolean map_poi_find_at_latlon(gdouble lat, gdouble lon, guint *poi_id); +void map_render_all_pois(guint width, guint height); void map_poi_cache_clear(void); +gboolean map_poi_find_at_latlon(gdouble lat, gdouble lon, guint *poi_id); #endif diff --git a/src/map.c b/src/map.c index a276d1a..6ee6c19 100644 --- a/src/map.c +++ b/src/map.c @@ -64,6 +64,17 @@ #define DEBUG_MAP_TIME 1 +/* Initial size */ +#define BUF_WIDTH_TILES (4) +#define BUF_HEIGHT_TILES (3) +#define BUF_WIDTH_PIXELS (1024) +#define BUF_HEIGHT_PIXELS (768) + +static guint buf_width_tiles=BUF_WIDTH_TILES; +static guint buf_height_tiles=BUF_HEIGHT_TILES; +static guint buf_width_pixels=BUF_WIDTH_PIXELS; +static guint buf_height_pixels=BUF_HEIGHT_PIXELS; + /** The "base tile" is the upper-left tile in the pixmap. */ guint _base_tilex = -5; guint _base_tiley = -5; @@ -104,6 +115,10 @@ static PangoContext *speed_context; static PangoLayout *speed_layout; static PangoFontDescription *speed_fontdesc; +#ifdef WITH_CAIRO +cairo_t *ct_pixmap; +#endif + static gint zoom_timeout_sid=0; static gint map_mode=0; static gboolean map_data_needs_refresh=FALSE; @@ -137,6 +152,7 @@ map_new(void) { GtkWidget *map_widget; +g_debug("MAP: new"); map_widget=gtk_drawing_area_new(); g_signal_connect_after(G_OBJECT(map_widget), "realize", G_CALLBACK(map_cb_after_realize), NULL); g_signal_connect(G_OBJECT(map_widget), "configure_event", G_CALLBACK(map_cb_configure), NULL); @@ -149,7 +165,7 @@ map_cb_after_realize(GtkWidget *map_widget, gpointer data) { GdkColor color; -_map_pixmap=gdk_pixmap_new(map_widget->window, BUF_WIDTH_PIXELS, BUF_HEIGHT_PIXELS, -1); +g_debug("MAP: after_realize"); scale_context=gtk_widget_get_pango_context(map_widget); scale_layout=pango_layout_new(scale_context); @@ -192,9 +208,32 @@ return TRUE; static gboolean map_cb_configure(GtkWidget *widget, GdkEventConfigure *event) { +guint tw, th; + +tw=TILE_SIZE_PIXELS*((widget->allocation.width/TILE_SIZE_PIXELS)+2); +th=TILE_SIZE_PIXELS*((widget->allocation.height/TILE_SIZE_PIXELS)+2); + +g_debug("MAP: configure %d %d -> (%d,%d)", widget->allocation.width, widget->allocation.height, tw, th); + +if (_map_pixmap==NULL) { + g_debug("Initial buffer pixmap"); + _map_pixmap=gdk_pixmap_new(widget->window, tw, th, -1); +} else { + if (tw>buf_width_pixels || th>buf_height_pixels) { + g_debug("Resize buffer pixmap"); + g_object_unref(_map_pixmap); + _map_pixmap=gdk_pixmap_new(widget->window, tw, th, -1); + map_force_redraw(); + } +} -_screen_width_pixels = _map_widget->allocation.width; -_screen_height_pixels = _map_widget->allocation.height; +buf_width_pixels=tw; +buf_height_pixels=th; +buf_width_tiles=buf_width_pixels/TILE_SIZE_PIXELS; +buf_height_tiles=buf_height_pixels/TILE_SIZE_PIXELS; + +_screen_width_pixels = widget->allocation.width; +_screen_height_pixels = widget->allocation.height; _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2; _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2; @@ -360,12 +399,17 @@ if (se==0) { return pixbuf; } -void +gboolean map_render_tile(guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail) { GdkPixbuf *pixbuf=NULL; gint zoff; +g_debug("MAP RT: %d %d %d %d (%d, %d)", tilex, tiley, destx, desty, buf_width_tiles, buf_height_tiles); + +if (destx > buf_width_pixels || desty > buf_height_pixels) + return FALSE; + if (tilex<_world_size_tiles && tiley<_world_size_tiles) { /* The tile is possible. */ for (zoff = (_curr_repo->double_size ? 1 : 0); !pixbuf && (_zoom + zoff) <= MAX_ZOOM && zoff <= TILE_SIZE_P2; zoff += 1) { @@ -391,9 +435,10 @@ if (tilex<_world_size_tiles && tiley<_world_size_tiles) { if (pixbuf) { gdk_draw_pixbuf(_map_pixmap, _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; + return TRUE; } gdk_draw_rectangle(_map_pixmap, _map_widget->style->black_gc, TRUE, destx, desty, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS); +return TRUE; } void @@ -406,7 +451,7 @@ if (map_drag_id>0) if (_home.valid) map_draw_position_icon(&_home); if(_show_poi) - map_render_all_pois(); + map_render_all_pois(buf_width_pixels, buf_height_pixels); if(_show_tracks>0) map_render_paths(); } @@ -424,8 +469,8 @@ gulong tms; g_timer_start(map_timer); #endif -for (new_y = 0; new_y < BUF_HEIGHT_TILES; ++new_y) - for (new_x = 0; new_x < BUF_WIDTH_TILES; ++new_x) { +for (new_y = 0; new_y < buf_height_tiles; ++new_y) + for (new_x = 0; new_x < buf_width_tiles; ++new_x) { map_render_tile(_base_tilex + new_x, _base_tiley + new_y, new_x * TILE_SIZE_PIXELS, @@ -511,7 +556,7 @@ if (new_base_tilex != _base_tilex || new_base_tiley != _base_tiley) { * new_y, old_x, old_y, iox, and ioy with that in mind. */ if (new_base_tiley < _base_tiley) { /* New is lower than old - start at bottom and go up. */ - new_y = BUF_HEIGHT_TILES - 1; + new_y = buf_height_tiles - 1; ioy = -1; } else { /* New is higher than old - start at top and go down. */ @@ -520,7 +565,7 @@ if (new_base_tilex != _base_tilex || new_base_tiley != _base_tiley) { } if (new_base_tilex < _base_tilex) { /* New is righter than old - start at right and go left. */ - base_new_x = BUF_WIDTH_TILES - 1; + base_new_x = buf_width_tiles - 1; iox = -1; } else { /* New is lefter than old - start at left and go right. */ @@ -533,13 +578,13 @@ if (new_base_tilex != _base_tilex || new_base_tiley != _base_tiley) { base_old_x = base_new_x + new_base_tilex - _base_tilex; _base_tilex = new_base_tilex; _base_tiley = new_base_tiley; - for (j = 0; j < BUF_HEIGHT_TILES; ++j, new_y += ioy, old_y += ioy) { + 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) { + 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) { + 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(_map_pixmap, _gc[COLORABLE_MARK], @@ -690,7 +735,7 @@ latlon2unit(pos->lat, pos->lon, x, y); x1=unit2bufx(x); y1=unit2bufy(y); -if ((x1 > BUF_WIDTH_PIXELS) || (y1 > BUF_HEIGHT_PIXELS)) +if ((x1 > buf_width_pixels) || (y1 > buf_height_pixels)) return; p=gdk_pixbuf_new_from_file(DATADIR "/pixmaps/mapper/home.png", NULL); @@ -733,41 +778,52 @@ if (_center_mode>0) * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK. */ void -map_render_segment(GdkGC * gc_norm, GdkGC * gc_alt, guint unitx1, guint unity1, guint unitx2, guint unity2) +map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt, guint unitx1, guint unity1, guint unitx2, guint unity2) { - if (!unity1) { - guint x2, y2; - x2 = unit2bufx(unitx2); - y2 = unit2bufy(unity2); - /* Make sure this circle will be visible. */ - if ((x2 < BUF_WIDTH_PIXELS) && (y2 < BUF_HEIGHT_PIXELS)) - gdk_draw_arc(_map_pixmap, gc_alt, FALSE, /* FALSE: not filled. */ - x2 - _draw_width, y2 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, /* start at 0 degrees. */ - 360 * 64); - } else if (!unity2) { - guint x1, y1; - x1 = unit2bufx(unitx1); - y1 = unit2bufy(unity1); - /* Make sure this circle will be visible. */ - if ((x1 < BUF_WIDTH_PIXELS) && ((unsigned)y1 < BUF_HEIGHT_PIXELS)) - gdk_draw_arc(_map_pixmap, gc_alt, FALSE, /* FALSE: not filled. */ - x1 - _draw_width, y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, /* start at 0 degrees. */ - 360 * 64); - } else { - gint x1, y1, x2, y2; - x1 = unit2bufx(unitx1); - y1 = unit2bufy(unity1); - x2 = unit2bufx(unitx2); - y2 = unit2bufy(unity2); - /* Make sure this line could possibly be visible. */ - if (!((x1 > BUF_WIDTH_PIXELS && x2 > BUF_WIDTH_PIXELS) - || (x1 < 0 && x2 < 0) - || (y1 > BUF_HEIGHT_PIXELS && y2 > BUF_HEIGHT_PIXELS) - || (y1 < 0 && y2 < 0))) - gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2); +if (!unity1) { + guint x2, y2; + + x2 = unit2bufx(unitx2); + y2 = unit2bufy(unity2); + /* Make sure this circle will be visible. */ + if ((x2 < buf_width_pixels) && (y2 < buf_height_pixels)) + gdk_draw_arc(_map_pixmap, gc_alt, FALSE, /* FALSE: not filled. */ + x2 - _draw_width, y2 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, /* start at 0 degrees. */ + 360 * 64); +} else if (!unity2) { + guint x1, y1; + + x1 = unit2bufx(unitx1); + y1 = unit2bufy(unity1); + /* Make sure this circle will be visible. */ + if ((x1 < buf_width_pixels) && ((unsigned)y1 < buf_height_pixels)) + gdk_draw_arc(_map_pixmap, gc_alt, FALSE, /* FALSE: not filled. */ + x1 - _draw_width, y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, /* start at 0 degrees. */ + 360 * 64); +} else { + gint x1, y1, x2, y2; + + x1 = unit2bufx(unitx1); + y1 = unit2bufy(unity1); + x2 = unit2bufx(unitx2); + y2 = unit2bufy(unity2); + /* Make sure this line could possibly be visible. */ + if (!((x1 > buf_width_pixels && x2 > buf_width_pixels) + || (x1 < 0 && x2 < 0) + || (y1 > buf_height_pixels && y2 > buf_height_pixels) + || (y1 < 0 && y2 < 0))) + gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2); } } +void +map_render_waypoint(guint x1, guint y1, GdkGC ** gc) +{ +if ((x1 > buf_width_pixels) || (y1 > buf_height_pixels)) + return; +gdk_draw_arc(_map_pixmap, gc[1], FALSE, x1 - _draw_width, y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, 360 * 64); +} + /** * Render all track data onto the _map_pixmap. Note that this does not * clear the pixmap of previous track data (use map_force_redraw() for @@ -778,34 +834,28 @@ map_render_segment(GdkGC * gc_norm, GdkGC * gc_alt, guint unitx1, guint unity1, void map_render_path(Path * path, GdkGC ** gc) { - Point *curr; - WayPoint *wcurr; - - /* gc is a pointer to the first GC to use (for plain points). (gc + 1) - * is a pointer to the GC to use for waypoints, and (gc + 2) is a pointer - * to the GC to use for breaks. */ - - /* else there is a route to draw. */ - for (curr = path->head, wcurr = path->whead; curr++ != path->tail;) { - /* Draw the line from (curr - 1) to (curr). */ - map_render_segment(gc[0], gc[2], - curr[-1].unitx, curr[-1].unity, curr->unitx, - curr->unity); - - /* Now, check if curr is a waypoint. */ - if (wcurr && wcurr <= path->wtail && wcurr->point == curr) { - guint x1 = unit2bufx(wcurr->point->unitx); - guint y1 = unit2bufy(wcurr->point->unity); - if ((x1 < BUF_WIDTH_PIXELS) - && (y1 < BUF_HEIGHT_PIXELS)) { - gdk_draw_arc(_map_pixmap, gc[1], FALSE, /* FALSE: not filled. */ - x1 - _draw_width, y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, /* start at 0 degrees. */ - 360 * 64); - } - wcurr++; - } +Point *curr; +WayPoint *wcurr; + +/* gc is a pointer to the first GC to use (for plain points). (gc + 1) + * is a pointer to the GC to use for waypoints, and (gc + 2) is a pointer + * to the GC to use for breaks. */ + +/* else there is a route to draw. */ +for (curr = path->head, wcurr = path->whead; curr++ != path->tail;) { + /* Draw the line from (curr - 1) to (curr). */ + map_render_segment(gc[0], gc[2], curr[-1].unitx, curr[-1].unity, curr->unitx, curr->unity); + + /* Now, check if curr is a waypoint. */ + if (wcurr && wcurr <= path->wtail && wcurr->point == curr) { + guint x1 = unit2bufx(wcurr->point->unitx); + guint y1 = unit2bufy(wcurr->point->unity); + + map_render_waypoint(x1, y1, _gc[COLORABLE_TRACK_BREAK]); + wcurr++; } } +} void map_render_paths(void) @@ -818,7 +868,7 @@ if ((_show_tracks & ROUTES_MASK) && _route.head != _route.tail) { guint x1 = unit2bufx(_next_way->point->unitx); guint y1 = unit2bufy(_next_way->point->unity); - if ((x1 < BUF_WIDTH_PIXELS) && (y1 < BUF_HEIGHT_PIXELS)) { + if ((x1 < buf_width_pixels) && (y1 < buf_height_pixels)) { /* Draw the next waypoint as a break. */ gdk_draw_arc(_map_pixmap, _gc[COLORABLE_ROUTE_BREAK], FALSE, /* FALSE: not filled. */ x1 - _draw_width, y1 - _draw_width, 4 * _draw_width, 4 * _draw_width, 0, /* start at 0 degrees. */ diff --git a/src/map.h b/src/map.h index f15df0e..9a223b1 100644 --- a/src/map.h +++ b/src/map.h @@ -28,18 +28,6 @@ #define TILE_SIZE_PIXELS (256) #define TILE_SIZE_P2 (8) -#ifdef WITH_DEVICE_770 -#define BUF_WIDTH_TILES (4) -#define BUF_HEIGHT_TILES (3) -#define BUF_WIDTH_PIXELS (1024) -#define BUF_HEIGHT_PIXELS (768) -#else -#define BUF_WIDTH_TILES (8) -#define BUF_HEIGHT_TILES (8) -#define BUF_WIDTH_PIXELS (2048) -#define BUF_HEIGHT_PIXELS (2048) -#endif - #define WORLD_SIZE_UNITS (2 << (MAX_ZOOM + TILE_SIZE_P2)) #define tile2grid(tile) ((tile) << 3) @@ -214,8 +202,9 @@ void map_pan(gint delta_unitx, gint delta_unity); void map_move_mark(void); void map_set_mark(GpsData *gps); void map_render_data(void); +gboolean map_render_tile(guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail); -void map_render_tile(guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail); +void map_render_waypoint(guint x1, guint y1, GdkGC ** gc); void map_center_unit(guint new_center_unitx, guint new_center_unity); void map_center_latlon(gdouble lat, gdouble lon); diff --git a/src/track.c b/src/track.c index d401ada..ad6317b 100644 --- a/src/track.c +++ b/src/track.c @@ -202,23 +202,17 @@ track_insert_break(void) if (_track.tail->unity) { guint x1, y1; -/* To mark a "waypoint" in a track, we'll add a (0, 0) point and then - * another instance of the most recent track point. */ -MACRO_PATH_INCREMENT_TAIL(_track); -*_track.tail=_point_null; -MACRO_PATH_INCREMENT_TAIL(_track); -*_track.tail=_track.tail[-2]; - -/* Instead of calling map_render_paths(), we'll just add the waypoint ourselves. */ -x1 = unit2bufx(_track.tail->unitx); -y1 = unit2bufy(_track.tail->unity); -/* Make sure this circle will be visible. */ -if ((x1 < BUF_WIDTH_PIXELS) && ((unsigned)y1 < BUF_HEIGHT_PIXELS)) - gdk_draw_arc(_map_pixmap, _gc[COLORABLE_TRACK_BREAK], FALSE, - x1 - _draw_width, y1 - _draw_width, - 2 * _draw_width, 2 * _draw_width, 0, - 360 * 64); - return TRUE; + /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then + * another instance of the most recent track point. */ + MACRO_PATH_INCREMENT_TAIL(_track); + *_track.tail=_point_null; + MACRO_PATH_INCREMENT_TAIL(_track); + *_track.tail=_track.tail[-2]; + + /* Instead of calling map_render_paths(), we'll just draw the waypoint ourselves. */ + x1 = unit2bufx(_track.tail->unitx); + y1 = unit2bufy(_track.tail->unity); + map_render_waypoint(x1, y1, _gc[COLORABLE_TRACK_BREAK]); } return FALSE; } -- 2.39.5