/** * champlain_map_source_factory_create_cached_source: * @factory: the Factory * @id: the wanted map source id * * Creates a cached map source. * * Returns: (transfer none): a ready to use #ChamplainMapSourceChain consisting of * #ChamplainMemoryCache, #ChamplainFileCache, #ChamplainMapSource matching the given name, and * an error tile source created with champlain_map_source_factory_create_error_source (). * * Since: 0.6 */ ChamplainMapSource * champlain_map_source_factory_create_cached_source (ChamplainMapSourceFactory *factory, const gchar *id) { ChamplainMapSourceChain *source_chain; ChamplainMapSource *tile_source; ChamplainMapSource *error_source; ChamplainMapSource *memory_cache; ChamplainMapSource *file_cache; guint tile_size; ChamplainRenderer *renderer; tile_source = champlain_map_source_factory_create (factory, id); tile_size = champlain_map_source_get_tile_size (tile_source); error_source = champlain_map_source_factory_create_error_source (factory, tile_size); renderer = CHAMPLAIN_RENDERER (champlain_image_renderer_new ()); file_cache = CHAMPLAIN_MAP_SOURCE (champlain_file_cache_new_full (100000000, NULL, renderer)); renderer = CHAMPLAIN_RENDERER (champlain_image_renderer_new ()); memory_cache = CHAMPLAIN_MAP_SOURCE (champlain_memory_cache_new_full (100, renderer)); source_chain = champlain_map_source_chain_new (); champlain_map_source_chain_push (source_chain, error_source); champlain_map_source_chain_push (source_chain, tile_source); champlain_map_source_chain_push (source_chain, file_cache); champlain_map_source_chain_push (source_chain, memory_cache); return CHAMPLAIN_MAP_SOURCE (source_chain); }
static ChamplainMapSource * champlain_map_source_new_memphis (ChamplainMapSourceDesc *desc) { ChamplainMapSource *map_source; ChamplainRenderer *renderer; gchar *id, *name, *license, *license_uri; guint min_zoom, max_zoom, tile_size; ChamplainMapProjection projection; g_object_get (G_OBJECT (desc), "id", &id, "name", &name, "license", &license, "license-uri", &license_uri, "min-zoom-level", &min_zoom, "max-zoom-level", &max_zoom, "tile-size", &tile_size, "projection", &projection, NULL); renderer = CHAMPLAIN_RENDERER (champlain_memphis_renderer_new_full (tile_size)); if (g_strcmp0 (id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_LOCAL) == 0) { map_source = CHAMPLAIN_MAP_SOURCE (champlain_file_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, renderer)); } else { map_source = CHAMPLAIN_MAP_SOURCE (champlain_network_bbox_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, renderer)); } return map_source; }
static ChamplainMapSource * champlain_map_source_new_memphis (ChamplainMapSourceDesc *desc) { ChamplainMapSource *map_source; ChamplainRenderer *renderer; const gchar *id, *name, *license, *license_uri; guint min_zoom, max_zoom, tile_size; ChamplainMapProjection projection; id = champlain_map_source_desc_get_id (desc); name = champlain_map_source_desc_get_name (desc); license = champlain_map_source_desc_get_license (desc); license_uri = champlain_map_source_desc_get_license_uri (desc); min_zoom = champlain_map_source_desc_get_min_zoom_level (desc); max_zoom = champlain_map_source_desc_get_max_zoom_level (desc); tile_size = champlain_map_source_desc_get_tile_size (desc); projection = champlain_map_source_desc_get_projection (desc); renderer = CHAMPLAIN_RENDERER (champlain_memphis_renderer_new_full (tile_size)); if (g_strcmp0 (id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_LOCAL) == 0) { map_source = CHAMPLAIN_MAP_SOURCE (champlain_file_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, renderer)); } else { map_source = CHAMPLAIN_MAP_SOURCE (champlain_network_bbox_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, renderer)); } return map_source; }
static ChamplainMapSource * champlain_map_source_new_generic (ChamplainMapSourceDesc *desc) { ChamplainMapSource *map_source; ChamplainRenderer *renderer; const gchar *id, *name, *license, *license_uri, *uri_format; guint min_zoom, max_zoom, tile_size; ChamplainMapProjection projection; id = champlain_map_source_desc_get_id (desc); name = champlain_map_source_desc_get_name (desc); license = champlain_map_source_desc_get_license (desc); license_uri = champlain_map_source_desc_get_license_uri (desc); min_zoom = champlain_map_source_desc_get_min_zoom_level (desc); max_zoom = champlain_map_source_desc_get_max_zoom_level (desc); tile_size = champlain_map_source_desc_get_tile_size (desc); projection = champlain_map_source_desc_get_projection (desc); uri_format = champlain_map_source_desc_get_uri_format (desc); renderer = CHAMPLAIN_RENDERER (champlain_image_renderer_new ()); map_source = CHAMPLAIN_MAP_SOURCE (champlain_network_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, uri_format, renderer)); return map_source; }
static ChamplainMapSource * champlain_map_source_new_memphis (ChamplainMapSourceDesc *desc, G_GNUC_UNUSED gpointer user_data) { ChamplainMapDataSource *map_data_source; if (g_strcmp0 (desc->id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_LOCAL) == 0) { map_data_source = CHAMPLAIN_MAP_DATA_SOURCE (champlain_local_map_data_source_new ()); /* Abuse the uri_format field to store an initial data path (optional) */ if (desc->uri_format && g_strcmp0 (desc->uri_format, "") != 0) champlain_local_map_data_source_load_map_data ( CHAMPLAIN_LOCAL_MAP_DATA_SOURCE (map_data_source), desc->uri_format); } else if (g_strcmp0 (desc->id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_NETWORK) == 0) map_data_source = CHAMPLAIN_MAP_DATA_SOURCE (champlain_network_map_data_source_new ()); else return NULL; return CHAMPLAIN_MAP_SOURCE (champlain_memphis_tile_source_new_full ( desc->id, desc->name, desc->license, desc->license_uri, desc->min_zoom_level, desc->max_zoom_level, 256, desc->projection, map_data_source)); }
/** * champlain_map_source_chain_pop: * @source_chain: a #ChamplainMapSourceChain * * Pops a map source from the top of the stack from the chain. * * Since: 0.6 */ void champlain_map_source_chain_pop (ChamplainMapSourceChain *source_chain) { ChamplainMapSourceChainPrivate *priv = source_chain->priv; ChamplainMapSource *old_stack_top = priv->stack_top; ChamplainMapSource *next_source = champlain_map_source_get_next_source (priv->stack_top); g_return_if_fail (priv->stack_top); if (CHAMPLAIN_IS_TILE_CACHE (priv->stack_top)) { ChamplainTileCache *tile_cache = NULL; if (CHAMPLAIN_IS_TILE_CACHE (next_source)) tile_cache = CHAMPLAIN_TILE_CACHE (next_source); /* _push() guarantees that the last source is tile_source so we can be sure that the next map source is still within the chain */ assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache); } if (next_source == champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE (source_chain))) { priv->stack_top = NULL; priv->stack_bottom = NULL; } else priv->stack_top = next_source; g_object_unref (old_stack_top); }
static void refresh_tile_time (ChamplainTileCache *tile_cache, ChamplainTile *tile) { g_return_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (tile_cache)); ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (tile_cache); ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source); if (CHAMPLAIN_IS_TILE_CACHE (next_source)) champlain_tile_cache_refresh_tile_time (CHAMPLAIN_TILE_CACHE (next_source), tile); }
/** * champlain_map_source_factory_create_error_source: * @factory: the Factory * @tile_size: the size of the error tile * * Creates a map source generating error tiles. * * Returns: (transfer none): a ready to use map source generating error tiles. * * Since: 0.8 */ ChamplainMapSource * champlain_map_source_factory_create_error_source (ChamplainMapSourceFactory *factory, guint tile_size) { ChamplainMapSource *null_source; ChamplainRenderer *renderer; renderer = CHAMPLAIN_RENDERER (champlain_error_tile_renderer_new (tile_size)); null_source = CHAMPLAIN_MAP_SOURCE (champlain_null_tile_source_new_full (renderer)); return null_source; }
/** * champlain_map_source_factory_create_cached_source: * @factory: the Factory * @id: the wanted map source id * * Creates a cached map source. * * Returns: a ready to use #ChamplainMapSourceChain consisting of * #ChamplainFileCache, #ChamplainMapSource matching the given name, and * #ChamplainErrorTileSource. * * Since: 0.6 */ ChamplainMapSource * champlain_map_source_factory_create_cached_source (ChamplainMapSourceFactory *factory, const gchar *id) { ChamplainMapSourceChain *source_chain; ChamplainMapSource *tile_source; ChamplainMapSource *error_source; ChamplainMapSource *file_cache; guint tile_size; tile_source = champlain_map_source_factory_create (factory, id); tile_size = champlain_map_source_get_tile_size (tile_source); error_source = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size)); file_cache = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new ()); source_chain = champlain_map_source_chain_new (); champlain_map_source_chain_push (source_chain, error_source); champlain_map_source_chain_push (source_chain, tile_source); champlain_map_source_chain_push (source_chain, file_cache); return CHAMPLAIN_MAP_SOURCE(source_chain); }
static void on_set_next_source_cb (ChamplainMapSourceChain *source_chain, G_GNUC_UNUSED gpointer user_data) { g_return_if_fail (source_chain); ChamplainMapSourceChainPrivate *priv = source_chain->priv; ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (source_chain); ChamplainMapSource *next_source; next_source = champlain_map_source_get_next_source (map_source); if (priv->stack_bottom) champlain_map_source_set_next_source (priv->stack_bottom, next_source); }
static ChamplainMapSource * champlain_map_source_new_generic ( ChamplainMapSourceDesc *desc, G_GNUC_UNUSED gpointer user_data) { return CHAMPLAIN_MAP_SOURCE (champlain_network_tile_source_new_full ( desc->id, desc->name, desc->license, desc->license_uri, desc->min_zoom_level, desc->max_zoom_level, 256, desc->projection, desc->uri_format)); }
static gchar * generate_queue_key (ChamplainMemoryCache *memory_cache, ChamplainTile *tile) { g_return_val_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (memory_cache), NULL); g_return_val_if_fail (CHAMPLAIN_IS_TILE (tile), NULL); ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (memory_cache); gchar *key; key = g_strdup_printf ("%d/%d/%d/%s", champlain_tile_get_zoom_level (tile), champlain_tile_get_x (tile), champlain_tile_get_y (tile), champlain_map_source_get_id (map_source)); return key; }
static void store_tile (ChamplainTileCache *tile_cache, ChamplainTile *tile, const gchar *contents, gsize size) { g_return_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (tile_cache)); ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (tile_cache); ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source); ChamplainMemoryCache *memory_cache = CHAMPLAIN_MEMORY_CACHE (tile_cache); ChamplainMemoryCachePrivate *priv = memory_cache->priv; GList *link; gchar *key; key = generate_queue_key (memory_cache, tile); link = g_hash_table_lookup (priv->hash_table, key); if (link) { move_queue_member_to_head (priv->queue, link); g_free (key); } else { QueueMember *member; if (priv->queue->length >= priv->size_limit) { member = g_queue_pop_tail (priv->queue); g_hash_table_remove (priv->hash_table, member->key); delete_queue_member (member, NULL); } member = g_slice_new (QueueMember); member->key = key; member->data = g_memdup (contents, size); member->size = size; g_queue_push_head (priv->queue, member); g_hash_table_insert (priv->hash_table, g_strdup (key), g_queue_peek_head_link (priv->queue)); } if (CHAMPLAIN_IS_TILE_CACHE (next_source)) champlain_tile_cache_store_tile (CHAMPLAIN_TILE_CACHE (next_source), tile, contents, size); }
/** * champlain_map_source_chain_push: * @source_chain: a #ChamplainMapSourceChain * @map_source: the #ChamplainMapSource to be pushed into the chain * * Pushes a map source into the chain. * * Since: 0.6 */ void champlain_map_source_chain_push (ChamplainMapSourceChain *source_chain, ChamplainMapSource *map_source) { ChamplainMapSourceChainPrivate *priv = source_chain->priv; gboolean is_cache = FALSE; if (CHAMPLAIN_IS_TILE_CACHE(map_source)) is_cache = TRUE; else g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE(map_source)); g_object_ref_sink (map_source); if (!priv->stack_top) { ChamplainMapSource *chain_next_source = champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE(source_chain)); /* tile source has to be last */ g_return_if_fail (!is_cache); priv->stack_top = map_source; priv->stack_bottom = map_source; if (chain_next_source) champlain_map_source_set_next_source (priv->stack_bottom, chain_next_source); } else { if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id)) g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id); champlain_map_source_set_next_source (map_source, priv->stack_top); priv->stack_top = map_source; if (is_cache) { ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(map_source); assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache); } } priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles", G_CALLBACK (reload_tiles_cb), source_chain); }
static void assign_cache_of_next_source_sequence (ChamplainMapSourceChain *source_chain, ChamplainMapSource *start_map_source, ChamplainTileCache *tile_cache) { ChamplainMapSource *map_source = start_map_source; ChamplainMapSource *chain_next_source = champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE (source_chain)); do { map_source = champlain_map_source_get_next_source (map_source); } while (CHAMPLAIN_IS_TILE_CACHE (map_source)); while (CHAMPLAIN_IS_TILE_SOURCE (map_source) && map_source != chain_next_source) { champlain_tile_source_set_cache (CHAMPLAIN_TILE_SOURCE (map_source), tile_cache); map_source = champlain_map_source_get_next_source (map_source); } }
/** * champlain_file_tile_source_load_map_data: * @self: a #ChamplainFileTileSource * @map_path: a path to a map data file * * Loads the OpenStreetMap XML file at the given path. * * Since: 0.8 */ void champlain_file_tile_source_load_map_data (ChamplainFileTileSource *self, const gchar *map_path) { g_return_if_fail (CHAMPLAIN_IS_FILE_TILE_SOURCE (self)); ChamplainRenderer *renderer; gchar *data; gsize length; if (!g_file_get_contents (map_path, &data, &length, NULL)) { g_critical ("Error: \"%s\" cannot be read.", map_path); return; } renderer = champlain_map_source_get_renderer (CHAMPLAIN_MAP_SOURCE (self)); champlain_renderer_set_data (renderer, (guint8*) data, length); g_free (data); }
static void champlain_map_source_dispose (GObject *object) { ChamplainMapSourcePrivate *priv = CHAMPLAIN_MAP_SOURCE (object)->priv; if (priv->next_source) { g_object_unref (priv->next_source); priv->next_source = NULL; } if (priv->renderer) { g_object_unref (priv->renderer); priv->renderer = NULL; } G_OBJECT_CLASS (champlain_map_source_parent_class)->dispose (object); }
/** * champlain_map_source_chain_pop: * @source_chain: a #ChamplainMapSourceChain * * Pops the map source from the top of the stack from the chain. * * Since: 0.6 */ void champlain_map_source_chain_pop (ChamplainMapSourceChain *source_chain) { ChamplainMapSourceChainPrivate *priv = source_chain->priv; ChamplainMapSource *old_stack_top = priv->stack_top; ChamplainMapSource *next_source = champlain_map_source_get_next_source (priv->stack_top); g_return_if_fail (priv->stack_top); if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id)) g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id); if (CHAMPLAIN_IS_TILE_CACHE(priv->stack_top)) { ChamplainTileCache *tile_cache = NULL; if (CHAMPLAIN_IS_TILE_CACHE(next_source)) tile_cache = CHAMPLAIN_TILE_CACHE(next_source); /* _push() guarantees that the last source is tile_source so we can be sure that the next map source is still within the chain */ assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache); } if (next_source == champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE(source_chain))) { priv->stack_top = NULL; priv->stack_bottom = NULL; } else priv->stack_top = next_source; if (priv->stack_top) { priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles", G_CALLBACK (reload_tiles_cb), source_chain); } g_object_unref (old_stack_top); }
static void champlain_map_source_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { ChamplainMapSourcePrivate *priv = CHAMPLAIN_MAP_SOURCE (object)->priv; switch (prop_id) { case PROP_NEXT_SOURCE: g_value_set_object (value, priv->next_source); break; case PROP_RENDERER: g_value_set_object (value, priv->renderer); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } }
/** * champlain_map_source_chain_push: * @source_chain: a #ChamplainMapSourceChain * @map_source: the #ChamplainMapSource to be pushed into the chain * * Pushes a map source into the chain. * * Since: 0.6 */ void champlain_map_source_chain_push (ChamplainMapSourceChain *source_chain, ChamplainMapSource *map_source) { ChamplainMapSourceChainPrivate *priv = source_chain->priv; gboolean is_cache = FALSE; if (CHAMPLAIN_IS_TILE_CACHE (map_source)) is_cache = TRUE; else g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source)); g_object_ref_sink (map_source); if (!priv->stack_top) { ChamplainMapSource *chain_next_source = champlain_map_source_get_next_source (CHAMPLAIN_MAP_SOURCE (source_chain)); /* tile source has to be last */ g_return_if_fail (!is_cache); priv->stack_top = map_source; priv->stack_bottom = map_source; if (chain_next_source) champlain_map_source_set_next_source (priv->stack_bottom, chain_next_source); } else { champlain_map_source_set_next_source (map_source, priv->stack_top); priv->stack_top = map_source; if (is_cache) { ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE (map_source); assign_cache_of_next_source_sequence (source_chain, priv->stack_top, tile_cache); } } }
static void on_tile_filled (ChamplainTileCache *tile_cache, ChamplainTile *tile) { g_return_if_fail (CHAMPLAIN_IS_MEMORY_CACHE (tile_cache)); g_return_if_fail (CHAMPLAIN_IS_TILE (tile)); ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (tile_cache); ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source); ChamplainMemoryCache *memory_cache = CHAMPLAIN_MEMORY_CACHE (tile_cache); ChamplainMemoryCachePrivate *priv = memory_cache->priv; GList *link; gchar *key; key = generate_queue_key (memory_cache, tile); link = g_hash_table_lookup (priv->hash_table, key); g_free (key); if (link) move_queue_member_to_head (priv->queue, link); if (CHAMPLAIN_IS_TILE_CACHE (next_source)) champlain_tile_cache_on_tile_filled (CHAMPLAIN_TILE_CACHE (next_source), tile); }
static ChamplainMapSource * champlain_map_source_new_generic (ChamplainMapSourceDesc *desc) { ChamplainMapSource *map_source; ChamplainRenderer *renderer; gchar *id, *name, *license, *license_uri, *uri_format; guint min_zoom, max_zoom, tile_size; ChamplainMapProjection projection; g_object_get (G_OBJECT (desc), "id", &id, "name", &name, "license", &license, "license-uri", &license_uri, "min-zoom-level", &min_zoom, "max-zoom-level", &max_zoom, "tile-size", &tile_size, "projection", &projection, "uri-format", &uri_format, NULL); renderer = CHAMPLAIN_RENDERER (champlain_image_renderer_new ()); map_source = CHAMPLAIN_MAP_SOURCE (champlain_network_tile_source_new_full ( id, name, license, license_uri, min_zoom, max_zoom, tile_size, projection, uri_format, renderer)); return map_source; }
static void champlain_map_source_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (object); switch (prop_id) { case PROP_NEXT_SOURCE: champlain_map_source_set_next_source (map_source, g_value_get_object (value)); break; case PROP_RENDERER: champlain_map_source_set_renderer (map_source, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } }