From 7d6ded3ba4081d002b4ae55f87b87cfc38dc76bf Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Tue, 12 Aug 2008 17:08:09 +0300 Subject: [PATCH] GObjectify tile repository thingy to TileRepo and adjust map widget and test code. Also move tile loading from map widget to TileRepo --- libs/libgtkmap/gtkmap.c | 114 ++++++---------- libs/libgtkmap/gtkmap.h | 3 +- libs/libgtkmap/map-widget-test.c | 4 +- libs/libgtkmap/tilerepo.c | 214 +++++++++++++++++++++++-------- libs/libgtkmap/tilerepo.h | 57 +++++++- 5 files changed, 251 insertions(+), 141 deletions(-) diff --git a/libs/libgtkmap/gtkmap.c b/libs/libgtkmap/gtkmap.c index 050a49f..2dd76b9 100644 --- a/libs/libgtkmap/gtkmap.c +++ b/libs/libgtkmap/gtkmap.c @@ -42,8 +42,6 @@ #endif #include "tilerepo.h" - -#include "image-cache.h" #include "latlon.h" #include "gtkmap.h" @@ -59,9 +57,6 @@ #define MARKER_FONT_SIZE_BIG (10) #define MARKER_FONT_SIZE_SMALL (8) -/* Filename buffer */ -#define BUFFER_SIZE (2048) - #define SCALE_WIDTH (256) #define MAP_CACHE_DEFAULT (64) @@ -128,10 +123,9 @@ struct _GtkMapPriv guint center_mark_size; GdkRectangle center_rect; - RepoData *curr_repo; + TileRepo *curr_repo; GTimer *timer; - ImageCache *icache; GSList *markers; GtkListStore *marker_store; @@ -565,8 +559,6 @@ priv->units_conv=1.85200; priv->center_mark_size=8; -priv->icache=image_cache_new(64); - priv->show_scale=TRUE; priv->show_velvec=TRUE; priv->show_markers=TRUE; @@ -1826,77 +1818,38 @@ do { while ((dest_dim >>= ratio_p2) > 1); } -static GdkPixbuf * -gtk_map_tile_load(GtkWidget *widget, guint tilex, guint tiley, gint zoff, gboolean fast_fail) + +/** + * gtk_map_set_tile_repository: + * + * Set the map bitmap tile repository object to use. The map does not in itself + * handle downloading of loading of bitmaps. The repository object does that. + * + */ +void +gtk_map_set_tile_repository(GtkWidget *widget, TileRepo *rd) { GtkMap *map; GtkMapPriv *priv; -GdkPixbuf *pixbuf; -GError *error = NULL; -gchar buffer[BUFFER_SIZE]; -gchar key[BUFFER_SIZE]; -struct stat tstat; -gint se; -g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); +g_return_if_fail(GTK_IS_MAP(widget)); map=GTK_MAP(widget); priv=GTK_MAP_GET_PRIVATE(map); -g_snprintf(buffer, sizeof(buffer), "%s/%u/%u/%u.jpg", priv->curr_repo->cache_dir, priv->zoom + zoff, (tilex >> zoff), (tiley >> zoff)); -g_snprintf(key, sizeof(key), "%s/%u/%u/%u", priv->curr_repo->cache_dir, priv->zoom + zoff, (tilex >> zoff), (tiley >> zoff)); - -g_debug("LOAD: %u, %u @ (%d+%d): %s", tilex, tiley, priv->zoom, zoff, buffer); - -pixbuf=image_cache_get(priv->icache, key, buffer); -if (!pixbuf) { - g_unlink(buffer); -#if 0 - if (_auto_download && _curr_repo->type != REPOTYPE_NONE && !((_zoom + zoff - (_curr_repo->double_size ? 1 : 0)) % _curr_repo->dl_zoom_steps)) { - if (download) - map_initiate_download(tilex >> zoff, tiley >> zoff, _zoom + zoff, -INITIAL_DOWNLOAD_RETRIES); - } -#endif - return NULL; -} - -g_object_ref(pixbuf); - -#if 0 -/* Check if we need to trim. */ -if (gdk_pixbuf_get_width(pixbuf) != TILE_SIZE_PIXELS || gdk_pixbuf_get_height(pixbuf) != TILE_SIZE_PIXELS) - pixbuf=pixbuf_trim(pixbuf); -#endif +g_return_if_fail(rd); -#if 0 -/* Check tile age, if file date is ower a week old, redownload if autodownload enabled */ -se=stat(buffer, &tstat); -if (se==0) { - time_t t; - t=time(NULL); - if (t-tstat.st_mtime>TILE_MAX_AGE) { - if (_auto_download && _curr_repo->type != REPOTYPE_NONE && !((_zoom + zoff - (_curr_repo->double_size ? 1 : 0)) % _curr_repo->dl_zoom_steps)) { - if (download) { - g_debug("Tile: %s is old, re-downloading\n", buffer); - map_initiate_download(tilex >> zoff, tiley >> zoff, _zoom + zoff, -INITIAL_DOWNLOAD_RETRIES); - image_cache_invalidate(map_ic, key); - } - } - } -} -#endif +priv->curr_repo=rd; -return pixbuf; +gtk_map_refresh(widget); } /** - * gtk_map_set_tile_repository: - * - * Set the map bitmap tile repository object to use. The map does not in itself - * handle downloading of loading of bitmaps. The repository object does that. + * gtk_map_get_tile_reposotory: * + * Get the active map tile repository object. */ -void -gtk_map_set_tile_repository(GtkWidget *widget, RepoData *rd) +TileRepo * +gtk_map_get_tile_repository(GtkWidget *widget) { GtkMap *map; GtkMapPriv *priv; @@ -1905,13 +1858,21 @@ g_return_if_fail(GTK_IS_MAP(widget)); map=GTK_MAP(widget); priv=GTK_MAP_GET_PRIVATE(map); -g_return_if_fail(rd); +return priv->curr_repo; +} -priv->curr_repo=rd; +static void +gtk_map_render_empty_tile(GtkWidget *widget, guint destx, guint desty) +{ +GtkMap *map; +GtkMapPriv *priv; -gtk_map_refresh(widget); -} +g_return_val_if_fail(GTK_IS_MAP(widget), FALSE); +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); +gdk_draw_rectangle(priv->buffer, widget->style->black_gc, TRUE, destx, desty, GTK_MAP_TILE_SIZE_PIXELS, GTK_MAP_TILE_SIZE_PIXELS); +} /** * gtk_map_render_tile: @@ -1944,7 +1905,11 @@ g_debug("RT: %u %u (%u) %u %u (%u, %u)", tilex, tiley, priv->world_size_tiles, destx, desty, priv->buf_width_tiles, priv->buf_height_tiles); g_return_val_if_fail(priv->buffer, FALSE); -g_return_val_if_fail(priv->curr_repo, FALSE); + +if (priv->curr_repo==NULL) { + gtk_map_render_empty_tile(widget, destx, desty); + return FALSE; +} if (destx > priv->buf_width_pixels || desty > priv->buf_height_pixels) return FALSE; @@ -1953,7 +1918,7 @@ if (tilex > priv->world_size_tiles || tiley > priv->world_size_tiles) return FALSE; 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(GTK_WIDGET(map), tilex, tiley, zoff, !fast_fail); + pixbuf=tile_repo_load(priv->curr_repo, tilex, tiley, priv->zoom, zoff, !fast_fail); if (!pixbuf) { if (!fast_fail) fast_fail=TRUE; @@ -1963,7 +1928,6 @@ for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zof 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)); - image_cache_invalidate_by_image(priv->icache, pixbuf); } } } @@ -1976,7 +1940,7 @@ if (pixbuf) { return TRUE; } -gdk_draw_rectangle(priv->buffer, widget->style->black_gc, TRUE, destx, desty, GTK_MAP_TILE_SIZE_PIXELS, GTK_MAP_TILE_SIZE_PIXELS); +gtk_map_render_empty_tile(widget, destx, desty); return FALSE; } @@ -2487,7 +2451,7 @@ map=GTK_MAP(widget); priv=GTK_MAP_GET_PRIVATE(map); if (cache_size>512) cache_size=512; -image_cache_set_size(priv->icache, cache_size); +/* XXX Set repo cache size */ } /******************************************************************************/ diff --git a/libs/libgtkmap/gtkmap.h b/libs/libgtkmap/gtkmap.h index 78be206..993599a 100644 --- a/libs/libgtkmap/gtkmap.h +++ b/libs/libgtkmap/gtkmap.h @@ -123,7 +123,8 @@ GtkWidget* gtk_map_new(void); void gtk_map_refresh(GtkWidget *map); /* Map repository handling */ -void gtk_map_set_tile_repository(GtkWidget *map, RepoData *rd); +void gtk_map_set_tile_repository(GtkWidget *map, TileRepo *rd); +TileRepo *gtk_map_get_tile_repository(GtkWidget *map); /* Markers */ gboolean gtk_map_markers_add(GtkWidget *map, GtkMapMarkerType type, GtkListStore *store); diff --git a/libs/libgtkmap/map-widget-test.c b/libs/libgtkmap/map-widget-test.c index 54ab216..a941058 100644 --- a/libs/libgtkmap/map-widget-test.c +++ b/libs/libgtkmap/map-widget-test.c @@ -67,7 +67,7 @@ main (int argc, char **args) GtkWidget *window, *wvbox; GtkWidget *hbox, *zoomer, *btn_left, *btn_right, *btn_up, *btn_down, *vbox; GtkWidget *rotate; -RepoData *rd; +TileRepo *rd; gint t; gdouble slat, slon; @@ -83,7 +83,7 @@ gtk_window_resize(GTK_WINDOW(window), 800, 600); wvbox=gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(window), wvbox); -rd=map_tile_repo_new(); +rd=tile_repo_new(); rd->view_zoom_steps=1; rd->cache_dir=TESTREPO; diff --git a/libs/libgtkmap/tilerepo.c b/libs/libgtkmap/tilerepo.c index 5b64c54..7c2ad34 100644 --- a/libs/libgtkmap/tilerepo.c +++ b/libs/libgtkmap/tilerepo.c @@ -1,7 +1,7 @@ /* * This file is part of mapper * - * Copyright (C) 2007 Kaj-Michael Lang + * Copyright (C) 2007-2008 Kaj-Michael Lang * Copyright (C) 2006-2007 John Costigan. * * This program is free software; you can redistribute it and/or modify @@ -22,38 +22,77 @@ #include #include #include +#include + #include +#include #include "tilerepo.h" +#include "image-cache.h" + +G_DEFINE_TYPE(TileRepo, tile_repo, G_TYPE_OBJECT); + +/* Filename buffer */ +#define BUFFER_SIZE (2048) + +#if 0 +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TILE_REPO_TYPE, TileRepoPrivate)) +#endif + +static void +tile_repo_dispose(GObject *object) +{ +G_OBJECT_CLASS(tile_repo_parent_class)->dispose(object); +} + +static void +tile_repo_finalize(GObject *object) +{ +TileRepo *tr=TILE_REPO(object); +} + +static void +tile_repo_class_init(TileRepoClass *klass) +{ +GObjectClass *object_class=G_OBJECT_CLASS(klass); + +object_class->dispose=tile_repo_dispose; +object_class->finalize=tile_repo_finalize; +} /** - * map_tile_repo_new: + * tile_repo_new: * - * Create a new empty Map image tile repository structure. + * Create a new empty Map image tile repository. * */ -RepoData * -map_tile_repo_new(void) +TileRepo * +tile_repo_new(void) { -RepoData *rd; -rd=g_new0(RepoData, 1); -rd->min_zoom=0; -rd->max_zoom=17; -return rd; +return g_object_new(TILE_REPO_TYPE, NULL); +} + +static void +tile_repo_init(TileRepo *tr) +{ +tr->min_zoom=0; +tr->max_zoom=17; +tr->view_zoom_steps=1; +tr->icache=image_cache_new(64); } /** - * map_tile_repo_new_from_string: + * tile_repo_new_from_string: * @str * * Create a new Map image tile repository structure by filling in values from given configuration string. * */ -RepoData * -map_tile_repo_new_from_string(gchar *str) +TileRepo * +tile_repo_new_from_string(gchar *str) { gchar *token, *error_check; -RepoData *rd; +TileRepo *tr; /* Parse each part of a repo, delimited by newline characters: * 1. name @@ -63,93 +102,156 @@ RepoData *rd; * 5. view_zoom_steps */ -rd=map_tile_repo_new(); +tr=tile_repo_new(); +g_return_val_if_fail(tr, NULL); /* Parse name. */ -token = strsep(&str, "\n\t"); +token=strsep(&str, "\n\t"); if (token) - rd->name = g_strdup(token); + tr->name = g_strdup(token); /* Parse URL format. */ -token = strsep(&str, "\n\t"); +token=strsep(&str, "\n\t"); if (token) - rd->url = g_strdup(token); + tr->url = g_strdup(token); /* Parse cache dir. */ -token = strsep(&str, "\n\t"); +token=strsep(&str, "\n\t"); if (token) - rd->cache_dir = gnome_vfs_expand_initial_tilde(token); + tr->cache_dir=gnome_vfs_expand_initial_tilde(token); /* Parse download zoom steps. */ -token = strsep(&str, "\n\t"); -if (!token || !*token || !(rd->dl_zoom_steps = atoi(token))) - rd->dl_zoom_steps = 1; +token=strsep(&str, "\n\t"); +if (!token || !*token || !(tr->dl_zoom_steps=atoi(token))) + tr->dl_zoom_steps=1; /* Parse view zoom steps. */ -token = strsep(&str, "\n\t"); -if (!token || !*token || !(rd->view_zoom_steps = atoi(token))) - rd->view_zoom_steps = 1; +token=strsep(&str, "\n\t"); +if (!token || !*token || !(tr->view_zoom_steps=atoi(token))) + tr->view_zoom_steps=1; /* Parse double-size. */ -token = strsep(&str, "\n\t"); +token=strsep(&str, "\n\t"); if (token) - rd->double_size = atoi(token); /* Default is zero (FALSE) */ + tr->double_size=atoi(token); /* Default is zero (FALSE) */ /* Parse next-able. */ token = strsep(&str, "\n\t"); -if (!token || !*token || (rd->nextable = strtol(token, &error_check, 10), token == str)) - rd->nextable = TRUE; +if (!token || !*token || (tr->nextable=strtol(token, &error_check, 10), token == str)) + tr->nextable = TRUE; -map_tile_repo_set_type(rd); -return rd; +tile_repo_set_type(tr); +return tr; } /** - * map_tile_repo_free: - * @rd + * tile_repo_free: + * @tr * * Free a map image tile repository */ void -map_tile_repo_free(RepoData *rd) +tile_repo_free(TileRepo *tr) { -if (rd->name) - g_free(rd->name); -if (rd->url) - g_free(rd->url); -if (rd->cache_dir) - g_free(rd->cache_dir); - -g_free(rd); +g_return_if_fail(tr); +if (tr->name) + g_free(tr->name); +if (tr->url) + g_free(tr->url); +if (tr->cache_dir) + g_free(tr->cache_dir); +if (tr->icache) + image_cache_free(tr->icache); + +g_object_unref(tr); } void -map_tile_repo_set_type(RepoData *rd) +tile_repo_set_type(TileRepo *tr) { -if (rd->url && *rd->url) { - gchar *url = g_utf8_strdown(rd->url, -1); +g_return_if_fail(tr); + +if (tr->url && *tr->url) { + gchar *url = g_utf8_strdown(tr->url, -1); /* Determine type of repository. */ if (strstr(url, "service=wms")) - rd->type = REPOTYPE_WMS; + tr->type = REPOTYPE_WMS; else if (strstr(url, "%s")) - rd->type = REPOTYPE_QUAD_QRST; + tr->type = REPOTYPE_QUAD_QRST; else if (strstr(url, "%0d")) - rd->type = REPOTYPE_XYZ_INV; + tr->type = REPOTYPE_XYZ_INV; else if (strstr(url, "%0s")) - rd->type = REPOTYPE_QUAD_ZERO; + tr->type = REPOTYPE_QUAD_ZERO; else - rd->type = REPOTYPE_XYZ; + tr->type = REPOTYPE_XYZ; g_free(url); } else - rd->type = REPOTYPE_NONE; + tr->type = REPOTYPE_NONE; } gboolean -map_tile_repo_make_cache_dir(RepoData *rd) +tile_repo_make_cache_dir(TileRepo *tr) { -if (g_mkdir_with_parents(rd->cache_dir, 0755)) +if (g_mkdir_with_parents(tr->cache_dir, 0755)) return FALSE; -return g_file_test(rd->cache_dir, G_FILE_TEST_EXISTS); +return g_file_test(tr->cache_dir, G_FILE_TEST_EXISTS); } + +GdkPixbuf * +tile_repo_load(TileRepo *tr, guint tilex, guint tiley, gint zoom, gint zoff, gboolean fast_fail) +{ +GdkPixbuf *pixbuf; +GError *error = NULL; +gchar buffer[BUFFER_SIZE]; +gchar key[BUFFER_SIZE]; +struct stat tstat; +gint se; + +g_snprintf(buffer, sizeof(buffer), "%s/%u/%u/%u.jpg", tr->cache_dir, zoom + zoff, (tilex >> zoff), (tiley >> zoff)); +g_snprintf(key, sizeof(key), "%s/%u/%u/%u", tr->cache_dir, zoom + zoff, (tilex >> zoff), (tiley >> zoff)); + +g_debug("LOAD: %u, %u @ (%d+%d): %s", tilex, tiley, zoom, zoff, buffer); + +pixbuf=image_cache_get(tr->icache, key, buffer); +if (!pixbuf) { + g_unlink(buffer); +#if 0 + if (tr->auto_download && tr->type!=REPOTYPE_NONE && !((zoom + zoff - (tr->double_size ? 1 : 0)) % tr->dl_zoom_steps)) { + if (download) + tile_repo_initiate_download(tilex >> zoff, tiley >> zoff, zoom + zoff, -INITIAL_DOWNLOAD_RETRIES); + } +#endif + return NULL; +} + +g_object_ref(pixbuf); + +#if 0 +/* Check if we need to trim. */ +if (gdk_pixbuf_get_width(pixbuf) != TILE_SIZE_PIXELS || gdk_pixbuf_get_height(pixbuf) != TILE_SIZE_PIXELS) + pixbuf=pixbuf_trim(pixbuf); +#endif + +#if 0 +/* Check tile age, if file date is ower a week old, redownload if autodownload enabled */ +se=stat(buffer, &tstat); +if (se==0 && tr->auto_update) { + time_t t; + t=time(NULL); + if (t-tstat.st_mtime>tr->tile_max_age) { + if (tr->auto_download && tr->type!=REPOTYPE_NONE && !((zoom + zoff - (tr->double_size ? 1 : 0)) % tr->dl_zoom_steps)) { + if (download) { + g_debug("Tile: %s is old, re-downloading\n", buffer); + tile_repo_initiate_download(tilex >> zoff, tiley >> zoff, _zoom + zoff, -INITIAL_DOWNLOAD_RETRIES); + image_cache_invalidate(map_ic, key); + } + } + } +} +#endif + +return pixbuf; +} + diff --git a/libs/libgtkmap/tilerepo.h b/libs/libgtkmap/tilerepo.h index 0102cc4..5478349 100644 --- a/libs/libgtkmap/tilerepo.h +++ b/libs/libgtkmap/tilerepo.h @@ -1,9 +1,41 @@ +/* + * This file is part of mapper + * + * Copyright (C) 2007-2008 Kaj-Michael Lang + * Copyright (C) 2006-2007 John Costigan. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #ifndef _MAP_TILE_REPO_H #define _MAP_TILE_REPO_H #include #include +#include "image-cache.h" + +G_BEGIN_DECLS + +#define TILE_REPO_TYPE (tile_repo_get_type ()) +#define TILE_REPO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TILE_REPO_TYPE, TileRepo)) +#define TILE_REPO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TILE_REPO_TYPE, TileRepoClass)) +#define IS_TILE_REPO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TILE_REPO_TYPE)) +#define IS_TILE_REPO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TILE_REPO_TYPE)) +#define TILE_REPO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TILE_REPO_TYPE, TileRepoClass)) + /** This enumerated type defines the supported types of repositories. */ typedef enum { REPOTYPE_NONE, /* No URL set. */ @@ -14,9 +46,10 @@ typedef enum { REPOTYPE_WMS /* "service=wms" */ } RepoType; -/** Data regarding a map repository. */ -typedef struct _RepoData RepoData; -struct _RepoData { +typedef struct _TileRepo TileRepo; +struct _TileRepo { + GObject parent; + /* */ gchar *name; gchar *url; gchar *cache_dir; @@ -26,13 +59,23 @@ struct _RepoData { guint max_zoom; gboolean double_size; gboolean nextable; + ImageCache *icache; RepoType type; GtkWidget *menu_item; }; -RepoData *map_tile_repo_new(void); -RepoData *map_tile_repo_new_from_string(gchar *str); -void map_tile_repo_free(RepoData *rd); -void map_tile_repo_set_type(RepoData *rd); +/** Data regarding a map repository. */ +typedef struct _TileRepoClass TileRepoClass; +struct _TileRepoClass { + GObjectClass parent; +}; + +TileRepo *tile_repo_new(void); +TileRepo *tile_repo_new_from_string(gchar *str); +void tile_repo_free(TileRepo *tr); +void tile_repo_set_type(TileRepo *tr); +GdkPixbuf *tile_repo_load(TileRepo *tr, guint tilex, guint tiley, gint zoom, gint zoff, gboolean fast_fail); + +G_END_DECLS #endif -- 2.39.5