From 9f58c4b4841869d578c2047cd4774179a8919fa7 Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Sun, 27 Mar 2011 23:06:25 +0200 Subject: [PATCH] Add support for Bing maps This implementation is quite rude as: * logo is built-in, while a right solution would be to download the logo and caching the result in viking's cache. * attributions are downloaded at first need, without automatically refreshing vikviewport, while a right solution would be to cache the file in viking's cache. Signed-off-by: Guilhem Bonnefille --- configure.ac | 14 ++ src/Makefile.am | 6 + src/bing.c | 43 ++++ src/bing.h | 28 +++ src/bingmapsource.c | 498 ++++++++++++++++++++++++++++++++++++++ src/bingmapsource.h | 55 +++++ src/icons/Makefile.am | 1 + src/icons/bing_maps.png | Bin 0 -> 4295 bytes src/modules.c | 4 + src/vikmapsourcedefault.c | 8 +- src/vikslippymapsource.c | 9 +- src/vikslippymapsource.h | 2 + 12 files changed, 660 insertions(+), 8 deletions(-) create mode 100644 src/bing.c create mode 100644 src/bing.h create mode 100644 src/bingmapsource.c create mode 100644 src/bingmapsource.h create mode 100644 src/icons/bing_maps.png diff --git a/configure.ac b/configure.ac index 22e369fd..64d8d17a 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,19 @@ case $ac_cv_enable_alpha_trw in ;; esac +AC_ARG_ENABLE(bing, AC_HELP_STRING([--enable-bing], + [enable Bing stuff (default is enable)]), + [ac_cv_enable_bing=$enableval], + [ac_cv_enable_bing=yes]) +AC_CACHE_CHECK([whether to enable Bing stuff], + [ac_cv_enable_bing], [ac_cv_enable_bing=yes]) +case $ac_cv_enable_bing in + yes) + AC_DEFINE(VIK_CONFIG_BING, [], [BING STUFF]) + ;; +esac +AM_CONDITIONAL([BING], [test x$ac_cv_enable_bing = xyes]) + AC_ARG_ENABLE(google, AC_HELP_STRING([--enable-google], [enable Google stuff (default is enable)]), [ac_cv_enable_google=$enableval], @@ -342,6 +355,7 @@ echo "===========================================" echo "$PACKAGE $VERSION" echo "-------------------------------------------" echo "Alphabetized track & waypoints : $ac_cv_enable_alpha_trw" +echo "Bing Maps : $ac_cv_enable_bing" echo "Google Maps : $ac_cv_enable_google" echo "Terraserver Maps : $ac_cv_enable_terraserver" echo "Expedia Maps : $ac_cv_enable_expedia" diff --git a/src/Makefile.am b/src/Makefile.am index d9094afe..d3d40b46 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -122,6 +122,12 @@ libviking_a_SOURCES = \ print.c print.h \ preferences.c preferences.h +if BING +libviking_a_SOURCES += \ + bingmapsource.c bingmapsource.h \ + bing.c bing.h +endif + if GOOGLE libviking_a_SOURCES += \ google.c google.h diff --git a/src/bing.c b/src/bing.c new file mode 100644 index 00000000..ccc044f9 --- /dev/null +++ b/src/bing.c @@ -0,0 +1,43 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2011, Guilhem Bonnefille + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "bing.h" +#include "vikmapslayer.h" +#include "bingmapsource.h" + +/** API key registered by Guilhem Bonnefille */ +#define API_KEY "AqsTAipaBBpKLXhcaGgP8kceYukatmtDLS1x0CXEhRZnpl1RELF9hlI8j4mNIkrE" + +/* initialisation */ +void bing_init () { + VikMapSource *bing_aerial = VIK_MAP_SOURCE + (bing_map_source_new_with_id (212, "Bing Bird's Eye Maps", API_KEY)); + + maps_layer_register_map_source (bing_aerial); +} + diff --git a/src/bing.h b/src/bing.h new file mode 100644 index 00000000..07f99bef --- /dev/null +++ b/src/bing.h @@ -0,0 +1,28 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2011, Guilhem Bonnefille + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __VIKING_BING_H +#define __VIKING_BING_H + +void bing_init (); + +#endif diff --git a/src/bingmapsource.c b/src/bingmapsource.c new file mode 100644 index 00000000..c1f1da14 --- /dev/null +++ b/src/bingmapsource.c @@ -0,0 +1,498 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * viking + * Copyright (C) 2011, Guilhem Bonnefille + * + * viking 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 3 of the License, or + * (at your option) any later version. + * + * viking 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, see . + */ + + /** + * SECTION:bingmapsource + * @short_description: the class for Bing Maps + * + * The #BingMapSource class handles Bing map source. + * + * License and term of use are available here: + * http://wiki.openstreetmap.org/wiki/File:Bing_license.pdf + * + * Technical details are available here: + * http://msdn.microsoft.com/en-us/library/dd877180.aspx + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_MATH_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#include "globals.h" +#include "curl_download.h" +#include "bingmapsource.h" +#include "bbox.h" +#include "background.h" +#include "icons/icons.h" + +/* Format for URL */ +#define URL_ATTR_FMT "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/0,0?zl=1&mapVersion=v1&key=%s&include=ImageryProviders&output=xml" + +static gchar *_get_uri ( VikMapSourceDefault *self, MapCoord *src ); +static void _get_copyright (VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(void*,const gchar*), void *data); +static const GdkPixbuf *_get_logo ( VikMapSource *self ); +static int _load_attributions ( BingMapSource *self ); +static void _async_load_attributions ( BingMapSource *self ); + +struct _Attribution +{ + gchar *attribution; + int minZoom; + int maxZoom; + LatLonBBox bounds; +}; + +typedef struct _BingMapSourcePrivate BingMapSourcePrivate; +struct _BingMapSourcePrivate +{ + gchar *api_key; + GList *attributions; + /* Current attribution, when parsing */ + gchar *attribution; +}; + +/* The pixbuf to store the logo */ +static GdkPixbuf *pixbuf = NULL; + +#define BING_MAP_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BING_TYPE_MAP_SOURCE, BingMapSourcePrivate)) + +/* properties */ +enum +{ + PROP_0, + + PROP_API_KEY, +}; + +G_DEFINE_TYPE (BingMapSource, bing_map_source, VIK_TYPE_SLIPPY_MAP_SOURCE); + +static void +bing_map_source_init (BingMapSource *self) +{ + /* initialize the object here */ + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + priv->api_key = NULL; + priv->attributions = NULL; + priv->attribution = NULL; +} + +static void +bing_map_source_finalize (GObject *object) +{ + BingMapSource *self = BING_MAP_SOURCE (object); + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + g_free (priv->api_key); + priv->api_key = NULL; + + G_OBJECT_CLASS (bing_map_source_parent_class)->finalize (object); +} + +static void +_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + BingMapSource *self = BING_MAP_SOURCE (object); + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + switch (property_id) + { + case PROP_API_KEY: + priv->api_key = g_strdup (g_value_get_string (value)); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + BingMapSource *self = BING_MAP_SOURCE (object); + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + switch (property_id) + { + case PROP_API_KEY: + g_value_set_string (value, priv->api_key); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +bing_map_source_class_init (BingMapSourceClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + VikMapSourceDefaultClass* grandparent_class = VIK_MAP_SOURCE_DEFAULT_CLASS (klass); + VikMapSourceClass* base_class = VIK_MAP_SOURCE_CLASS (klass); + GParamSpec *pspec = NULL; + + /* Overiding methods */ + object_class->set_property = _set_property; + object_class->get_property = _get_property; + grandparent_class->get_uri = _get_uri; + base_class->get_logo = _get_logo; + base_class->get_copyright = _get_copyright; + + pspec = g_param_spec_string ("api-key", + "API key", + "The API key to access Bing", + "" /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_API_KEY, pspec); + + g_type_class_add_private (klass, sizeof (BingMapSourcePrivate)); + + object_class->finalize = bing_map_source_finalize; + + pixbuf = gdk_pixbuf_from_pixdata ( &bing_maps_pixbuf, TRUE, NULL ); +} + +static gchar * +compute_quad_tree(int zoom, int tilex, int tiley) +{ + /* Picked from http://trac.openstreetmap.org/browser/applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java?rev=24486 */ + gchar k[20]; + int ik = 0; + int i = 0; + for(i = zoom; i > 0; i--) + { + char digit = 48; + int mask = 1 << (i - 1); + if ((tilex & mask) != 0) { + digit += 1; + } + if ((tiley & mask) != 0) { + digit += 2; + } + k[ik++] = digit; + } + k[ik] = '\0'; + return g_strdup(k); +} + +static gchar * +_get_uri( VikMapSourceDefault *self, MapCoord *src ) +{ + g_return_val_if_fail (BING_IS_MAP_SOURCE(self), NULL); + + /* BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); */ + gchar *quadtree = compute_quad_tree (17 - src->scale, src->x, src->y); + gchar *uri = g_strdup_printf ( "/tiles/a%s.%s?g=587", quadtree, "jpeg"); + g_free (quadtree); + return uri; +} + +static const GdkPixbuf * +_get_logo( VikMapSource *self ) +{ + return pixbuf; +} + +static void +_get_copyright(VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(void*,const gchar*), void *data) +{ + g_return_if_fail (BING_IS_MAP_SOURCE(self)); + g_debug("%s: looking for %g %g %g %g at %g", __FUNCTION__, bbox.south, bbox.north, bbox.east, bbox.west, zoom); + + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); + + int level = vik_slippy_map_source_zoom_to_scale (zoom); + + /* Loop over all known attributions */ + GList *attribution = priv->attributions; + if (attribution == NULL) { + _async_load_attributions (BING_MAP_SOURCE (self)); + } + while (attribution != NULL) { + struct _Attribution *current = (struct _Attribution*)attribution->data; + /* g_debug("%s %g %g %g %g %d %d", __FUNCTION__, current->bounds.south, current->bounds.north, current->bounds.east, current->bounds.west, current->minZoom, current->maxZoom); */ + if (BBOX_INTERSECT(bbox, current->bounds) && + (17 - level) > current->minZoom && + (17 - level) < current->maxZoom) { + (*fct)(data, current->attribution); + g_debug("%s: found match %s", __FUNCTION__, current->attribution); + } + attribution = attribution->next; + } +} + +/* Called for open tags */ +static void +_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + BingMapSource *self = BING_MAP_SOURCE (user_data); + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + const gchar *element = g_markup_parse_context_get_element (context); + if (strcmp (element, "CoverageArea") == 0) { + /* New Attribution */ + struct _Attribution *attribution = g_malloc (sizeof(struct _Attribution)); + priv->attributions = g_list_append (priv->attributions, attribution); + attribution->attribution = g_strdup (priv->attribution); + } +} + +/* Called for character data */ +/* text is not nul-terminated */ +static void +_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + BingMapSource *self = BING_MAP_SOURCE (user_data); + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + struct _Attribution *attribution = priv->attributions == NULL ? NULL : g_list_last (priv->attributions)->data; + const gchar *element = g_markup_parse_context_get_element (context); + gchar *textl = g_strndup (text, text_len); + const GSList *stack = g_markup_parse_context_get_element_stack (context); + int len = g_slist_length ((GSList *)stack); + + const gchar *parent = len > 1 ? g_slist_nth_data ((GSList *)stack, 1) : NULL; + + if (strcmp (element, "Attribution") == 0) { + g_free (priv->attribution); + priv->attribution = g_strdup (textl); + } else if (parent != NULL && strcmp (parent, "CoverageArea") == 0) { + if (strcmp (element, "ZoomMin") == 0) { + attribution->minZoom = atoi (textl); + } else if (strcmp (element, "ZoomMax") == 0) { + attribution->maxZoom = atoi (textl); + } + } else if (parent != NULL && strcmp (parent, "BoundingBox") == 0) { + if (strcmp (element, "SouthLatitude") == 0) { + attribution->bounds.south = g_ascii_strtod (textl, NULL); + } else if (strcmp (element, "WestLongitude") == 0) { + attribution->bounds.west = g_ascii_strtod (textl, NULL); + } else if (strcmp (element, "NorthLatitude") == 0) { + attribution->bounds.north = g_ascii_strtod (textl, NULL); + } else if (strcmp (element, "EastLongitude") == 0) { + attribution->bounds.east = g_ascii_strtod (textl, NULL); + } + } + if (attribution) + g_debug("Current attribution %s from %d to %d %g %g %g %g", + attribution->attribution, + attribution->minZoom, attribution->maxZoom, + attribution->bounds.south, attribution->bounds.north, attribution->bounds.west, attribution->bounds.east); + + g_free(textl); +} + +static gboolean +_parse_file_for_attributions(BingMapSource *self, gchar *filename) +{ + GMarkupParser xml_parser; + GMarkupParseContext *xml_context = NULL; + GError *error = NULL; + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + g_return_val_if_fail(priv != NULL, FALSE); + + FILE *file = g_fopen (filename, "r"); + if (file == NULL) + /* TODO emit warning */ + return FALSE; + + /* setup context parse (ie callbacks) */ + xml_parser.start_element = &_start_element; + xml_parser.end_element = NULL; + xml_parser.text = &_text; + xml_parser.passthrough = NULL; + xml_parser.error = NULL; + + xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL); + + gchar buff[BUFSIZ]; + size_t nb; + size_t offset = -1; + while (xml_context && + (nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0) + { + if (offset == -1) + /* first run */ + /* Avoid possible BOM at begining of the file */ + offset = buff[0] == '<' ? 0 : 3; + else + /* reset offset */ + offset = 0; + if (!g_markup_parse_context_parse(xml_context, buff+offset, nb-offset, &error)) + { + fprintf(stderr, "%s: parsing error: %s.\n", + __FUNCTION__, error->message); + g_markup_parse_context_free(xml_context); + xml_context = NULL; + } + g_clear_error (&error); + } + /* cleanup */ + if (xml_context && + !g_markup_parse_context_end_parse(xml_context, &error)) + fprintf(stderr, "%s: errors occurred while reading file: %s.\n", + __FUNCTION__, error->message); + g_clear_error (&error); + + if (xml_context) + g_markup_parse_context_free(xml_context); + xml_context = NULL; + fclose (file); + + return TRUE; +} + +static int +_load_attributions ( BingMapSource *self ) +{ + FILE *tmp_file; + int tmp_fd; + gchar *tmpname; + gchar *uri; + int ret = 0; /* OK */ + + BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); + + if ((tmp_fd = g_file_open_tmp ("vik-bing.XXXXXX", &tmpname, NULL)) == -1) { + g_critical(_("couldn't open temp file")); + return -1; + } + + tmp_file = fdopen(tmp_fd, "r+"); + uri = g_strdup_printf(URL_ATTR_FMT, priv->api_key); + + /* TODO: curl may not be available */ + if (curl_download_uri(uri, tmp_file, vik_map_source_default_get_download_options(VIK_MAP_SOURCE_DEFAULT(self)), 0, NULL)) { /* error */ + fclose(tmp_file); + tmp_file = NULL; + ret = -1; + goto done; + } + + fclose(tmp_file); + tmp_file = NULL; + + g_debug("%s: %s", __FUNCTION__, tmpname); + if (!_parse_file_for_attributions(self, tmpname)) { + ret = -1; + goto done; + } + +done: + g_free(uri); + g_remove(tmpname); + g_free(tmpname); + return ret; +} + +static int +_emit_update ( gpointer data ) +{ + gdk_threads_enter(); + /* TODO + vik_layers_panel_emit_update ( VIK_LAYERS_PANEL (data) ); + */ + gdk_threads_leave(); +} + +static int +_load_attributions_thread ( BingMapSource *self, gpointer threaddata ) +{ + _load_attributions ( self ); + int result = a_background_thread_progress ( threaddata, 1.0 ); + if ( result != 0 ) + return -1; /* Abort thread */ + + /* Emit update */ + /* As we are on a download thread, + * it's better to fire the update from the main loop. + */ + g_idle_add ( (GSourceFunc)_emit_update, NULL /* FIXME */ ); + + return 0; +} + +static void +_async_load_attributions ( BingMapSource *self ) +{ + a_background_thread ( /*VIK_GTK_WINDOW_FROM_WIDGET(vp)*/NULL, + _("Bing attribution Loading"), + (vik_thr_func) _load_attributions_thread, + self, + NULL, + NULL, + 1 ); + +} + +/** + * bing_map_source_new_with_id: + * @id: internal identifier. + * @label: the label to display in map provider selector. + * @key: the API key to access Bing's services. + * + * Constructor for Bing map source. + * + * Returns: a newly allocated BingMapSource GObject. + */ +BingMapSource * +bing_map_source_new_with_id (guint8 id, const gchar *label, const gchar *key) +{ + /* initialize settings here */ + return g_object_new(BING_TYPE_MAP_SOURCE, + "id", id, + "label", label, + "hostname", "ecn.t2.tiles.virtualearth.net", + "api-key", key, + "check-file-server-time", TRUE, + "copyright", "© 2011 Microsoft Corporation and/or its suppliers", + "license", "Microsoft Bing Maps Specific", + "license-url", "http://www.microsoft.com/maps/assets/docs/terms.aspx", + NULL); +} diff --git a/src/bingmapsource.h b/src/bingmapsource.h new file mode 100644 index 00000000..fa728fa4 --- /dev/null +++ b/src/bingmapsource.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * viking + * Copyright (C) 2011, Guilhem Bonnefille + * + * viking 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 3 of the License, or + * (at your option) any later version. + * + * viking 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, see . + */ + +#ifndef _BING_MAP_SOURCE_H +#define _BING_MAP_SOURCE_H + +#include "vikcoord.h" +#include "mapcoord.h" +#include "vikslippymapsource.h" + +G_BEGIN_DECLS + +#define BING_TYPE_MAP_SOURCE (bing_map_source_get_type ()) +#define BING_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BING_TYPE_MAP_SOURCE, BingMapSource)) +#define BING_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BING_TYPE_MAP_SOURCE, BingMapSourceClass)) +#define BING_IS_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BING_TYPE_MAP_SOURCE)) +#define BING_IS_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BING_TYPE_MAP_SOURCE)) +#define BING_MAP_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BING_TYPE_MAP_SOURCE, BingMapSourceClass)) + +typedef struct _BingMapSourceClass BingMapSourceClass; +typedef struct _BingMapSource BingMapSource; + +struct _BingMapSourceClass +{ + VikSlippyMapSourceClass parent_class; +}; + +struct _BingMapSource +{ + VikSlippyMapSource parent_instance; +}; + +GType bing_map_source_get_type (void) G_GNUC_CONST; + +BingMapSource * bing_map_source_new_with_id (guint8 id, const gchar *label, const gchar *key); + +G_END_DECLS + +#endif /* _BING_MAP_SOURCE_H_ */ diff --git a/src/icons/Makefile.am b/src/icons/Makefile.am index 7b13d313..5de5d568 100644 --- a/src/icons/Makefile.am +++ b/src/icons/Makefile.am @@ -201,6 +201,7 @@ WAYPOINT_ICONS_LARGE += wp_zoo_large.png ICONS = \ viking.png \ + bing_maps.png \ addtr_18.png \ begintr_18.png \ addwp_18.png \ diff --git a/src/icons/bing_maps.png b/src/icons/bing_maps.png new file mode 100644 index 0000000000000000000000000000000000000000..ae4367e87700710a625651348ea2f214d31b1788 GIT binary patch literal 4295 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 literal 0 HcmV?d00001 diff --git a/src/modules.c b/src/modules.c index ba79b22b..41818d5f 100644 --- a/src/modules.c +++ b/src/modules.c @@ -31,6 +31,7 @@ #include "modules.h" +#include "bing.h" #include "spotmaps.h" #include "google.h" #include "terraserver.h" @@ -110,6 +111,9 @@ modules_load_config(void) void modules_init() { +#ifdef VIK_CONFIG_BING + bing_init(); +#endif #ifdef VIK_CONFIG_GOOGLE google_init(); #endif diff --git a/src/vikmapsourcedefault.c b/src/vikmapsourcedefault.c index 4b574c07..8e09de39 100644 --- a/src/vikmapsourcedefault.c +++ b/src/vikmapsourcedefault.c @@ -128,7 +128,7 @@ vik_map_source_default_set_property (GObject *object, priv->uniq_id = g_value_get_uint (value); break; - case PROP_LABEL: + case PROP_LABEL: g_free (priv->label); priv->label = g_strdup(g_value_get_string (value)); break; @@ -268,7 +268,7 @@ vik_map_source_default_class_init (VikMapSourceDefaultClass *klass) 0 /* minimum value */, G_MAXUINT16 /* maximum value */, 0 /* default value */, - G_PARAM_READWRITE); + G_PARAM_CONSTRUCT | G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_TILESIZE_X, pspec); pspec = g_param_spec_uint ("tilesize-y", @@ -277,7 +277,7 @@ vik_map_source_default_class_init (VikMapSourceDefaultClass *klass) 0 /* minimum value */, G_MAXUINT16 /* maximum value */, 0 /* default value */, - G_PARAM_READWRITE); + G_PARAM_CONSTRUCT | G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_TILESIZE_Y, pspec); pspec = g_param_spec_enum("drawmode", @@ -292,7 +292,7 @@ vik_map_source_default_class_init (VikMapSourceDefaultClass *klass) "Copyright", "The copyright of the map source", NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_COPYRIGHT, pspec); pspec = g_param_spec_string ("license", diff --git a/src/vikslippymapsource.c b/src/vikslippymapsource.c index d8e45a9d..a8f514a6 100644 --- a/src/vikslippymapsource.c +++ b/src/vikslippymapsource.c @@ -233,14 +233,14 @@ vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass) "Hostname", "The hostname of the map server", "" /* default value */, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_HOSTNAME, pspec); pspec = g_param_spec_string ("url", "URL", "The template of the tiles' URL", "" /* default value */, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_URL, pspec); pspec = g_param_spec_string ("referer", @@ -290,7 +290,8 @@ static const gdouble scale_neg_mpps[] = { 1.0/GZ(0), 1.0/GZ(1), 1.0/GZ(2), 1.0/G static const gint num_scales_neg = (sizeof(scale_neg_mpps) / sizeof(scale_neg_mpps[0])); #define ERROR_MARGIN 0.01 -static gint slippy_zoom ( gdouble mpp ) { +gint +vik_slippy_map_source_zoom_to_scale ( gdouble mpp ) { gint i; for ( i = 0; i < num_scales; i++ ) { if ( ABS(scale_mpps[i] - mpp) < ERROR_MARGIN ) { @@ -324,7 +325,7 @@ _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdo if ( xzoom != yzoom ) return FALSE; - dest->scale = slippy_zoom ( xzoom ); + dest->scale = vik_slippy_map_source_zoom_to_scale ( xzoom ); if ( dest->scale == 255 ) return FALSE; diff --git a/src/vikslippymapsource.h b/src/vikslippymapsource.h index a39d2f33..bbb53c1e 100644 --- a/src/vikslippymapsource.h +++ b/src/vikslippymapsource.h @@ -49,6 +49,8 @@ struct _VikSlippyMapSource GType vik_slippy_map_source_get_type (void) G_GNUC_CONST; VikSlippyMapSource * vik_slippy_map_source_new_with_id (guint8 id, const gchar *label, const gchar *hostname, const gchar *url); +gint vik_slippy_map_source_zoom_to_scale ( gdouble mpp ); + G_END_DECLS -- 2.39.5