/**
 * champlain_tile_cache_on_tile_filled:
 * @tile_cache: a #ChamplainTileCache
 * @tile: a #ChamplainTile
 *
 * When a cache fills a tile and the next source in the chain is a tile cache,
 * it should call this function on the next source. This way all the caches
 * preceding a tile source in the chain get informed that the tile was used and
 * can modify their metadata accordingly in the implementation of this function.
 * In addition, the call of this function should be chained so within the
 * implementation of this function it should be called on the next source
 * in the chain when next source is a tile cache.
 *
 * Since: 0.6
 */
void
champlain_tile_cache_on_tile_filled (ChamplainTileCache *tile_cache,
    ChamplainTile *tile)
{
  g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));

  CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->on_tile_filled (tile_cache, tile);
}
/**
 * champlain_tile_cache_refresh_tile_time:
 * @tile_cache: a #ChamplainTileCache
 * @tile: a #ChamplainTile
 *
 * Refreshes the tile access time in the cache.
 *
 * Since: 0.6
 */
void
champlain_tile_cache_refresh_tile_time (ChamplainTileCache *tile_cache,
    ChamplainTile *tile)
{
  g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));

  CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->refresh_tile_time (tile_cache, tile);
}
/**
 * champlain_tile_cache_store_tile:
 * @tile_cache: a #ChamplainTileCache
 * @tile: a #ChamplainTile
 * @contents: the tile contents that should be stored
 * @size: size of the contents in bytes
 *
 * Stores the tile including the metadata into the cache.
 *
 * Since: 0.6
 */
void
champlain_tile_cache_store_tile (ChamplainTileCache *tile_cache,
    ChamplainTile *tile,
    const gchar *contents,
    gsize size)
{
  g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));

  CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->store_tile (tile_cache, tile, contents, size);
}
static ChamplainMapProjection
get_projection (ChamplainMapSource *map_source)
{
  g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), CHAMPLAIN_MAP_PROJECTION_MERCATOR);

  ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);

  g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), CHAMPLAIN_MAP_PROJECTION_MERCATOR);

  return champlain_map_source_get_projection (next_source);
}
static guint
get_tile_size (ChamplainMapSource *map_source)
{
  g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), 0);

  ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);

  g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), 0);

  return champlain_map_source_get_tile_size (next_source);
}
static const gchar *
get_license_uri (ChamplainMapSource *map_source)
{
  g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), NULL);

  ChamplainMapSource *next_source = champlain_map_source_get_next_source (map_source);

  g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), NULL);

  return champlain_map_source_get_license_uri (next_source);
}
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);
}
Пример #8
0
/**
 * 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
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);
}
Пример #10
0
/**
 * 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_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);
}