[libchamplain] New tile unref logic and various leak fixes



commit 6303a4d243701c09f52c3509ed0ef75684142483
Author: JiÅ?í Techet <techet gmail com>
Date:   Sun Mar 7 02:43:01 2010 +0100

    New tile unref logic and various leak fixes
    
    This patch does the following:
    
    * makes champlain_tile, champlain_zoom_level and champlain_polygon
      inherit from ClutterGroup, which makes them ClutterActor
    * tiles are not reffed/unreffed anywhere in the code. Instead, upon
      their creation they are inserted into champlain_zoom_level and when
      they are destructed, the map sources have to detect this destruction -
      this is much simpler than other way round
    * champlain_map is removed and the necessary functionality moved to
      champlain_zoom_level
    * removes the use of "public private" members
    * fixes many memory allocation related problems
    * some random fixes and code readability improvements found on the way
    
    Signed-off-by: JiÅ?í Techet <techet gmail com>

 champlain-gtk/gtk-champlain-embed.c       |    2 +-
 champlain/Makefile.am                     |    2 -
 champlain/champlain-base-marker.c         |    1 -
 champlain/champlain-error-tile-source.c   |    6 +-
 champlain/champlain-file-cache.c          |   25 +-
 champlain/champlain-layer.c               |    4 +-
 champlain/champlain-map.c                 |  126 ------
 champlain/champlain-map.h                 |   61 ---
 champlain/champlain-marker.c              |  152 +++++---
 champlain/champlain-marker.h              |    2 -
 champlain/champlain-memphis-tile-source.c |   88 +++--
 champlain/champlain-network-tile-source.c |   21 +-
 champlain/champlain-polygon.c             |  228 +++++++++---
 champlain/champlain-polygon.h             |   12 +-
 champlain/champlain-private.h             |   13 -
 champlain/champlain-tile.c                |  146 ++-----
 champlain/champlain-tile.h                |    7 +-
 champlain/champlain-view.c                |  614 ++++++++++-------------------
 champlain/champlain-view.h                |    3 -
 champlain/champlain-zoom-level.c          |  210 ++--------
 champlain/champlain-zoom-level.h          |   16 +-
 21 files changed, 669 insertions(+), 1070 deletions(-)
---
diff --git a/champlain-gtk/gtk-champlain-embed.c b/champlain-gtk/gtk-champlain-embed.c
index 431eda6..285cd70 100644
--- a/champlain-gtk/gtk-champlain-embed.c
+++ b/champlain-gtk/gtk-champlain-embed.c
@@ -200,7 +200,7 @@ set_view (GtkChamplainEmbed* embed,
       clutter_container_remove_actor (CLUTTER_CONTAINER (stage), CLUTTER_ACTOR (priv->view));
     }
 
-  priv->view = g_object_ref (view);
+  priv->view = g_object_ref_sink (view);
   clutter_actor_set_size (CLUTTER_ACTOR (priv->view), priv->width, priv->height);
 
   clutter_container_add_actor (CLUTTER_CONTAINER (stage), CLUTTER_ACTOR (priv->view));
diff --git a/champlain/Makefile.am b/champlain/Makefile.am
index 18b4130..0e80c4e 100644
--- a/champlain/Makefile.am
+++ b/champlain/Makefile.am
@@ -23,7 +23,6 @@ libchamplain_headers = \
 	champlain-selection-layer.h 	\
 	champlain-base-marker.h		\
 	champlain-marker.h		\
-	champlain-map.h			\
 	champlain-tile.h		\
 	champlain-map-source.h		\
 	champlain-map-source-chain.h	\
@@ -52,7 +51,6 @@ libchamplain_0_5_la_SOURCES = \
 	champlain-selection-layer.c 	\
 	champlain-base-marker.c 	\
 	champlain-marker.c 		\
-	champlain-map.c  		\
 	champlain-zoom-level.c 		\
 	champlain-tile.c		\
 	champlain-map-source.c		\
diff --git a/champlain/champlain-base-marker.c b/champlain/champlain-base-marker.c
index 51f7992..5deb74c 100644
--- a/champlain/champlain-base-marker.c
+++ b/champlain/champlain-base-marker.c
@@ -41,7 +41,6 @@
 #include "champlain-defines.h"
 #include "champlain-marshal.h"
 #include "champlain-private.h"
-#include "champlain-map.h"
 #include "champlain-tile.h"
 #include "champlain-zoom-level.h"
 
diff --git a/champlain/champlain-error-tile-source.c b/champlain/champlain-error-tile-source.c
index d4b5df7..e3fbea1 100644
--- a/champlain/champlain-error-tile-source.c
+++ b/champlain/champlain-error-tile-source.c
@@ -100,8 +100,12 @@ fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile)
   guint size;
 
   if (champlain_tile_get_content (tile))
-    /* cache is just validating tile - don't generate error tile in this case */
+  {
+    /* cache is just validating tile - don't generate error tile in this case - instead use what we have */
+    if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_DONE)
+      champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
     return;
+  }
 
   size = champlain_map_source_get_tile_size (map_source);
 
diff --git a/champlain/champlain-file-cache.c b/champlain/champlain-file-cache.c
index 4b8b5e8..e79c9b2 100644
--- a/champlain/champlain-file-cache.c
+++ b/champlain/champlain-file-cache.c
@@ -579,8 +579,20 @@ tile_loaded_cb (ClutterTexture *texture,
   GTimeVal modified_time = {0,};
 
   g_signal_handler_disconnect (texture, user_data->handler);
+
+  if (tile)
+    g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer*)&user_data->tile);
+
   g_free (user_data);
 
+  if (!tile)
+    {
+      DEBUG ("Tile destroyed while loading");
+      if (!error && actor)
+        clutter_actor_destroy (actor);
+      goto cleanup;
+    }
+
   if (error)
     {
       DEBUG ("Failed to load tile %s, error: %s", filename, error->message);
@@ -653,16 +665,14 @@ tile_loaded_cb (ClutterTexture *texture,
 load_next:
   if (CHAMPLAIN_IS_MAP_SOURCE(next_source))
     champlain_map_source_fill_tile (next_source, tile);
-
-  /* if we have some content, use the tile even if it wasn't validated */
-  if (champlain_tile_get_content (tile) &&
-      champlain_tile_get_state (tile) != CHAMPLAIN_STATE_DONE)
+  else if (champlain_tile_get_content (tile) &&
+           champlain_tile_get_state (tile) != CHAMPLAIN_STATE_DONE)
+    /* if we have some content, use the tile even if it wasn't validated */
     champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
 
 cleanup:
   sqlite3_reset (priv->stmt_select);
   g_free (filename);
-  g_object_unref (tile);
   g_object_unref (map_source);
 }
 
@@ -686,10 +696,7 @@ fill_tile (ChamplainMapSource *map_source,
 
       DEBUG ("fill of %s", callback_data->filename);
 
-      /* Ref the tile as it may be freeing during the loading
-       * Unref when the loading is done.
-       */
-      g_object_ref (tile);
+      g_object_add_weak_pointer (G_OBJECT (tile), (gpointer*)&callback_data->tile);
       g_object_ref (map_source);
 
       /* Load the cached version */
diff --git a/champlain/champlain-layer.c b/champlain/champlain-layer.c
index b3d7191..48e5f47 100644
--- a/champlain/champlain-layer.c
+++ b/champlain/champlain-layer.c
@@ -208,7 +208,7 @@ champlain_layer_add_marker (ChamplainLayer *layer,
   g_return_if_fail (CHAMPLAIN_IS_LAYER (layer));
   g_return_if_fail (CHAMPLAIN_IS_BASE_MARKER (marker));
 
-  clutter_container_add (CLUTTER_CONTAINER (layer), CLUTTER_ACTOR (marker), NULL);
+  clutter_container_add_actor (CLUTTER_CONTAINER (layer), CLUTTER_ACTOR (marker));
 }
 
 /**
@@ -227,7 +227,7 @@ champlain_layer_remove_marker (ChamplainLayer *layer,
   g_return_if_fail (CHAMPLAIN_IS_LAYER (layer));
   g_return_if_fail (CHAMPLAIN_IS_BASE_MARKER (marker));
 
-  clutter_container_remove (CLUTTER_CONTAINER (layer), CLUTTER_ACTOR (marker), NULL);
+  clutter_container_remove_actor (CLUTTER_CONTAINER (layer), CLUTTER_ACTOR (marker));
 }
 
 /**
diff --git a/champlain/champlain-marker.c b/champlain/champlain-marker.c
index 26ea247..4724153 100644
--- a/champlain/champlain-marker.c
+++ b/champlain/champlain-marker.c
@@ -41,7 +41,6 @@
 #include "champlain-defines.h"
 #include "champlain-marshal.h"
 #include "champlain-private.h"
-#include "champlain-map.h"
 #include "champlain-tile.h"
 #include "champlain-zoom-level.h"
 
@@ -110,7 +109,7 @@ struct _ChamplainMarkerPrivate
 
 G_DEFINE_TYPE (ChamplainMarker, champlain_marker, CHAMPLAIN_TYPE_BASE_MARKER);
 
-#define CHAMPLAIN_MARKER_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MARKER, ChamplainMarkerPrivate))
+#define GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MARKER, ChamplainMarkerPrivate))
 
 static void draw_marker (ChamplainMarker *marker);
 
@@ -184,8 +183,7 @@ champlain_marker_get_property (GObject *object,
                                GValue *value,
                                GParamSpec *pspec)
 {
-    ChamplainMarker *marker = CHAMPLAIN_MARKER (object);
-    ChamplainMarkerPrivate *priv = marker->priv;
+    ChamplainMarkerPrivate *priv = GET_PRIVATE (object);
 
     switch (prop_id)
       {
@@ -283,22 +281,71 @@ champlain_marker_set_property (GObject *object,
 }
 
 static void
+champlain_marker_dispose (GObject *object)
+{
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (object);
+
+  if (priv->background)
+    {
+      g_object_unref (priv->background);
+      priv->background = NULL;
+    }
+
+  if (priv->shadow)
+    {
+      g_object_unref (priv->shadow);
+      priv->shadow = NULL;
+    }
+
+  if (priv->text_actor)
+    {
+      g_object_unref (priv->text_actor);
+      priv->text_actor = NULL;
+    }
+
+  if (priv->image)
+    {
+      g_object_unref (priv->image);
+      priv->image = NULL;
+    }
+
+  if (priv->attributes)
+    {
+      pango_attr_list_unref (priv->attributes);
+      priv->attributes = NULL;
+    }
+
+  G_OBJECT_CLASS (champlain_marker_parent_class)->dispose (object);
+}
+
+static void
 champlain_marker_finalize (GObject *object)
 {
-  ChamplainMarker *marker = CHAMPLAIN_MARKER (object);
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (object);
 
-  if (priv->text != NULL)
-    g_free (priv->text);
-  priv->text = NULL;
+  if (priv->text)
+    {
+      g_free (priv->text);
+      priv->text = NULL;
+    }
 
-  if (priv->image != NULL)
-    g_object_unref (priv->image);
-  priv->image = NULL;
+  if (priv->font_name)
+    {
+      g_free (priv->font_name);
+      priv->font_name = NULL;
+    }
 
-  if (priv->background != NULL)
-    g_object_unref (priv->background);
-  priv->background = NULL;
+  if (priv->color)
+    {
+      clutter_color_free (priv->color);
+      priv->color = NULL;
+    }
+
+  if (priv->text_color)
+    {
+      clutter_color_free (priv->text_color);
+      priv->text_color = NULL;
+    }
 
   if (priv->redraw_id)
     {
@@ -316,6 +363,7 @@ champlain_marker_class_init (ChamplainMarkerClass *markerClass)
 
   GObjectClass *object_class = G_OBJECT_CLASS (markerClass);
   object_class->finalize = champlain_marker_finalize;
+  object_class->dispose = champlain_marker_dispose;
   object_class->get_property = champlain_marker_get_property;
   object_class->set_property = champlain_marker_set_property;
 
@@ -498,7 +546,7 @@ draw_shadow (ChamplainMarker *marker,
    gint height,
    gint point)
 {
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
   ClutterActor *shadow = NULL;
   cairo_t *cr;
   gdouble slope;
@@ -550,7 +598,7 @@ draw_background (ChamplainMarker *marker,
     gint height,
     gint point)
 {
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
   ChamplainBaseMarkerPrivate *base_priv = CHAMPLAIN_BASE_MARKER (marker)->priv;
   ClutterActor *bg = NULL;
   ClutterColor *color;
@@ -602,7 +650,7 @@ draw_background (ChamplainMarker *marker,
 static void
 draw_marker (ChamplainMarker *marker)
 {
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
   ChamplainBaseMarkerPrivate *base_priv = CHAMPLAIN_BASE_MARKER (marker)->priv;
   guint height = 0, point = 0;
   guint total_width = 0, total_height = 0;
@@ -713,8 +761,9 @@ static gboolean
 redraw_on_idle (gpointer gobject)
 {
   ChamplainMarker *marker = CHAMPLAIN_MARKER (gobject);
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
   CHAMPLAIN_MARKER_GET_CLASS (gobject)->draw_marker (marker);
-  marker->priv->redraw_id = 0;
+  priv->redraw_id = 0;
   return FALSE;
 }
 
@@ -732,8 +781,9 @@ redraw_on_idle (gpointer gobject)
 void
 champlain_marker_queue_redraw (ChamplainMarker *marker)
 {
-  if (!marker->priv->redraw_id)
-    marker->priv->redraw_id = g_idle_add (redraw_on_idle, marker);
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
+  if (!priv->redraw_id)
+    priv->redraw_id = g_idle_add (redraw_on_idle, marker);
 }
 
 static void
@@ -747,8 +797,7 @@ notify_highlighted (GObject *gobject,
 static void
 champlain_marker_init (ChamplainMarker *marker)
 {
-  ChamplainMarkerPrivate *priv = CHAMPLAIN_MARKER_GET_PRIVATE (marker) ;
-  marker->priv = priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->text = NULL;
   priv->image = NULL;
@@ -903,7 +952,7 @@ champlain_marker_set_text (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (priv->text != NULL)
     g_free (priv->text);
@@ -927,10 +976,13 @@ champlain_marker_set_image (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (priv->image != NULL)
-    clutter_actor_destroy (priv->image);
+    {
+      g_object_unref (image);
+      clutter_actor_destroy (priv->image);
+    }
 
   if (image != NULL)
     {
@@ -959,7 +1011,7 @@ champlain_marker_set_use_markup (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->use_markup = markup;
   g_object_notify (G_OBJECT (marker), "use-markup");
@@ -981,7 +1033,7 @@ champlain_marker_set_alignment (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->alignment = alignment;
   g_object_notify (G_OBJECT (marker), "alignment");
@@ -1004,13 +1056,13 @@ champlain_marker_set_color (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (priv->color != NULL)
     clutter_color_free (priv->color);
 
   if (color == NULL)
-     color = &DEFAULT_COLOR;
+    color = &DEFAULT_COLOR;
 
   priv->color = clutter_color_copy (color);
   g_object_notify (G_OBJECT (marker), "color");
@@ -1033,7 +1085,7 @@ champlain_marker_set_text_color (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (priv->text_color != NULL)
     clutter_color_free (priv->text_color);
@@ -1062,7 +1114,7 @@ champlain_marker_set_font_name (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (priv->font_name != NULL)
     g_free (priv->font_name);
@@ -1090,7 +1142,7 @@ champlain_marker_set_wrap (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->wrap = wrap;
   g_object_notify (G_OBJECT (marker), "wrap");
@@ -1112,7 +1164,7 @@ champlain_marker_set_wrap_mode (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->wrap_mode = wrap_mode;
   g_object_notify (G_OBJECT (marker), "wrap");
@@ -1134,7 +1186,7 @@ champlain_marker_set_attributes (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   if (attributes)
     pango_attr_list_ref (attributes);
@@ -1163,7 +1215,7 @@ champlain_marker_set_ellipsize (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->ellipsize = ellipsize;
   g_object_notify (G_OBJECT (marker), "ellipsize");
@@ -1184,7 +1236,7 @@ champlain_marker_set_single_line_mode (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->single_line_mode = mode;
 
@@ -1207,7 +1259,7 @@ champlain_marker_set_draw_background (ChamplainMarker *marker,
 {
   g_return_if_fail (CHAMPLAIN_IS_MARKER (marker));
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   priv->draw_background = background;
   g_object_notify (G_OBJECT (marker), "draw-background");
@@ -1227,7 +1279,7 @@ champlain_marker_get_image (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), NULL);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->image;
 }
@@ -1245,7 +1297,7 @@ champlain_marker_get_use_markup (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->use_markup;
 }
@@ -1263,7 +1315,7 @@ champlain_marker_get_text (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->text;
 }
@@ -1281,7 +1333,7 @@ champlain_marker_get_alignment (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->alignment;
 }
@@ -1299,7 +1351,7 @@ champlain_marker_get_color (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), NULL);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->color;
 }
@@ -1317,7 +1369,7 @@ champlain_marker_get_text_color (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), NULL);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->text_color;
 }
@@ -1335,7 +1387,7 @@ champlain_marker_get_font_name (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->font_name;
 }
@@ -1353,7 +1405,7 @@ champlain_marker_get_wrap (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->wrap;
 }
@@ -1371,7 +1423,7 @@ champlain_marker_get_wrap_mode (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->wrap_mode;
 }
@@ -1389,7 +1441,7 @@ champlain_marker_get_ellipsize (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->ellipsize;
 }
@@ -1407,7 +1459,7 @@ champlain_marker_get_single_line_mode (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->single_line_mode;
 }
@@ -1425,7 +1477,7 @@ champlain_marker_get_draw_background (ChamplainMarker *marker)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER (marker), FALSE);
 
-  ChamplainMarkerPrivate *priv = marker->priv;
+  ChamplainMarkerPrivate *priv = GET_PRIVATE (marker);
 
   return priv->draw_background;
 }
diff --git a/champlain/champlain-marker.h b/champlain/champlain-marker.h
index dfbfbe9..09f46d3 100644
--- a/champlain/champlain-marker.h
+++ b/champlain/champlain-marker.h
@@ -45,8 +45,6 @@ typedef struct _ChamplainMarkerClass ChamplainMarkerClass;
 struct _ChamplainMarker
 {
   ChamplainBaseMarker base;
-
-  ChamplainMarkerPrivate *priv;
 };
 
 struct _ChamplainMarkerClass
diff --git a/champlain/champlain-memphis-tile-source.c b/champlain/champlain-memphis-tile-source.c
index a2fa284..c94251e 100644
--- a/champlain/champlain-memphis-tile-source.c
+++ b/champlain/champlain-memphis-tile-source.c
@@ -84,10 +84,15 @@ struct _ChamplainMemphisTileSourcePrivate
   gboolean no_map_data;
 };
 
-typedef struct _TileLoadedData TileLoadedData;
+typedef struct _WorkerThreadData WorkerThreadData;
 
-struct _TileLoadedData
+struct _WorkerThreadData
 {
+  gint x;
+  gint y;
+  guint z;
+  guint size;
+
   ChamplainMapSource *map_source;
   ChamplainTile *tile;
   cairo_surface_t *cst;
@@ -330,26 +335,35 @@ void argb_to_rgba (guchar *data, guint size)
 }
 
 static gboolean
-tile_loaded_cb (gpointer data)
+tile_loaded_cb (gpointer worker_data)
 {
-  TileLoadedData *tdata = (TileLoadedData *) data;
-  ChamplainMapSource *map_source = tdata->map_source;
-  ChamplainTile *tile = tdata->tile;
-  cairo_surface_t *cst = tdata->cst;
+  WorkerThreadData *data = (WorkerThreadData *) worker_data;
+  ChamplainMapSource *map_source = data->map_source;
+  ChamplainTile *tile = data->tile;
+  cairo_surface_t *cst = data->cst;
   ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE(map_source);
   ChamplainTileCache *tile_cache = champlain_tile_source_get_cache (tile_source);
   cairo_t *cr_clutter;
   ClutterActor *actor;
-  guint size;
+  guint size = data->size;
   GError *error = NULL;
 
-  g_free (tdata);
+  if (tile)
+    g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer*)&data->tile);
+
+  g_free (data);
+
+  if (!tile)
+    {
+      DEBUG ("Tile destroyed while loading");
+      cairo_surface_destroy (cst);
+      g_object_unref (map_source);
+      return FALSE;
+    }
 
   // FIXME - once memphis detects when tile cannot be rendered, call fill_tile
   // on next_source here and return
 
-  size = champlain_tile_get_size (tile);
-
   /* draw the clutter texture */
   actor = clutter_cairo_texture_new (size, size);
 
@@ -394,49 +408,33 @@ tile_loaded_cb (gpointer data)
   champlain_tile_set_content (tile, actor, TRUE);
   champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
 
-  g_object_unref (tile);
   g_object_unref (map_source);
 
   return FALSE;
 }
 
 static void
-memphis_worker_thread (gpointer data, gpointer user_data)
+memphis_worker_thread (gpointer worker_data, gpointer user_data)
 {
-  ChamplainTile *tile = (ChamplainTile *)data;
-  ChamplainMapSource *map_source = (ChamplainMapSource *)user_data;
+  WorkerThreadData *data = (WorkerThreadData *)worker_data;
+  ChamplainMapSource *map_source = data->map_source;
   cairo_t *cr;
-  cairo_surface_t *cst;
-  guint x, y, z, size;
-  TileLoadedData *loaded_data;
-
-  x = champlain_tile_get_x (tile);
-  y = champlain_tile_get_y (tile);
-  z = champlain_tile_get_zoom_level (tile);
-  size = champlain_tile_get_size (tile);
 
   /* create a clutter-independant surface to draw on */
-  cst = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
-  cr = cairo_create (cst);
+  data->cst = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, data->size, data->size);
+  cr = cairo_create (data->cst);
 
-  DEBUG ("Draw Tile (%d, %d, %d)", x, y, z);
+  DEBUG ("Draw Tile (%d, %d, %d)", data->x, data->y, data->z);
 
   g_static_rw_lock_reader_lock (&MemphisLock);
   // FIXME - memphis needs to indicate if it cannot render the tile so we can
   // load the tile from the next map source
-  memphis_renderer_draw_tile (GET_PRIVATE(map_source)->renderer, cr, x, y, z);
+  memphis_renderer_draw_tile (GET_PRIVATE(map_source)->renderer, cr, data->x, data->y, data->z);
   g_static_rw_lock_reader_unlock (&MemphisLock);
 
   cairo_destroy (cr);
 
-  /* Write the tile content and cache entry */
-  loaded_data = g_new (TileLoadedData, 1);
-  loaded_data->map_source = map_source;
-  loaded_data->tile = tile;
-  loaded_data->cst = cst;
-
-  clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, tile_loaded_cb,
-                                 loaded_data, NULL);
+  clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, tile_loaded_cb, data, NULL);
 }
 
 static void
@@ -460,21 +458,29 @@ fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile)
   else
     {
       GError *error = NULL;
-      guint size;
+      WorkerThreadData *data;
+
+      data = g_new (WorkerThreadData, 1);
+      data->x = champlain_tile_get_x (tile);
+      data->y = champlain_tile_get_y (tile);
+      data->z = champlain_tile_get_zoom_level (tile);
+      data->size = champlain_map_source_get_tile_size (map_source);
+      data->tile = tile;
+      data->map_source = map_source;
 
-      size = champlain_map_source_get_tile_size (map_source);
-      champlain_tile_set_size (tile, size);
+      g_object_add_weak_pointer (G_OBJECT (tile), (gpointer*)&data->tile);
 
-      g_object_ref (tile);
       g_object_ref (map_source);
 
-      g_thread_pool_push (priv->thpool, tile, &error);
+      champlain_tile_set_size (tile, data->size);
+
+      g_thread_pool_push (priv->thpool, data, &error);
       if (error)
         {
           g_error ("Thread pool error: %s", error->message);
           g_error_free (error);
           g_object_unref (map_source);
-          g_object_unref (tile);
+          g_free (data);
         }
     }
 }
diff --git a/champlain/champlain-network-tile-source.c b/champlain/champlain-network-tile-source.c
index 7e946e0..70e1ab0 100644
--- a/champlain/champlain-network-tile-source.c
+++ b/champlain/champlain-network-tile-source.c
@@ -501,17 +501,21 @@ tile_loaded_cb (SoupSession *session,
   ClutterActor *actor;
   const gchar *etag;
 
+  if (tile)
+    g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer*)&callback_data->tile);
+
   g_free (user_data);
 
   DEBUG ("Got reply %d", msg->status_code);
 
-  if (msg->status_code == SOUP_STATUS_CANCELLED)
+  if (!tile || msg->status_code == SOUP_STATUS_CANCELLED)
     {
-      DEBUG ("Download of tile %d, %d got cancelled",
-             champlain_tile_get_x (tile), champlain_tile_get_y (tile));
-      //champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+      if (!tile)
+        DEBUG ("Tile destroyed while loading");
+      else
+        DEBUG ("Download of tile %d, %d got cancelled",
+               champlain_tile_get_x (tile), champlain_tile_get_y (tile));
 
-      g_object_unref (tile);
       g_object_unref (map_source);
       return;
     }
@@ -603,13 +607,11 @@ load_next:
     {
       champlain_map_source_fill_tile (next_source, tile);
     }
-  g_object_unref (tile);
   g_object_unref (map_source);
   return;
 
 finish:
   champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
-  g_object_unref (tile);
   g_object_unref (map_source);
 }
 
@@ -667,10 +669,7 @@ fill_tile (ChamplainMapSource *map_source,
       callback_data->tile = tile;
       callback_data->map_source = map_source;
 
-      /* Ref the tile as it may be freeing during the loading
-       * Unref when the loading is done.
-       */
-      g_object_ref (tile);
+      g_object_add_weak_pointer (G_OBJECT (tile), (gpointer*)&callback_data->tile);
       g_object_ref (map_source);
 
       soup_session_queue_message (priv->soup_session, msg,
diff --git a/champlain/champlain-polygon.c b/champlain/champlain-polygon.c
index d846190..64db997 100644
--- a/champlain/champlain-polygon.c
+++ b/champlain/champlain-polygon.c
@@ -28,15 +28,28 @@
 #include "champlain-polygon.h"
 
 #include "champlain-defines.h"
-#include "champlain-private.h"
+#include "champlain-map-source.h"
 
 #include <clutter/clutter.h>
 #include <glib.h>
+#include <math.h>
 
 static ClutterColor DEFAULT_FILL_COLOR = {0xcc, 0x00, 0x00, 0xaa};
 static ClutterColor DEFAULT_STROKE_COLOR = {0xa4, 0x00, 0x00, 0xff};
 
-G_DEFINE_TYPE (ChamplainPolygon, champlain_polygon, G_TYPE_INITIALLY_UNOWNED)
+struct _ChamplainPolygonPrivate {
+  GList *points;
+  gboolean closed_path;
+  ClutterColor *stroke_color;
+  gboolean fill;
+  ClutterColor *fill_color;
+  gboolean stroke;
+  gdouble stroke_width;
+  gboolean visible;
+  gboolean mark_points;
+};
+
+G_DEFINE_TYPE (ChamplainPolygon, champlain_polygon, CLUTTER_TYPE_GROUP)
 
 #define GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_POLYGON, ChamplainPolygonPrivate))
@@ -60,7 +73,7 @@ champlain_polygon_get_property (GObject *object,
     GValue *value,
     GParamSpec *pspec)
 {
-  ChamplainPolygonPrivate *priv = CHAMPLAIN_POLYGON (object)->priv;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (object);
 
   switch (property_id)
     {
@@ -99,7 +112,7 @@ champlain_polygon_set_property (GObject *object,
     const GValue *value,
     GParamSpec *pspec)
 {
-  ChamplainPolygonPrivate *priv = CHAMPLAIN_POLYGON (object)->priv;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (object);
 
   switch (property_id)
     {
@@ -144,22 +157,14 @@ champlain_polygon_set_property (GObject *object,
 static void
 champlain_polygon_dispose (GObject *object)
 {
-  ChamplainPolygonPrivate *priv = GET_PRIVATE (object);
-
-  if (priv->actor != NULL)
-    {
-      g_object_unref (priv->actor);
-      priv->actor = NULL;
-    }
-
-  champlain_polygon_clear_points (CHAMPLAIN_POLYGON (object));
-
   G_OBJECT_CLASS (champlain_polygon_parent_class)->dispose (object);
 }
 
 static void
 champlain_polygon_finalize (GObject *object)
 {
+  champlain_polygon_clear_points (CHAMPLAIN_POLYGON (object));
+
   G_OBJECT_CLASS (champlain_polygon_parent_class)->finalize (object);
 }
 
@@ -297,17 +302,17 @@ champlain_polygon_class_init (ChamplainPolygonClass *klass)
 static void
 champlain_polygon_init (ChamplainPolygon *polygon)
 {
-  polygon->priv = GET_PRIVATE (polygon);
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
 
-  polygon->priv->visible = TRUE;
-  polygon->priv->points = NULL;
-  polygon->priv->fill = FALSE;
-  polygon->priv->stroke = TRUE;
-  polygon->priv->stroke_width = 2.0;
-  polygon->priv->mark_points = FALSE;
+  priv->visible = TRUE;
+  priv->points = NULL;
+  priv->fill = FALSE;
+  priv->stroke = TRUE;
+  priv->stroke_width = 2.0;
+  priv->mark_points = FALSE;
 
-  polygon->priv->fill_color = clutter_color_copy (&DEFAULT_FILL_COLOR);
-  polygon->priv->stroke_color = clutter_color_copy (&DEFAULT_STROKE_COLOR);
+  priv->fill_color = clutter_color_copy (&DEFAULT_FILL_COLOR);
+  priv->stroke_color = clutter_color_copy (&DEFAULT_STROKE_COLOR);
 }
 
 /**
@@ -342,9 +347,11 @@ champlain_polygon_append_point (ChamplainPolygon *polygon,
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), NULL);
 
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
   ChamplainPoint *point = champlain_point_new (lat, lon);
 
-  polygon->priv->points = g_list_append (polygon->priv->points, point);
+  priv->points = g_list_append (priv->points, point);
   g_object_notify (G_OBJECT (polygon), "visible");
   return point;
 }
@@ -370,9 +377,11 @@ champlain_polygon_insert_point (ChamplainPolygon *polygon,
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), NULL);
 
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
   ChamplainPoint *point = champlain_point_new (lat, lon);
 
-  polygon->priv->points = g_list_insert (polygon->priv->points, point, pos);
+  priv->points = g_list_insert (priv->points, point, pos);
   g_object_notify (G_OBJECT (polygon), "visible");
   return point;
 }
@@ -392,7 +401,9 @@ champlain_polygon_remove_point (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->points = g_list_remove (polygon->priv->points, point);
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->points = g_list_remove (priv->points, point);
   g_object_notify (G_OBJECT (polygon), "visible");
 }
 
@@ -409,14 +420,16 @@ champlain_polygon_clear_points (ChamplainPolygon *polygon)
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  GList *next = polygon->priv->points;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  GList *next = priv->points;
   while (next != NULL)
   {
     champlain_point_free (next->data);
     next = g_list_next (next);
   }
-  g_list_free (polygon->priv->points);
-  polygon->priv->points = NULL;
+  g_list_free (priv->points);
+  priv->points = NULL;
   g_object_notify (G_OBJECT (polygon), "visible");
 }
 
@@ -433,7 +446,9 @@ champlain_polygon_get_points (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), NULL);
 
-  return polygon->priv->points;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->points;
 }
 
 /**
@@ -452,13 +467,13 @@ champlain_polygon_set_fill_color (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  ChamplainPolygonPrivate *priv = polygon->priv;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
 
   if (priv->fill_color != NULL)
     clutter_color_free (priv->fill_color);
 
   if (color == NULL)
-     color = &DEFAULT_FILL_COLOR;
+    color = &DEFAULT_FILL_COLOR;
 
   priv->fill_color = clutter_color_copy (color);
   g_object_notify (G_OBJECT (polygon), "fill-color");
@@ -480,13 +495,13 @@ champlain_polygon_set_stroke_color (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  ChamplainPolygonPrivate *priv = polygon->priv;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
 
   if (priv->stroke_color != NULL)
     clutter_color_free (priv->stroke_color);
 
   if (color == NULL)
-     color = &DEFAULT_STROKE_COLOR;
+    color = &DEFAULT_STROKE_COLOR;
 
   priv->stroke_color = clutter_color_copy (color);
   g_object_notify (G_OBJECT (polygon), "stroke-color");
@@ -505,7 +520,9 @@ champlain_polygon_get_fill_color (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), NULL);
 
-  return polygon->priv->fill_color;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->fill_color;
 }
 
 /**
@@ -521,7 +538,9 @@ champlain_polygon_get_stroke_color (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), NULL);
 
-  return polygon->priv->stroke_color;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->stroke_color;
 }
 
 /**
@@ -539,7 +558,9 @@ champlain_polygon_set_stroke (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->stroke = value;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->stroke = value;
   g_object_notify (G_OBJECT (polygon), "stroke");
 }
 
@@ -556,7 +577,9 @@ champlain_polygon_get_stroke (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), FALSE);
 
-  return polygon->priv->stroke;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->stroke;
 }
 
 /**
@@ -574,7 +597,9 @@ champlain_polygon_set_fill (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->fill = value;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->fill = value;
   g_object_notify (G_OBJECT (polygon), "fill");
 }
 
@@ -591,7 +616,9 @@ champlain_polygon_get_fill (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), FALSE);
 
-  return polygon->priv->fill;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->fill;
 }
 
 /**
@@ -609,7 +636,9 @@ champlain_polygon_set_stroke_width (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->stroke_width = value;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->stroke_width = value;
   g_object_notify (G_OBJECT (polygon), "stroke-width");
 }
 
@@ -626,7 +655,9 @@ champlain_polygon_get_stroke_width (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), 0);
 
-  return polygon->priv->stroke_width;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->stroke_width;
 }
 
 /**
@@ -645,7 +676,9 @@ champlain_polygon_set_mark_points (ChamplainPolygon *polygon,
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->mark_points = value;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->mark_points = value;
   g_object_notify (G_OBJECT (polygon), "mark-points");
 }
 
@@ -662,7 +695,9 @@ champlain_polygon_get_mark_points (ChamplainPolygon *polygon)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_POLYGON (polygon), FALSE);
 
-  return polygon->priv->mark_points;
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  return priv->mark_points;
 }
 
 /**
@@ -678,9 +713,10 @@ champlain_polygon_show (ChamplainPolygon *polygon)
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->visible = TRUE;
-  if (polygon->priv->actor != NULL)
-    clutter_actor_show (polygon->priv->actor);
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->visible = TRUE;
+  clutter_actor_show (CLUTTER_ACTOR (polygon));
   g_object_notify (G_OBJECT (polygon), "visible");
 }
 
@@ -697,8 +733,100 @@ champlain_polygon_hide (ChamplainPolygon *polygon)
 {
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  polygon->priv->visible = FALSE;
-  if (polygon->priv->actor != NULL)
-    clutter_actor_hide (polygon->priv->actor);
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+
+  priv->visible = FALSE;
+  clutter_actor_hide (CLUTTER_ACTOR (polygon));
   g_object_notify (G_OBJECT (polygon), "visible");
 }
+
+void
+champlain_polygon_draw_polygon (ChamplainPolygon *polygon,
+                                ChamplainMapSource *map_source,
+                                guint zoom_level,
+                                gfloat width, gfloat height,
+                                gfloat shift_x, gfloat shift_y)
+{
+  ChamplainPolygonPrivate *priv = GET_PRIVATE (polygon);
+  ClutterActor *cairo_texture;
+  cairo_t *cr;
+
+  if (!priv->visible)
+    return;
+
+  clutter_group_remove_all (CLUTTER_GROUP (polygon));
+  cairo_texture = clutter_cairo_texture_new (width, height);
+  clutter_container_add_actor (CLUTTER_CONTAINER (polygon), cairo_texture);
+
+  cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (cairo_texture));
+
+  /* Clear the drawing area */
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  cairo_rectangle (cr, 0, 0, width, height);
+  cairo_fill (cr);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+  GList *list = g_list_first (priv->points);
+  while (list != NULL)
+    {
+      ChamplainPoint *point = (ChamplainPoint*) list->data;
+      gfloat x, y;
+
+      x = champlain_map_source_get_x (map_source, zoom_level, point->lon);
+      y = champlain_map_source_get_y (map_source, zoom_level, point->lat);
+
+      x -= shift_x;
+      y -= shift_y;
+
+      cairo_line_to (cr, x, y);
+
+      list = list->next;
+    }
+
+  if (priv->closed_path)
+    cairo_close_path (cr);
+
+  cairo_set_source_rgba (cr,
+      priv->fill_color->red / 255.0,
+      priv->fill_color->green / 255.0,
+      priv->fill_color->blue / 255.0,
+      priv->fill_color->alpha / 255.0);
+
+  if (priv->fill)
+    cairo_fill_preserve (cr);
+
+  cairo_set_source_rgba (cr,
+      priv->stroke_color->red / 255.0,
+      priv->stroke_color->green / 255.0,
+      priv->stroke_color->blue / 255.0,
+      priv->stroke_color->alpha / 255.0);
+
+  cairo_set_line_width (cr, priv->stroke_width);
+
+  if (priv->stroke)
+    cairo_stroke (cr);
+
+  if (priv->mark_points)
+    {
+      /* Draw points */
+      GList *list = g_list_first (priv->points);
+      while (list != NULL)
+        {
+          ChamplainPoint *point = (ChamplainPoint*) list->data;
+          gfloat x, y;
+
+          x = champlain_map_source_get_x (map_source, zoom_level, point->lon);
+          y = champlain_map_source_get_y (map_source, zoom_level, point->lat);
+
+          x -= shift_x;
+          y -= shift_y;
+
+          cairo_arc (cr, x, y, priv->stroke_width * 1.5, 0, 2 * M_PI);
+          cairo_fill (cr);
+
+          list = list->next;
+        }
+    }
+
+  cairo_destroy (cr);
+}
diff --git a/champlain/champlain-polygon.h b/champlain/champlain-polygon.h
index f0eea35..2488b4f 100644
--- a/champlain/champlain-polygon.h
+++ b/champlain/champlain-polygon.h
@@ -24,6 +24,7 @@
 #define CHAMPLAIN_POLYGON_H
 
 #include <champlain/champlain-point.h>
+#include <champlain/champlain-defines.h>
 
 #include <glib-object.h>
 #include <clutter/clutter.h>
@@ -53,12 +54,11 @@ typedef struct _ChamplainPolygon        ChamplainPolygon;
 typedef struct _ChamplainPolygonClass   ChamplainPolygonClass;
 
 struct _ChamplainPolygon {
-  GInitiallyUnowned parent;
-  ChamplainPolygonPrivate *priv;
+  ClutterGroup parent;
 };
 
 struct _ChamplainPolygonClass {
-  GInitiallyUnownedClass parent_class;
+  ClutterGroupClass parent_class;
 };
 
 GType champlain_polygon_get_type (void);
@@ -100,6 +100,12 @@ gboolean champlain_polygon_get_mark_points (ChamplainPolygon *polygon);
 void champlain_polygon_show (ChamplainPolygon *polygon);
 void champlain_polygon_hide (ChamplainPolygon *polygon);
 
+void champlain_polygon_draw_polygon (ChamplainPolygon *polygon,
+                                     ChamplainMapSource *map_source,
+                                     guint zoom_level,
+                                     gfloat width, gfloat height,
+                                     gfloat shift_x, gfloat shift_y);
+
 G_END_DECLS
 
 #endif
diff --git a/champlain/champlain-private.h b/champlain/champlain-private.h
index 7455fe7..66739e0 100644
--- a/champlain/champlain-private.h
+++ b/champlain/champlain-private.h
@@ -38,19 +38,6 @@ struct _ChamplainBaseMarkerPrivate
   gboolean highlighted;
 };
 
-struct _ChamplainPolygonPrivate {
-  GList *points;
-  gboolean closed_path;
-  ClutterColor *stroke_color;
-  gboolean fill;
-  ClutterColor *fill_color;
-  gboolean stroke;
-  gdouble stroke_width;
-  ClutterActor *actor;
-  gboolean visible;
-  gboolean mark_points;
-};
-
 typedef struct
 {
   gfloat x;
diff --git a/champlain/champlain-tile.c b/champlain/champlain-tile.c
index e68e1ed..e04dd03 100644
--- a/champlain/champlain-tile.c
+++ b/champlain/champlain-tile.c
@@ -25,7 +25,6 @@
 #include "champlain-tile.h"
 
 #include "champlain-enum-types.h"
-#include "champlain-map.h"
 #include "champlain-private.h"
 
 #include <math.h>
@@ -35,7 +34,7 @@
 #include <gio/gio.h>
 #include <clutter/clutter.h>
 
-G_DEFINE_TYPE (ChamplainTile, champlain_tile, G_TYPE_OBJECT)
+G_DEFINE_TYPE (ChamplainTile, champlain_tile, CLUTTER_TYPE_GROUP)
 
 #define GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_TILE, ChamplainTilePrivate))
@@ -48,7 +47,6 @@ enum
   PROP_ZOOM_LEVEL,
   PROP_SIZE,
   PROP_STATE,
-  PROP_ACTOR,
   PROP_CONTENT,
   PROP_ETAG
 };
@@ -60,7 +58,6 @@ struct _ChamplainTilePrivate {
   gint zoom_level; /* The tile's zoom level */
 
   ChamplainState state; /* The tile state: loading, validation, done */
-  ClutterActor *actor; /* An actor grouping all content actors */
   ClutterActor *content_actor; /* The actual tile actor */
 
   GTimeVal *modified_time; /* The last modified time of the cache */
@@ -91,9 +88,6 @@ champlain_tile_get_property (GObject *object,
       case PROP_STATE:
         g_value_set_enum (value, champlain_tile_get_state (self));
         break;
-      case PROP_ACTOR:
-        g_value_set_object (value, champlain_tile_get_actor (self));
-        break;
       case PROP_CONTENT:
         g_value_set_object (value, champlain_tile_get_content (self));
         break;
@@ -143,20 +137,6 @@ champlain_tile_set_property (GObject *object,
 static void
 champlain_tile_dispose (GObject *object)
 {
-  ChamplainTilePrivate *priv = CHAMPLAIN_TILE (object)->priv;
-
-  if (priv->actor != NULL)
-    {
-      g_object_unref (G_OBJECT (priv->actor));
-      priv->actor = NULL;
-    }
-
-  if (priv->content_actor != NULL)
-    {
-      g_object_unref (G_OBJECT (priv->content_actor));
-      priv->content_actor = NULL;
-    }
-
   G_OBJECT_CLASS (champlain_tile_parent_class)->dispose (object);
 }
 
@@ -165,7 +145,7 @@ champlain_tile_dispose (GObject *object)
 static void
 champlain_tile_finalize (GObject *object)
 {
-  ChamplainTilePrivate *priv = CHAMPLAIN_TILE (object)->priv;
+  ChamplainTilePrivate *priv = GET_PRIVATE (object);
 
   g_free (priv->modified_time);
   g_free (priv->etag);
@@ -270,22 +250,6 @@ champlain_tile_class_init (ChamplainTileClass *klass)
           G_PARAM_READWRITE));
 
   /**
-  * ChamplainTile:actor:
-  *
-  * The #ClutterActor where the tile content is rendered.  Should never change
-  * during the tile's life.
-  *
-  * Since: 0.4
-  */
-  g_object_class_install_property (object_class,
-      PROP_ACTOR,
-      g_param_spec_object ("actor",
-          "Actor",
-          "The tile's actor",
-          CLUTTER_TYPE_ACTOR,
-          G_PARAM_READABLE));
-
-  /**
   * ChamplainTile:content:
   *
   * The #ClutterActor with the specific image content.  When changing this
@@ -324,7 +288,6 @@ static void
 champlain_tile_init (ChamplainTile *self)
 {
   ChamplainTilePrivate *priv = GET_PRIVATE (self);
-  self->priv = priv;
 
   priv->state = CHAMPLAIN_STATE_INIT;
   priv->x = 0;
@@ -334,9 +297,6 @@ champlain_tile_init (ChamplainTile *self)
   priv->modified_time = NULL;
   priv->etag = NULL;
 
-  priv->actor = g_object_ref (clutter_group_new ());
-  g_object_add_weak_pointer (G_OBJECT (priv->actor), (gpointer*)&priv->actor);
-
   priv->content_actor = NULL;
 }
 
@@ -366,7 +326,7 @@ champlain_tile_get_x (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), 0);
 
-  return self->priv->x;
+  return GET_PRIVATE (self)->x;
 }
 
 /**
@@ -382,7 +342,7 @@ champlain_tile_get_y (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), 0);
 
-  return self->priv->y;
+  return GET_PRIVATE (self)->y;
 }
 
 /**
@@ -398,7 +358,7 @@ champlain_tile_get_zoom_level (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), 0);
 
-  return self->priv->zoom_level;
+  return GET_PRIVATE (self)->zoom_level;
 }
 
 /**
@@ -414,7 +374,7 @@ champlain_tile_get_size (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), 0);
 
-  return self->priv->size;
+  return GET_PRIVATE (self)->size;
 }
 
 /**
@@ -430,24 +390,7 @@ champlain_tile_get_state (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), CHAMPLAIN_STATE_NONE);
 
-  return self->priv->state;
-}
-
-/**
- * champlain_tile_get_actor:
- * @self: the #ChamplainTile
- *
- * Returns: the tile's actor.  This actor should not change during the tile's
- * lifetime. You should not unref this actor, it is owned by the tile.
- *
- * Since: 0.4
- */
-ClutterActor *
-champlain_tile_get_actor (ChamplainTile *self)
-{
-  g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
-
-  return self->priv->actor;
+  return GET_PRIVATE (self)->state;
 }
 
 /**
@@ -465,7 +408,7 @@ champlain_tile_set_x (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  self->priv->x = x;
+  GET_PRIVATE (self)->x = x;
 
   g_object_notify (G_OBJECT (self), "x");
 }
@@ -485,7 +428,7 @@ champlain_tile_set_y (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  self->priv->y = y;
+  GET_PRIVATE (self)->y = y;
 
   g_object_notify (G_OBJECT (self), "y");
 }
@@ -505,7 +448,7 @@ champlain_tile_set_zoom_level (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  self->priv->zoom_level = zoom_level;
+  GET_PRIVATE (self)->zoom_level = zoom_level;
 
   g_object_notify (G_OBJECT (self), "zoom-level");
 }
@@ -525,7 +468,7 @@ champlain_tile_set_size (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  self->priv->size = size;
+  GET_PRIVATE (self)->size = size;
 
   g_object_notify (G_OBJECT (self), "size");
 }
@@ -545,7 +488,7 @@ champlain_tile_set_state (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  self->priv->state = state;
+  GET_PRIVATE (self)->state = state;
 
   g_object_notify (G_OBJECT (self), "state");
 }
@@ -584,7 +527,7 @@ champlain_tile_get_modified_time (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
 
-  return self->priv->modified_time;
+  return GET_PRIVATE (self)->modified_time;
 }
 
 /**
@@ -603,7 +546,7 @@ champlain_tile_set_modified_time (ChamplainTile *self,
   g_return_if_fail (CHAMPLAIN_TILE (self));
   g_return_if_fail (time != NULL);
 
-  ChamplainTilePrivate *priv = self->priv;
+  ChamplainTilePrivate *priv = GET_PRIVATE (self);
 
   g_free (priv->modified_time);
   priv->modified_time = g_memdup(time_, sizeof (GTimeVal));
@@ -622,7 +565,7 @@ champlain_tile_get_modified_time_string (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
 
-  ChamplainTilePrivate *priv = self->priv;
+  ChamplainTilePrivate *priv = GET_PRIVATE (self);
 
   if (priv->modified_time == NULL)
     return NULL;
@@ -648,7 +591,7 @@ champlain_tile_get_etag (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), "");
 
-  return self->priv->etag;
+  return GET_PRIVATE (self)->etag;
 }
 
 /**
@@ -666,7 +609,7 @@ champlain_tile_set_etag (ChamplainTile *self,
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
 
-  ChamplainTilePrivate *priv = self->priv;
+  ChamplainTilePrivate *priv = GET_PRIVATE (self);
 
   g_free (priv->etag);
   priv->etag = g_strdup (etag);
@@ -674,25 +617,22 @@ champlain_tile_set_etag (ChamplainTile *self,
 }
 
 typedef struct {
-  ChamplainTile *tile;
   ClutterActor *old_actor;
-} AnimationContext;
+} FadeInCompletedData;
 
 static void
 fade_in_completed (ClutterAnimation *animation,
-    ClutterActor *old_actor)
+    FadeInCompletedData *data)
 {
-  ClutterActor *parent;
-
-  if (old_actor == NULL)
-    return;
-
-  parent = clutter_actor_get_parent (old_actor);
+  ClutterActor *old_actor = data->old_actor;
 
-  if (parent != NULL)
-    clutter_container_remove (CLUTTER_CONTAINER (parent), old_actor, NULL);
+  if (old_actor)
+    {
+      g_object_remove_weak_pointer (G_OBJECT (old_actor), (gpointer*)&data->old_actor);
+      clutter_actor_destroy (old_actor);
+    }
 
-  g_object_unref (old_actor);
+  g_free(data);
 }
 
 /**
@@ -711,30 +651,25 @@ champlain_tile_set_content (ChamplainTile *self,
     gboolean fade_in)
 {
   g_return_if_fail (CHAMPLAIN_TILE (self));
-  g_return_if_fail (actor != NULL);
+  g_return_if_fail (CLUTTER_ACTOR (actor));
 
-  ChamplainTilePrivate *priv = self->priv;
-  ClutterActor *old_actor = NULL;
+  ChamplainTilePrivate *priv = GET_PRIVATE (self);
 
-  if (priv->content_actor != NULL)
+  if (priv->content_actor)
     {
       /* it sometimes happen that the priv->content_actor has been destroyed,
        * this assert will help determine when with no impact on the user */
       g_assert (CLUTTER_IS_ACTOR (priv->content_actor));
 
-      if (fade_in == TRUE)
-        old_actor = g_object_ref (priv->content_actor);
-      else if (priv->actor != NULL)
-        clutter_container_remove (CLUTTER_CONTAINER (priv->actor), priv->content_actor, NULL);
-
-      g_object_unref (priv->content_actor);
+      if (!fade_in)
+        clutter_container_remove_actor (CLUTTER_CONTAINER (self), priv->content_actor);
     }
 
-  if (priv->actor != NULL)
-    clutter_container_add (CLUTTER_CONTAINER (priv->actor), actor, NULL);
+  clutter_container_add_actor (CLUTTER_CONTAINER (self), actor);
 
-  if (fade_in == TRUE && priv->actor != NULL)
+  if (fade_in)
     {
+      FadeInCompletedData *data;
       ClutterAnimation *animation;
 
       clutter_actor_set_opacity (actor, 0);
@@ -745,10 +680,16 @@ champlain_tile_set_content (ChamplainTile *self,
           "opacity", 255,
           NULL);
 
-      g_signal_connect (animation, "completed", G_CALLBACK (fade_in_completed), old_actor);
+      data = g_new (FadeInCompletedData, 1);
+      data->old_actor = priv->content_actor;
+
+      if (data->old_actor)
+        g_object_add_weak_pointer (G_OBJECT (data->old_actor), (gpointer*)&data->old_actor);
+
+      g_signal_connect (animation, "completed", G_CALLBACK (fade_in_completed), data);
     }
 
-  priv->content_actor = g_object_ref (actor);
+  priv->content_actor = actor;
 
   g_object_notify (G_OBJECT (self), "content");
 }
@@ -767,6 +708,5 @@ champlain_tile_get_content (ChamplainTile *self)
 {
   g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
 
-  return self->priv->content_actor;
+  return GET_PRIVATE (self)->content_actor;
 }
-
diff --git a/champlain/champlain-tile.h b/champlain/champlain-tile.h
index 8451f64..2ee4863 100644
--- a/champlain/champlain-tile.h
+++ b/champlain/champlain-tile.h
@@ -49,13 +49,11 @@ typedef struct _ChamplainTile        ChamplainTile;
 typedef struct _ChamplainTileClass   ChamplainTileClass;
 
 struct _ChamplainTile {
-  GObject parent;
-
-  ChamplainTilePrivate *priv;
+  ClutterGroup parent;
 };
 
 struct _ChamplainTileClass {
-  GObjectClass parent_class;
+  ClutterGroupClass parent_class;
 };
 
 GType champlain_tile_get_type (void);
@@ -71,7 +69,6 @@ gint champlain_tile_get_y (ChamplainTile *self);
 gint champlain_tile_get_zoom_level (ChamplainTile *self);
 guint champlain_tile_get_size (ChamplainTile *self);
 ChamplainState champlain_tile_get_state (ChamplainTile *self);
-ClutterActor * champlain_tile_get_actor (ChamplainTile *self);
 ClutterActor * champlain_tile_get_content (ChamplainTile *self);
 const GTimeVal * champlain_tile_get_modified_time (ChamplainTile *self);
 gchar * champlain_tile_get_modified_time_string (ChamplainTile *self);
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index 064c799..2be77a8 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -55,7 +55,6 @@
 #include "champlain.h"
 #include "champlain-defines.h"
 #include "champlain-enum-types.h"
-#include "champlain-map.h"
 #include "champlain-marshal.h"
 #include "champlain-map-source.h"
 #include "champlain-map-source-factory.h"
@@ -144,7 +143,7 @@ struct _ChamplainViewPrivate
   gdouble anchor_zoom_level; /* the zoom_level for which the current anchor has
                                 been computed for */
 
-  Map *map; /* Contains the current map model */
+  ChamplainZoomLevel *map_zoom_level;
 
   ClutterActor *finger_scroll; /* Contains the viewport */
   ClutterActor *viewport;  /* Contains the map_layer, license and markers */
@@ -175,7 +174,6 @@ struct _ChamplainViewPrivate
   guint polygon_redraw_id;
 
   /* Lines and shapes */
-  GList *polygons;
   ClutterActor *polygon_layer;  /* Contains the polygons */
 
 };
@@ -252,9 +250,6 @@ viewport_get_longitude_at (ChamplainViewPrivate *priv, gint x)
 static gdouble
 viewport_get_current_longitude (ChamplainViewPrivate *priv)
 {
-  if (!priv->map)
-    return 0.0;
-
   return viewport_get_longitude_at (priv, priv->anchor.x +
       priv->viewport_size.x + priv->viewport_size.width / 2.0);
 }
@@ -272,9 +267,6 @@ viewport_get_latitude_at (ChamplainViewPrivate *priv, gint y)
 static gdouble
 viewport_get_current_latitude (ChamplainViewPrivate *priv)
 {
-  if (!priv->map)
-    return 0.0;
-
   return viewport_get_latitude_at (priv,
       priv->anchor.y + priv->viewport_size.y +
       priv->viewport_size.height / 2.0);
@@ -286,7 +278,7 @@ update_viewport (ChamplainView *view,
     gfloat x,
     gfloat y)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gfloat lat, lon;
 
   ChamplainFloatPoint old_anchor;
@@ -337,9 +329,10 @@ static void
 panning_completed (TidyFingerScroll *scroll,
                    ChamplainView *view)
 {
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gfloat x, y;
 
-  tidy_viewport_get_origin (TIDY_VIEWPORT (view->priv->viewport), &x, &y,
+  tidy_viewport_get_origin (TIDY_VIEWPORT (priv->viewport), &x, &y,
       NULL);
 
   update_viewport (view, x, y);
@@ -350,7 +343,7 @@ scroll_event (ClutterActor *actor,
     ClutterScrollEvent *event,
     ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   gint zoom_level = priv->zoom_level;
 
@@ -366,20 +359,17 @@ static void
 marker_reposition_cb (ChamplainMarker *marker,
     ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ChamplainBaseMarkerPrivate *marker_priv = CHAMPLAIN_BASE_MARKER(marker)->priv;
 
   gint x, y;
 
-  if (priv->map)
-    {
-      x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, marker_priv->lon);
-      y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, marker_priv->lat);
+  x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, marker_priv->lon);
+  y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, marker_priv->lat);
 
-      clutter_actor_set_position (CLUTTER_ACTOR (marker),
-        x - priv->anchor.x,
-        y - priv->anchor.y);
-    }
+  clutter_actor_set_position (CLUTTER_ACTOR (marker),
+    x - priv->anchor.x,
+    y - priv->anchor.y);
 }
 
 static void
@@ -421,108 +411,25 @@ static gboolean
 marker_reposition (gpointer data)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (data);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   clutter_container_foreach (CLUTTER_CONTAINER (priv->user_layers),
       CLUTTER_CALLBACK (layer_reposition_cb), view);
   return FALSE;
 }
 
-static void
-draw_polygon (ChamplainView *view, ChamplainPolygon *polygon)
-{
-  cairo_t *cr;
-  ChamplainViewPrivate *priv = view->priv;
-
-  if (polygon->priv->visible == FALSE)
-    return;
-
-  cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (polygon->priv->actor));
-
-  /* Clear the drawing area */
-  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
-  cairo_rectangle (cr, 0, 0,
-      view->priv->viewport_size.width,
-      view->priv->viewport_size.height);
-  cairo_fill (cr);
-
-  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-  GList *list = g_list_first (polygon->priv->points);
-  while (list != NULL)
-    {
-      ChamplainPoint *point = (ChamplainPoint*) list->data;
-      gfloat x, y;
-
-      x = champlain_map_source_get_x (priv->map_source, priv->zoom_level,
-          point->lon);
-      y = champlain_map_source_get_y (priv->map_source, priv->zoom_level,
-          point->lat);
-
-      x -= priv->viewport_size.x + priv->anchor.x;
-      y -= priv->viewport_size.y + priv->anchor.y;
-
-      cairo_line_to (cr, x, y);
-
-      list = list->next;
-    }
-
-  if (polygon->priv->closed_path)
-    cairo_close_path (cr);
-
-  cairo_set_source_rgba (cr,
-      polygon->priv->fill_color->red / 255.0,
-      polygon->priv->fill_color->green / 255.0,
-      polygon->priv->fill_color->blue / 255.0,
-      polygon->priv->fill_color->alpha / 255.0);
-
-  if (polygon->priv->fill)
-    cairo_fill_preserve (cr);
-
-  cairo_set_source_rgba (cr,
-      polygon->priv->stroke_color->red / 255.0,
-      polygon->priv->stroke_color->green / 255.0,
-      polygon->priv->stroke_color->blue / 255.0,
-      polygon->priv->stroke_color->alpha / 255.0);
-
-  cairo_set_line_width (cr, polygon->priv->stroke_width);
-
-  if (polygon->priv->stroke)
-    cairo_stroke (cr);
-
-  if (polygon->priv->mark_points)
-    {
-      /* Draw points */
-      GList *list = g_list_first (polygon->priv->points);
-      while (list != NULL)
-        {
-          ChamplainPoint *point = (ChamplainPoint*) list->data;
-          gfloat x, y;
-
-          x = champlain_map_source_get_x (priv->map_source, priv->zoom_level,
-              point->lon);
-          y = champlain_map_source_get_y (priv->map_source, priv->zoom_level,
-              point->lat);
-
-          x -= priv->viewport_size.x + priv->anchor.x;
-          y -= priv->viewport_size.y + priv->anchor.y;
-
-          cairo_arc (cr, x, y, polygon->priv->stroke_width * 1.5, 0, 2 * M_PI);
-          cairo_fill (cr);
-
-          list = list->next;
-        }
-    }
-
-  cairo_destroy (cr);
-}
-
 static gboolean
 redraw_polygon_on_idle (PolygonRedrawContext *ctx)
 {
+  ChamplainViewPrivate *priv = GET_PRIVATE(ctx->view);
 
   if (ctx->polygon)
-    draw_polygon (ctx->view, ctx->polygon);
+    champlain_polygon_draw_polygon (ctx->polygon,
+                                    priv->map_source,
+                                    priv->zoom_level,
+                                    priv->viewport_size.width, priv->viewport_size.height,
+                                    priv->viewport_size.x + priv->anchor.x, priv->viewport_size.y + priv->anchor.y);
 
-  ctx->view->priv->polygon_redraw_id = 0;
+  priv->polygon_redraw_id = 0;
   // ctx is freed by g_idle_add_full
   return FALSE;
 }
@@ -532,9 +439,10 @@ notify_polygon_cb (ChamplainPolygon *polygon,
     GParamSpec *arg1,
     ChamplainView *view)
 {
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   PolygonRedrawContext *ctx;
 
-  if (view->priv->polygon_redraw_id != 0)
+  if (priv->polygon_redraw_id != 0)
     return;
 
   ctx = g_new0 (PolygonRedrawContext, 1);
@@ -542,7 +450,7 @@ notify_polygon_cb (ChamplainPolygon *polygon,
   ctx->polygon = polygon;
   g_object_add_weak_pointer (G_OBJECT (polygon), (gpointer *) &ctx->polygon);
 
-  view->priv->polygon_redraw_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+  priv->polygon_redraw_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
       (GSourceFunc) redraw_polygon_on_idle, ctx, g_free);
 }
 
@@ -550,10 +458,10 @@ static void
 resize_viewport (ChamplainView *view)
 {
   gdouble lower, upper;
+  gint i;
   TidyAdjustment *hadjust, *vadjust;
-  GList *polygons;
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   tidy_scrollable_get_adjustments (TIDY_SCROLLABLE (priv->viewport), &hadjust,
       &vadjust);
@@ -593,30 +501,14 @@ resize_viewport (ChamplainView *view)
       priv->viewport_size.height == 0)
     return;
 
-  polygons = priv->polygons;
-  while (polygons != NULL)
+  for (i = 0; i < clutter_group_get_n_children (CLUTTER_GROUP (priv->polygon_layer)); i++)
     {
-      ChamplainPolygon *polygon;
-
-      polygon = CHAMPLAIN_POLYGON (polygons->data);
+      ChamplainPolygon *polygon = CHAMPLAIN_POLYGON (clutter_group_get_nth_child (CLUTTER_GROUP (priv->polygon_layer), i));
 
-      if (polygon->priv->actor != NULL)
-        {
-          g_object_unref (polygon->priv->actor);
-          clutter_container_remove_actor (CLUTTER_CONTAINER (view->priv->polygon_layer),
-              polygon->priv->actor);
-        }
-
-      polygon->priv->actor = g_object_ref (clutter_cairo_texture_new (
-          view->priv->viewport_size.width,
-          view->priv->viewport_size.height));
-      g_object_set (G_OBJECT (polygon->priv->actor), "visible",
-          polygon->priv->visible, NULL);
-      clutter_container_add_actor (CLUTTER_CONTAINER (view->priv->polygon_layer),
-          polygon->priv->actor);
-      clutter_actor_set_position (polygon->priv->actor, 0, 0);
-      draw_polygon (view, polygon);
-      polygons = polygons->next;
+      clutter_actor_set_position (CLUTTER_ACTOR (polygon), 0, 0);
+      champlain_polygon_draw_polygon (polygon, priv->map_source, priv->zoom_level,
+                                      priv->viewport_size.width, priv->viewport_size.height,
+                                      priv->viewport_size.x + priv->anchor.x, priv->viewport_size.y + priv->anchor.y);
     }
 }
 
@@ -627,7 +519,7 @@ champlain_view_get_property (GObject *object,
     GParamSpec *pspec)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (object);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   switch (prop_id)
     {
@@ -697,7 +589,7 @@ champlain_view_set_property (GObject *object,
     GParamSpec *pspec)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (object);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   switch (prop_id)
   {
@@ -757,8 +649,7 @@ static void
 champlain_view_dispose (GObject *object)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (object);
-  ChamplainViewPrivate *priv = view->priv;
-  GList *polygons;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->factory != NULL)
     {
@@ -772,12 +663,24 @@ champlain_view_dispose (GObject *object)
       priv->map_source = NULL;
     }
 
+  if (priv->stage != NULL)
+    {
+      g_object_unref (priv->stage);
+      priv->stage = NULL;
+    }
+
   if (priv->license_actor != NULL)
     {
       g_object_unref (priv->license_actor);
       priv->license_actor = NULL;
     }
 
+  if (priv->scale_actor != NULL)
+    {
+      g_object_unref (priv->scale_actor);
+      priv->scale_actor = NULL;
+    }
+
   if (priv->finger_scroll != NULL)
     {
       tidy_finger_scroll_stop (TIDY_FINGER_SCROLL (priv->finger_scroll));
@@ -804,27 +707,18 @@ champlain_view_dispose (GObject *object)
       priv->user_layers = NULL;
     }
 
-  if (priv->stage != NULL)
+  if (priv->polygon_layer != NULL)
     {
-      g_object_unref (priv->stage);
-      priv->stage = NULL;
+      g_object_unref (CLUTTER_ACTOR (priv->polygon_layer));
+      priv->polygon_layer = NULL;
     }
 
-  if (priv->map != NULL)
+  if (priv->map_zoom_level != NULL)
     {
-      map_free (priv->map);
-      priv->map = NULL;
+      g_object_unref (CLUTTER_ACTOR (priv->map_zoom_level));
+      priv->map_zoom_level = NULL;
     }
 
-  polygons = priv->polygons;
-  while (polygons != NULL)
-    {
-      g_object_unref (G_OBJECT (polygons->data));
-      polygons = polygons->next;
-    }
-  g_list_free (priv->polygons);
-  priv->polygons = NULL;
-
   if (priv->goto_context != NULL)
     champlain_view_stop_go_to (view);
 
@@ -834,7 +728,7 @@ champlain_view_dispose (GObject *object)
 static gboolean
 _update_idle_cb (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gdouble lat, lon;
 
   clutter_actor_set_size (priv->finger_scroll,
@@ -862,13 +756,14 @@ _update_idle_cb (ChamplainView *view)
 
   return FALSE;
 }
+
 static void
 champlain_view_allocate (ClutterActor          *actor,
                          const ClutterActorBox *box,
                          ClutterAllocationFlags flags)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (actor);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   guint width, height;
 
   /* Chain up */
@@ -893,8 +788,7 @@ static void
 champlain_view_realize (ClutterActor *actor)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (actor);
-  ChamplainViewPrivate *priv = view->priv;
-  ClutterActor *group;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   /*
    We should be calling this but it segfaults
@@ -903,10 +797,7 @@ champlain_view_realize (ClutterActor *actor)
    */
   clutter_actor_realize (actor);
 
-  priv->map = map_new ();
-  map_load_level (priv->map, priv->map_source, priv->zoom_level);
-  group = champlain_zoom_level_get_actor (priv->map->current_level);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer), group);
+  champlain_zoom_level_zoom_to (priv->map_zoom_level, priv->map_source, priv->zoom_level);
 
   /* Setup the viewport according to the zoom level */
   //resize_viewport (view);
@@ -932,7 +823,7 @@ champlain_view_get_preferred_width (ClutterActor *actor,
                                     gfloat       *nat_width)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (actor);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gint width = champlain_map_source_get_tile_size (priv->map_source);
 
   if (min_width)
@@ -949,7 +840,7 @@ champlain_view_get_preferred_height (ClutterActor *actor,
                                      gfloat       *nat_height)
 {
   ChamplainView *view = CHAMPLAIN_VIEW (actor);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gint height = champlain_map_source_get_tile_size (priv->map_source);
 
   if (min_height)
@@ -1239,7 +1130,7 @@ champlain_view_class_init (ChamplainViewClass *champlainViewClass)
 static void
 create_license (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->license_actor)
     {
@@ -1264,7 +1155,7 @@ button_release_cb (ClutterActor *actor,
 {
   GList *children = NULL;
   gboolean found = FALSE;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (clutter_event_get_button (event) != 1)
     return FALSE;
@@ -1294,7 +1185,7 @@ update_scale (ChamplainView *view)
   gboolean is_small_unit = TRUE;  /* indicates if using meters */
   ClutterActor *text, *line;
   gfloat width;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gfloat m_per_pixel;
   gfloat scale_width = priv->max_scale_width;
   gchar *label;
@@ -1303,9 +1194,6 @@ update_scale (ChamplainView *view)
   gfloat factor;
   gboolean final_unit = FALSE;
 
-  if (!priv->map || !priv->map->current_level)
-    return;
-
   if (priv->show_scale)
     {
       clutter_actor_show (priv->scale_actor);
@@ -1433,7 +1321,7 @@ create_scale (ChamplainView *view)
 {
   ClutterActor *scale, *text;
   gfloat width;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->scale_actor)
     {
@@ -1476,8 +1364,6 @@ champlain_view_init (ChamplainView *view)
 
   champlain_debug_set_flags (g_getenv ("CHAMPLAIN_DEBUG"));
 
-  view->priv = priv;
-
   priv->factory = champlain_map_source_factory_dup_default ();
   source = champlain_map_source_factory_create_cached_source (priv->factory, CHAMPLAIN_MAP_SOURCE_OSM_MAPNIK);
 
@@ -1491,7 +1377,7 @@ champlain_view_init (ChamplainView *view)
   priv->show_license = TRUE;
   priv->license_actor = NULL;
   priv->license_text = NULL;
-  priv->stage = g_object_ref (clutter_group_new ());
+  priv->stage = NULL;
   priv->scroll_mode = CHAMPLAIN_SCROLL_MODE_PUSH;
   priv->viewport_size.x = 0;
   priv->viewport_size.y = 0;
@@ -1504,12 +1390,30 @@ champlain_view_init (ChamplainView *view)
   priv->latitude = 0.0f;
   priv->longitude = 0.0f;
   priv->goto_context = NULL;
-  priv->map = NULL;
+  priv->map_zoom_level = NULL;
   priv->polygon_redraw_id = 0;
   priv->show_scale = FALSE;
   priv->scale_unit = CHAMPLAIN_UNIT_KM;
   priv->max_scale_width = 100;
 
+  /* Setup zoom level */
+  priv->map_zoom_level = g_object_ref (champlain_zoom_level_new ());
+  clutter_actor_show (CLUTTER_ACTOR (priv->map_zoom_level));
+
+  /* Setup map layer */
+  priv->map_layer = g_object_ref (clutter_group_new ());
+  clutter_actor_show (priv->map_layer);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer), CLUTTER_ACTOR (priv->map_zoom_level));
+
+  /* Setup polygon layer */
+  priv->polygon_layer = g_object_ref (clutter_group_new ());
+  clutter_actor_show (priv->polygon_layer);
+
+  /* Setup user_layers */
+  priv->user_layers = g_object_ref (clutter_group_new ());
+  clutter_actor_show (priv->user_layers);
+
   /* Setup viewport */
   priv->viewport = g_object_ref (tidy_viewport_new ());
   g_object_set (G_OBJECT (priv->viewport), "sync-adjustments", FALSE, NULL);
@@ -1519,6 +1423,16 @@ champlain_view_init (ChamplainView *view)
   g_signal_connect (priv->viewport, "notify::y-origin",
       G_CALLBACK (viewport_pos_changed_cb), view);
 
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
+      priv->map_layer);
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
+      priv->polygon_layer);
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
+      priv->user_layers);
+
+  clutter_actor_raise (priv->polygon_layer, priv->map_layer);
+  clutter_actor_raise (priv->user_layers, priv->map_layer);
+
   /* Setup finger scroll */
   priv->finger_scroll = g_object_ref (tidy_finger_scroll_new (priv->scroll_mode));
 
@@ -1526,19 +1440,6 @@ champlain_view_init (ChamplainView *view)
       G_CALLBACK (scroll_event), view);
   g_signal_connect (priv->finger_scroll, "panning-completed",
       G_CALLBACK (panning_completed), view);
-
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->finger_scroll),
-      priv->viewport);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->stage),
-      priv->finger_scroll);
-  clutter_container_add_actor (CLUTTER_CONTAINER (view), priv->stage);
-
-  /* Map Layer */
-  priv->map_layer = g_object_ref (clutter_group_new ());
-  clutter_actor_show (priv->map_layer);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
-      priv->map_layer);
-
   g_signal_connect (priv->finger_scroll, "button-press-event",
       G_CALLBACK (finger_scroll_button_press_cb), view);
   g_signal_connect_after (priv->finger_scroll, "button-release-event",
@@ -1549,21 +1450,16 @@ champlain_view_init (ChamplainView *view)
   g_signal_connect (priv->finger_scroll, "key-press-event",
       G_CALLBACK (finger_scroll_key_press_cb), view);
 
-  /* Setup user_layers */
-  priv->user_layers = g_object_ref (clutter_group_new ());
-  clutter_actor_show (priv->user_layers);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
-      priv->user_layers);
-  clutter_actor_raise (priv->user_layers, priv->map_layer);
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->finger_scroll),
+      priv->viewport);
 
-  priv->polygons = NULL;
+  /* Setup stage */
+  priv->stage = g_object_ref (clutter_group_new ());
 
-  /* Setup polygon layer */
-  priv->polygon_layer = g_object_ref (clutter_group_new ());
-  clutter_actor_show (priv->polygon_layer);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport),
-      priv->polygon_layer);
-  clutter_actor_raise (priv->polygon_layer, priv->map_layer);
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->stage),
+      priv->finger_scroll);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (view), priv->stage);
 
   resize_viewport (view);
 
@@ -1585,7 +1481,7 @@ viewport_pos_changed_cb (GObject *gobject,
     GParamSpec *arg1,
     ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   gfloat x, y;
 
@@ -1626,7 +1522,7 @@ champlain_view_set_size (ChamplainView *view,
 static void
 update_license (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gchar *license;
 
   if (priv->license_text)
@@ -1652,7 +1548,7 @@ finger_scroll_button_press_cb (ClutterActor *actor,
     ClutterButtonEvent *event,
     ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->zoom_on_double_click && event->button == 1 && event->click_count == 2)
     {
@@ -1666,8 +1562,7 @@ scroll_to (ChamplainView *view,
     gint x,
     gint y)
 {
-
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->scroll_mode == CHAMPLAIN_SCROLL_MODE_KINETIC)
     {
@@ -1694,7 +1589,7 @@ champlain_view_scroll_left (ChamplainView* view)
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
   gint x, y;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, priv->longitude);
   y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, priv->latitude);
@@ -1710,7 +1605,7 @@ champlain_view_scroll_right (ChamplainView* view)
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
   gint x, y;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, priv->longitude);
   y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, priv->latitude);
@@ -1726,7 +1621,7 @@ champlain_view_scroll_up (ChamplainView* view)
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
   gint x, y;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, priv->longitude);
   y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, priv->latitude);
@@ -1742,7 +1637,7 @@ champlain_view_scroll_down (ChamplainView* view)
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
   gint x, y;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, priv->longitude);
   y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, priv->latitude);
@@ -1758,7 +1653,6 @@ finger_scroll_key_press_cb (ClutterActor *actor,
     ClutterKeyEvent *event,
     ChamplainView *view)
 {
-
   switch (event->keyval)
   {
     case 65361: // Left
@@ -1807,7 +1701,7 @@ view_update_anchor (ChamplainView *view,
     gint x,  /* Absolute x */
     gint y)  /* Absolute y */
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gboolean need_anchor = FALSE;
   gboolean need_update = FALSE;
 
@@ -1833,7 +1727,7 @@ view_update_anchor (ChamplainView *view,
       if ( priv->anchor.y < 0 )
         priv->anchor.y = 0;
 
-      max = champlain_zoom_level_get_width (priv->map->current_level) *
+      max = champlain_zoom_level_get_width (priv->map_zoom_level) *
           champlain_map_source_get_tile_size (priv->map_source) -
           (G_MAXINT16 / 2);
       if (priv->anchor.x > max)
@@ -1872,14 +1766,11 @@ champlain_view_center_on (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
   gint x, y;
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->longitude = CLAMP (longitude, CHAMPLAIN_MIN_LONG, CHAMPLAIN_MAX_LONG);
   priv->latitude = CLAMP (latitude, CHAMPLAIN_MIN_LAT, CHAMPLAIN_MAX_LAT);
 
-  if (!priv->map)
-    return;
-
   x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, longitude);
   y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, latitude);
 
@@ -1944,7 +1835,7 @@ champlain_view_stop_go_to (ChamplainView *view)
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->goto_context == NULL)
     return;
@@ -1976,9 +1867,10 @@ champlain_view_go_to (ChamplainView *view,
     gdouble latitude,
     gdouble longitude)
 {
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   guint duration;
 
-  duration = 500 * view->priv->zoom_level / 2.0;
+  duration = 500 * priv->zoom_level / 2.0;
   champlain_view_go_to_with_duration (view, latitude, longitude, duration);
 }
 
@@ -1999,7 +1891,7 @@ champlain_view_go_to_with_duration (ChamplainView *view,
 
   GoToContext *ctx;
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   champlain_view_stop_go_to (view);
 
@@ -2045,7 +1937,7 @@ champlain_view_zoom_in (ChamplainView *view)
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   champlain_view_set_zoom_level (view, priv->zoom_level + 1);
 }
@@ -2063,7 +1955,7 @@ champlain_view_zoom_out (ChamplainView *view)
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   champlain_view_set_zoom_level (view, priv->zoom_level - 1);
 }
@@ -2083,7 +1975,7 @@ champlain_view_set_zoom_level (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gdouble longitude;
   gdouble latitude;
 
@@ -2092,13 +1984,9 @@ champlain_view_set_zoom_level (ChamplainView *view,
 
   priv->zoom_level = zoom_level;
 
-  if (priv->map == NULL)
-    return;
-
   champlain_view_stop_go_to (view);
 
-  ClutterActor *group = champlain_zoom_level_get_actor (priv->map->current_level);
-  if (!map_zoom_to (priv->map, priv->map_source, zoom_level))
+  if (!champlain_zoom_level_zoom_to (priv->map_zoom_level, priv->map_source, zoom_level))
     return;
 
   DEBUG ("Zooming to %d", zoom_level);
@@ -2111,9 +1999,6 @@ champlain_view_set_zoom_level (ChamplainView *view,
   latitude = priv->latitude;
   resize_viewport (view);
 
-  ClutterActor *new_group = champlain_zoom_level_get_actor (priv->map->current_level);
-  clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer), group);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer), new_group);
   champlain_view_center_on (view, latitude, longitude);
 
   g_object_notify (G_OBJECT (view), "zoom-level");
@@ -2134,7 +2019,7 @@ champlain_view_set_min_zoom_level (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->min_zoom_level == min_zoom_level ||
       min_zoom_level > priv->max_zoom_level ||
@@ -2162,7 +2047,7 @@ champlain_view_set_max_zoom_level (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->max_zoom_level == max_zoom_level ||
       max_zoom_level < priv->min_zoom_level ||
@@ -2191,13 +2076,12 @@ champlain_view_add_layer (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
   g_return_if_fail (CHAMPLAIN_IS_LAYER (layer));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   clutter_container_add_actor (CLUTTER_CONTAINER (priv->user_layers),
       CLUTTER_ACTOR (layer));
   clutter_actor_raise_top (CLUTTER_ACTOR (layer));
 
-  if (priv->map)
-    g_idle_add (marker_reposition, view);
+  g_idle_add (marker_reposition, view);
 
   g_signal_connect_after (layer, "actor-added",
       G_CALLBACK (layer_add_marker_cb), view);
@@ -2222,7 +2106,7 @@ champlain_view_remove_layer (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
   g_return_if_fail (CHAMPLAIN_IS_LAYER (layer));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   g_signal_handlers_disconnect_by_func (layer,
       G_CALLBACK (layer_add_marker_cb), view);
@@ -2312,7 +2196,7 @@ gboolean champlain_view_get_coords_at (ChamplainView *view,
     gdouble *longitude)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gfloat actor_x, actor_y;
   gdouble rel_x, rel_y;
 
@@ -2334,7 +2218,7 @@ gboolean champlain_view_get_coords_at (ChamplainView *view,
 static void
 view_load_visible_tiles (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ChamplainRectangle viewport = priv->viewport_size;
   gint size;
   ChamplainZoomLevel *level;
@@ -2343,7 +2227,7 @@ view_load_visible_tiles (ChamplainView *view)
   viewport.y += priv->anchor.y;
 
   size = champlain_map_source_get_tile_size (priv->map_source);
-  level = priv->map->current_level;
+  level = priv->map_zoom_level;
 
   if (viewport.x < 0)
     viewport.x = 0;
@@ -2370,16 +2254,10 @@ view_load_visible_tiles (ChamplainView *view)
   guint k = 0;
 
   // Get rid of old tiles first
-  int count = champlain_zoom_level_tile_count (level);
+  int count = clutter_group_get_n_children (CLUTTER_GROUP (level));
   while (k < count)
     {
-      ChamplainTile *tile = champlain_zoom_level_get_nth_tile (level, k);
-
-      if (tile == NULL)
-        {
-          k++;
-          continue;
-        }
+      ChamplainTile *tile = CHAMPLAIN_TILE (clutter_group_get_nth_child (CLUTTER_GROUP (level), k));
 
       gint tile_x = champlain_tile_get_x (tile);
       gint tile_y = champlain_tile_get_y (tile);
@@ -2387,16 +2265,8 @@ view_load_visible_tiles (ChamplainView *view)
       if (tile_x < x_first || tile_x > x_count ||
           tile_y < y_first || tile_y > y_count)
       {
-        ClutterActor *group, *actor;
-        if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE)
-          {
-            actor = champlain_tile_get_actor (tile);
-            group = champlain_zoom_level_get_actor (level);
-            if (actor != NULL)
-              clutter_container_remove_actor (CLUTTER_CONTAINER (group), actor);
-          }
-        champlain_zoom_level_remove_tile (level, tile);
-        count = champlain_zoom_level_tile_count (level);
+        clutter_container_remove_actor (CLUTTER_CONTAINER (level), CLUTTER_ACTOR (tile));
+        count--;
       }
       else
         k++;
@@ -2420,18 +2290,18 @@ view_load_visible_tiles (ChamplainView *view)
                 {
                   gboolean exist = FALSE;
 
-                  for (k = 0; k < champlain_zoom_level_tile_count (level) && !exist; k++)
+                  for (k = 0; k < clutter_group_get_n_children (CLUTTER_GROUP (level)) && !exist; k++)
                     {
-                      ChamplainTile *tile = champlain_zoom_level_get_nth_tile (level, k);
-
-                      if (tile == NULL)
-                        continue;
+                      ChamplainTile *tile = CHAMPLAIN_TILE (clutter_group_get_nth_child (CLUTTER_GROUP (level), k));
 
                       gint tile_x = champlain_tile_get_x (tile);
                       gint tile_y = champlain_tile_get_y (tile);
 
                       if ( tile_x == i && tile_y == j)
-                        exist = TRUE;
+                        {
+                          exist = TRUE;
+                          break;
+                        }
                     }
 
                   if(!exist)
@@ -2442,14 +2312,10 @@ view_load_visible_tiles (ChamplainView *view)
                       tile = champlain_tile_new ();
                       g_object_set (G_OBJECT (tile), "x", i, "y", j, "zoom-level", champlain_zoom_level_get_zoom_level (level), NULL);
                       g_signal_connect (tile, "notify::state", G_CALLBACK (tile_state_notify), view);
-                      clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (level)),
-                          champlain_tile_get_actor (tile), NULL);
+                      clutter_container_add_actor (CLUTTER_CONTAINER (level), CLUTTER_ACTOR (tile));
 
-                      champlain_zoom_level_add_tile (level, tile);
                       champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
                       champlain_map_source_fill_tile (priv->map_source, tile);
-
-                      g_object_unref (tile);
                     }
                 }
               i += dirs[spiral_pos / arm_size + 1];
@@ -2466,17 +2332,14 @@ static void
 view_position_tile (ChamplainView* view,
     ChamplainTile* tile)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   ClutterActor *actor;
   gint x;
   gint y;
   guint size;
 
-  actor = champlain_tile_get_actor (tile);
-
-  if (actor == NULL)
-    return;
+  actor = CLUTTER_ACTOR (tile);
 
   x = champlain_tile_get_x (tile);
   y = champlain_tile_get_y (tile);
@@ -2490,15 +2353,12 @@ view_position_tile (ChamplainView* view,
 static void
 view_tiles_reposition (ChamplainView* view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gint i;
 
-  for (i = 0; i < champlain_zoom_level_tile_count (priv->map->current_level); i++)
+  for (i = 0; i < clutter_group_get_n_children (CLUTTER_GROUP (priv->map_zoom_level)); i++)
     {
-      ChamplainTile *tile = champlain_zoom_level_get_nth_tile (priv->map->current_level, i);
-
-      if (tile == NULL)
-        continue;
+      ChamplainTile *tile = CHAMPLAIN_TILE (clutter_group_get_nth_child (CLUTTER_GROUP (priv->map_zoom_level), i));
 
       if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE)
         view_position_tile (view, tile);
@@ -2509,56 +2369,26 @@ static void
 view_reload_tiles_cb (ChamplainMapSource *map_source,
     ChamplainView* view)
 {
-  ChamplainViewPrivate *priv = view->priv;
-  ChamplainZoomLevel *level;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gint i, tile_count;
 
-  // flush previous_level
-  if (priv->map->previous_level != NULL)
-    {
-      level = priv->map->previous_level;
-      i = 0;
-      while (i < champlain_zoom_level_tile_count (level))
-        {
-          ChamplainTile *tile = champlain_zoom_level_get_nth_tile (level, i);
-
-          if (tile == NULL)
-            {
-              i++;
-              continue;
-            }
-
-          ClutterActor *group, *actor;
-          if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE)
-            {
-              actor = champlain_tile_get_actor (tile);
-              group = champlain_zoom_level_get_actor (level);
-              if (actor != NULL)
-                clutter_container_remove_actor (CLUTTER_CONTAINER (group), actor);
-            }
-          champlain_zoom_level_remove_tile (level, tile);
-        }
-    }
-
   // update current_level
-  level = priv->map->current_level;
-  tile_count = champlain_zoom_level_tile_count (level);
+  tile_count = clutter_group_get_n_children (CLUTTER_GROUP (priv->map_zoom_level));
 
   for (i = 0; i < tile_count; i++)
     {
-      ChamplainTile *tile = champlain_zoom_level_get_nth_tile (level, i);
+      ChamplainTile *tile = CHAMPLAIN_TILE (clutter_group_get_nth_child (CLUTTER_GROUP (priv->map_zoom_level), i));
 
       DEBUG("Reload tile: %d, %d\n", champlain_tile_get_x (tile),
           champlain_tile_get_y (tile));
 
-      if (tile == NULL)
-        continue;
-
+      // TODO - we should destroy the loading tiles (they may be loading
+      // with different parameters of the renderer) and load new tiles instead
       if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADING)
-      {
-        champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
-        champlain_map_source_fill_tile (priv->map_source, tile);
-      }
+        {
+          champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
+          champlain_map_source_fill_tile (priv->map_source, tile);
+        }
     }
   view_update_state (view);
 }
@@ -2575,19 +2405,19 @@ tile_state_notify (GObject *gobject,
 static void
 view_update_state (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ChamplainState new_state = CHAMPLAIN_STATE_DONE;
   gint i;
 
-  for (i = 0; i < champlain_zoom_level_tile_count (priv->map->current_level); i++)
+  for (i = 0; i < clutter_group_get_n_children (CLUTTER_GROUP (priv->map_zoom_level)); i++)
     {
-      ChamplainTile *tile = champlain_zoom_level_get_nth_tile (priv->map->current_level, i);
-
-      if (tile == NULL)
-        continue;
+      ChamplainTile *tile = CHAMPLAIN_TILE (clutter_group_get_nth_child (CLUTTER_GROUP (priv->map_zoom_level), i));
 
       if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADING)
-        new_state = CHAMPLAIN_STATE_LOADING;
+        {
+          new_state = CHAMPLAIN_STATE_LOADING;
+          break;
+        }
     }
 
   if (priv->state != new_state)
@@ -2614,9 +2444,7 @@ champlain_view_set_map_source (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view) &&
       CHAMPLAIN_IS_MAP_SOURCE (source));
 
-  ClutterActor *group;
-
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   if (priv->map_source == source)
     return;
@@ -2627,15 +2455,6 @@ champlain_view_set_map_source (ChamplainView *view,
   priv->min_zoom_level = champlain_map_source_get_min_zoom_level (priv->map_source);
   priv->max_zoom_level = champlain_map_source_get_max_zoom_level (priv->map_source);
 
-  if (priv->map == NULL)
-    return;
-
-  group = champlain_zoom_level_get_actor (priv->map->current_level);
-  clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer), group);
-
-  map_free (priv->map);
-  priv->map = map_new ();
-
   /* Keep same zoom level if the new map supports it */
   if (priv->zoom_level > priv->max_zoom_level)
     {
@@ -2648,11 +2467,9 @@ champlain_view_set_map_source (ChamplainView *view,
       g_object_notify (G_OBJECT (view), "zoom-level");
     }
 
-  map_load_level (priv->map, priv->map_source, priv->zoom_level);
-  group = champlain_zoom_level_get_actor (priv->map->current_level);
+  champlain_zoom_level_zoom_to (priv->map_zoom_level, priv->map_source, priv->zoom_level);
 
   view_load_visible_tiles (view);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer), group);
 
   g_object_notify (G_OBJECT (view), "map-source");
 
@@ -2682,7 +2499,7 @@ champlain_view_set_decel_rate (ChamplainView *view,
       rate < 2.0 &&
       rate > 1.0001);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   g_object_set (priv->finger_scroll, "decel-rate", rate, NULL);
 }
@@ -2702,7 +2519,7 @@ champlain_view_set_scroll_mode (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->scroll_mode = mode;
 
@@ -2725,7 +2542,7 @@ champlain_view_set_keep_center_on_resize (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->keep_center_on_resize = value;
 }
@@ -2746,7 +2563,10 @@ champlain_view_set_license_text (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
+
+  if (priv->license_text)
+    g_free (priv->license_text);
 
   priv->license_text = g_strdup (text);
   update_license (view);
@@ -2769,7 +2589,7 @@ champlain_view_set_show_license (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->show_license = value;
   update_license (view);
@@ -2790,7 +2610,7 @@ champlain_view_set_show_scale (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->show_scale = value;
   update_scale (view);
@@ -2811,7 +2631,7 @@ champlain_view_set_max_scale_width (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->max_scale_width = value;
   create_scale (view);
@@ -2833,7 +2653,7 @@ champlain_view_set_scale_unit (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->scale_unit = unit;
   update_scale (view);
@@ -2854,7 +2674,7 @@ champlain_view_set_zoom_on_double_click (ChamplainView *view,
 {
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   priv->zoom_on_double_click = value;
 }
@@ -2881,7 +2701,7 @@ champlain_view_ensure_visible (ChamplainView *view,
     gdouble lon2,
     gboolean animate)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gint zoom_level = priv->zoom_level;
   gdouble width, height;
   gdouble min_lat,min_lon,max_lat,max_lon;
@@ -2936,6 +2756,7 @@ champlain_view_ensure_visible (ChamplainView *view,
     }
   while (good_size == FALSE);
 
+  // JT question - what's the purpose of this? The condition is never satisfied...
   if (good_size == FALSE)
     {
       zoom_level = priv->min_zoom_level;
@@ -3006,9 +2827,8 @@ view_set_zoom_level_at (ChamplainView *view,
     gint x,
     gint y)
 {
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
-  ClutterActor *group, *new_group;
   gdouble lon, lat;
   gint x_diff, y_diff;
   gfloat actor_x, actor_y;
@@ -3021,7 +2841,6 @@ view_set_zoom_level_at (ChamplainView *view,
 
   champlain_view_stop_go_to (view);
 
-  group = champlain_zoom_level_get_actor (priv->map->current_level);
   clutter_actor_get_transformed_position (priv->finger_scroll, &actor_x, &actor_y);
   rel_x = x - actor_x;
   rel_y = y - actor_y;
@@ -3036,11 +2855,10 @@ view_set_zoom_level_at (ChamplainView *view,
   x_diff = priv->viewport_size.width / 2 - rel_x;
   y_diff = priv->viewport_size.height / 2 - rel_y;
 
-  if (!map_zoom_to (priv->map, priv->map_source, zoom_level))
+  if (!champlain_zoom_level_zoom_to (priv->map_zoom_level, priv->map_source, zoom_level))
     return FALSE;
 
   priv->zoom_level = zoom_level;
-  new_group = champlain_zoom_level_get_actor (priv->map->current_level);
 
   /* Get the new x,y in the new zoom level */
   x2 = champlain_map_source_get_x (priv->map_source, priv->zoom_level, lon);
@@ -3053,10 +2871,6 @@ view_set_zoom_level_at (ChamplainView *view,
       priv->zoom_level, y2 + y_diff);
 
   resize_viewport (view);
-  clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer),
-      group);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer),
-      new_group);
   champlain_view_center_on (view, lat2, lon2);
 
   g_object_notify (G_OBJECT (view), "zoom-level");
@@ -3076,7 +2890,7 @@ champlain_view_get_zoom_level (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), 0);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   return priv->zoom_level;
 }
@@ -3094,7 +2908,7 @@ champlain_view_get_min_zoom_level (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), 0);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   return priv->min_zoom_level;
 }
@@ -3112,7 +2926,7 @@ champlain_view_get_max_zoom_level (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), 0);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   return priv->max_zoom_level;
 }
@@ -3131,7 +2945,7 @@ champlain_view_get_map_source (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), NULL);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   return priv->map_source;
 }
@@ -3149,7 +2963,7 @@ champlain_view_get_decel_rate (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), 0.0);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   gdouble decel = 0.0;
   g_object_get (priv->finger_scroll, "decel-rate", &decel, NULL);
   return decel;
@@ -3168,7 +2982,7 @@ champlain_view_get_scroll_mode (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), CHAMPLAIN_SCROLL_MODE_PUSH);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->scroll_mode;
 }
 
@@ -3185,7 +2999,7 @@ champlain_view_get_keep_center_on_resize (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->keep_center_on_resize;
 }
 
@@ -3202,7 +3016,7 @@ champlain_view_get_show_license (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->show_license;
 }
 
@@ -3219,7 +3033,7 @@ champlain_view_get_license_text (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->license_text;
 }
 
@@ -3237,7 +3051,7 @@ champlain_view_get_show_scale (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->show_scale;
 }
 
@@ -3254,7 +3068,7 @@ champlain_view_get_max_scale_width (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->max_scale_width;
 }
 
@@ -3271,7 +3085,7 @@ champlain_view_get_scale_unit (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->scale_unit;
 }
 
@@ -3288,28 +3102,30 @@ champlain_view_get_zoom_on_double_click (ChamplainView *view)
 {
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  ChamplainViewPrivate *priv = view->priv;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
   return priv->zoom_on_double_click;
 }
 
 static void
 view_update_polygons (ChamplainView *view)
 {
-  ChamplainViewPrivate *priv = view->priv;
-  GList *polygons;
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
+  ClutterGroup *polygon_layer_group = CLUTTER_GROUP (priv->polygon_layer);
+  guint polygon_num, i;
   gfloat x, y;
 
-  if (priv->polygons == NULL)
+  polygon_num = clutter_group_get_n_children (polygon_layer_group);
+
+  if (polygon_num == 0)
     return;
 
-  polygons = priv->polygons;
-  while (polygons != NULL)
+  for (i = 0; i < polygon_num; i++)
     {
-      ChamplainPolygon *polygon;
+      ChamplainPolygon *polygon = CHAMPLAIN_POLYGON (clutter_group_get_nth_child (polygon_layer_group, i));
 
-      polygon = CHAMPLAIN_POLYGON (polygons->data);
-      draw_polygon (view, polygon);
-      polygons = polygons->next;
+      champlain_polygon_draw_polygon (polygon, priv->map_source, priv->zoom_level,
+                                      priv->viewport_size.width, priv->viewport_size.height,
+                                      priv->viewport_size.x + priv->anchor.x, priv->viewport_size.y + priv->anchor.y);
     }
 
   /* Position the layer in the viewport */
@@ -3335,26 +3151,22 @@ champlain_view_add_polygon (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  view->priv->polygons = g_list_append (view->priv->polygons, g_object_ref_sink (polygon));
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
   g_signal_connect (polygon, "notify",
       G_CALLBACK (notify_polygon_cb), view);
 
-  if (view->priv->viewport_size.width == 0 ||
+// JT question: what was the code below good for? It definitely leaks memory...
+/*  if (view->priv->viewport_size.width == 0 ||
       view->priv->viewport_size.height == 0)
   {
     polygon->priv->actor = NULL;
     return;
-  }
+  }*/
 
-  polygon->priv->actor = g_object_ref (clutter_cairo_texture_new (
-      view->priv->viewport_size.width,
-      view->priv->viewport_size.height));
-  g_object_set (G_OBJECT (polygon->priv->actor), "visible",
-      polygon->priv->visible, NULL);
-  clutter_actor_set_position (polygon->priv->actor, 0, 0);
-  clutter_container_add_actor (CLUTTER_CONTAINER (view->priv->polygon_layer),
-      polygon->priv->actor);
+  clutter_actor_set_position (CLUTTER_ACTOR (polygon), 0, 0);
+  clutter_container_add_actor (CLUTTER_CONTAINER (priv->polygon_layer),
+      CLUTTER_ACTOR (polygon));
 }
 
 /**
@@ -3373,11 +3185,9 @@ champlain_view_remove_polygon (ChamplainView *view,
   g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
   g_return_if_fail (CHAMPLAIN_IS_POLYGON (polygon));
 
-  view->priv->polygons = g_list_remove (view->priv->polygons, polygon);
-
-  if (polygon->priv->actor != NULL)
-    clutter_container_remove_actor (CLUTTER_CONTAINER (view->priv->polygon_layer),
-        polygon->priv->actor);
+  ChamplainViewPrivate *priv = GET_PRIVATE (view);
 
-  g_object_unref (polygon);
+  clutter_container_remove_actor (CLUTTER_CONTAINER (priv->polygon_layer),
+      CLUTTER_ACTOR (polygon));
 }
+
diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h
index 2479fcf..a3c0cba 100644
--- a/champlain/champlain-view.h
+++ b/champlain/champlain-view.h
@@ -60,14 +60,11 @@ typedef enum {
 struct _ChamplainView
 {
   ClutterGroup group;
-
-  ChamplainViewPrivate *priv;
 };
 
 struct _ChamplainViewClass
 {
   ClutterGroupClass parent_class;
-
 };
 
 GType champlain_view_get_type (void);
diff --git a/champlain/champlain-zoom-level.c b/champlain/champlain-zoom-level.c
index e7303fe..bef29c1 100644
--- a/champlain/champlain-zoom-level.c
+++ b/champlain/champlain-zoom-level.c
@@ -18,41 +18,28 @@
 
 #include "champlain-zoom-level.h"
 
-#include "champlain-map.h"
 #include "champlain-tile.h"
+#include "champlain-map-source.h"
 
 #include <clutter/clutter.h>
 
-G_DEFINE_TYPE (ChamplainZoomLevel, champlain_zoom_level, G_TYPE_OBJECT)
+G_DEFINE_TYPE (ChamplainZoomLevel, champlain_zoom_level, CLUTTER_TYPE_GROUP)
 
 #define GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_ZOOM_LEVEL, ChamplainZoomLevelPrivate))
 
 enum
 {
-  /* normal signals */
-  SIGNAL_TILE_ADDED,
-  SIGNAL_TILE_REMOVED,
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-enum
-{
   PROP_0,
   PROP_WIDTH,
   PROP_HEIGHT,
-  PROP_ZOOM_LEVEL,
-  PROP_ACTOR
+  PROP_ZOOM_LEVEL
 };
 
 struct _ChamplainZoomLevelPrivate {
   guint width; /* The absolute width of the zoom level in tiles */
   guint height; /* The absolute height of the zoom level in tiles */
   gint zoom_level;
-  GPtrArray *tiles; /* Contains the tiles of this level */
-  ClutterActor *actor;  /* The actor on which tile actors are added */
 };
 
 static void
@@ -73,9 +60,6 @@ champlain_zoom_level_get_property (GObject *object,
       case PROP_ZOOM_LEVEL:
         g_value_set_int (value, champlain_zoom_level_get_zoom_level (self));
         break;
-      case PROP_ACTOR:
-        g_value_set_object (value, champlain_zoom_level_get_actor (self));
-        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -99,7 +83,6 @@ champlain_zoom_level_set_property (GObject *object,
       case PROP_ZOOM_LEVEL:
         champlain_zoom_level_set_zoom_level (self, g_value_get_int (value));
         break;
-      case PROP_ACTOR:
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -108,30 +91,6 @@ champlain_zoom_level_set_property (GObject *object,
 static void
 champlain_zoom_level_dispose (GObject *object)
 {
-
-  guint k;
-  ChamplainZoomLevel *level = CHAMPLAIN_ZOOM_LEVEL (object);
-  ChamplainZoomLevelPrivate *priv = level->priv;
-
-  if (priv->actor != NULL)
-  {
-    g_object_unref (priv->actor);
-    priv->actor = NULL;
-  }
-
-  if (priv->tiles != NULL)
-    {
-      int count = champlain_zoom_level_tile_count (level);
-      for (k = 0; k < count; k++)
-        {
-          ChamplainTile *tile = champlain_zoom_level_get_nth_tile (level, 0);
-          if (tile != NULL)
-              champlain_zoom_level_remove_tile (level, tile);
-        }
-      g_ptr_array_free (priv->tiles, TRUE);
-      priv->tiles = NULL;
-    }
-
   G_OBJECT_CLASS (champlain_zoom_level_parent_class)->dispose (object);
 }
 
@@ -153,16 +112,6 @@ champlain_zoom_level_class_init (ChamplainZoomLevelClass *klass)
   object_class->dispose = champlain_zoom_level_dispose;
   object_class->finalize = champlain_zoom_level_finalize;
 
-  signals[SIGNAL_TILE_ADDED] =
-      g_signal_new ("tile-added", G_OBJECT_CLASS_TYPE (klass),
-      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
-      G_TYPE_NONE, 1, CHAMPLAIN_TYPE_TILE);
-
-  signals[SIGNAL_TILE_REMOVED] =
-      g_signal_new ("tile-removed", G_OBJECT_CLASS_TYPE (klass),
-      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
-      G_TYPE_NONE, 1, CHAMPLAIN_TYPE_TILE);
-
   /**
   * ChamplainZoomLevel:width:
   *
@@ -213,31 +162,16 @@ champlain_zoom_level_class_init (ChamplainZoomLevelClass *klass)
           G_MAXINT,
           0,
           G_PARAM_READWRITE));
-
-  /**
-  * ChamplainZoomLevel:actor:
-  *
-  * The #ClutterActor containing all the tiles
-  *
-  * Since: 0.4
-  */
-  g_object_class_install_property (object_class,
-      PROP_ACTOR,
-      g_param_spec_object ("actor",
-          "Actor",
-          "The actor containing all the tiles",
-          CLUTTER_TYPE_ACTOR,
-          G_PARAM_READABLE));
 }
 
 static void
 champlain_zoom_level_init (ChamplainZoomLevel *self)
 {
   ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
-  self->priv = priv;
 
-  priv->tiles = g_ptr_array_sized_new (64);
-  priv->actor = g_object_ref (clutter_group_new ());
+  priv->width = 0;
+  priv->height = 0;
+  priv->zoom_level = 0;
 }
 
 /**
@@ -254,88 +188,6 @@ champlain_zoom_level_new (void)
 }
 
 /**
- * champlain_zoom_level_add_tile:
- * @self: a #ChamplainZoomLevel
- * @tile: a #ChamplainTile
- *
- * Adds a #ChamplainTile to a #ChamplainZoomLevel.
- *
- * Since: 0.4
- */
-void
-champlain_zoom_level_add_tile (ChamplainZoomLevel *self,
-    ChamplainTile *tile)
-{
-  g_return_if_fail (CHAMPLAIN_ZOOM_LEVEL (self));
-
-  ChamplainZoomLevelPrivate *priv = self->priv;
-
-  g_object_ref (tile);
-  g_ptr_array_add (priv->tiles, tile);
-
-  g_signal_emit (self, signals[SIGNAL_TILE_ADDED], 0, tile);
-}
-
-/**
- * champlain_zoom_level_remove_tile:
- * @self: a #ChamplainZoomLevel
- * @tile: a #ChamplainTile
- *
- * Removes a #ChamplainTile to a #ChamplainZoomLevel.
- *
- * Since: 0.4
- */
-void
-champlain_zoom_level_remove_tile (ChamplainZoomLevel *self,
-    ChamplainTile *tile)
-{
-  g_return_if_fail (CHAMPLAIN_ZOOM_LEVEL (self));
-
-  ChamplainZoomLevelPrivate *priv = self->priv;
-
-  g_signal_emit (self, signals[SIGNAL_TILE_REMOVED], 0, tile);
-
-  g_ptr_array_remove_fast (priv->tiles, tile);
-  g_object_unref (tile);
-}
-
-/**
- * champlain_zoom_level_tile_count:
- * @self: a #ChamplainZoomLevel
- *
- * Returns: the number of tiles in a #ChamplainZoomLevel.
- *
- * Since: 0.4
- */
-guint
-champlain_zoom_level_tile_count (ChamplainZoomLevel *self)
-{
-  g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), 0);
-
-  return self->priv->tiles->len;
-}
-
-/**
- * champlain_zoom_level_get_nth_tile:
- * @self: a #ChamplainZoomLevel
- * @index: an index
- *
- * Returns: the #ChamplainTile at given index
- *
- * Since: 0.4
- */
-ChamplainTile *
-champlain_zoom_level_get_nth_tile (ChamplainZoomLevel *self,
-    guint index)
-{
-  g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), NULL);
-  g_return_val_if_fail (index < self->priv->tiles->len, NULL);
-  g_return_val_if_fail (index >= 0, NULL);
-
-  return g_ptr_array_index (self->priv->tiles, index);
-}
-
-/**
  * champlain_zoom_level_get_width:
  * @self: a #ChamplainZoomLevel
  *
@@ -347,8 +199,9 @@ guint
 champlain_zoom_level_get_width (ChamplainZoomLevel *self)
 {
   g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), 0);
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  return self->priv->width;
+  return priv->width;
 }
 
 /**
@@ -363,8 +216,9 @@ guint
 champlain_zoom_level_get_height (ChamplainZoomLevel *self)
 {
   g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), 0);
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  return self->priv->height;
+  return priv->height;
 }
 
 /**
@@ -379,8 +233,9 @@ gint
 champlain_zoom_level_get_zoom_level (ChamplainZoomLevel *self)
 {
   g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), 0);
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  return self->priv->zoom_level;
+  return priv->zoom_level;
 }
 
 /**
@@ -397,8 +252,9 @@ champlain_zoom_level_set_width (ChamplainZoomLevel *self,
     guint width)
 {
   g_return_if_fail (CHAMPLAIN_ZOOM_LEVEL (self));
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  self->priv->width = width;
+  priv->width = width;
 
   g_object_notify (G_OBJECT (self), "width");
 }
@@ -417,8 +273,9 @@ champlain_zoom_level_set_height (ChamplainZoomLevel *self,
     guint height)
 {
   g_return_if_fail (CHAMPLAIN_ZOOM_LEVEL (self));
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  self->priv->height = height;
+  priv->height = height;
 
   g_object_notify (G_OBJECT (self), "height");
 }
@@ -437,25 +294,32 @@ champlain_zoom_level_set_zoom_level (ChamplainZoomLevel *self,
     gint zoom_level)
 {
   g_return_if_fail (CHAMPLAIN_ZOOM_LEVEL (self));
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
 
-  self->priv->zoom_level = zoom_level;
+  priv->zoom_level = zoom_level;
 
   g_object_notify (G_OBJECT (self), "zoom-level");
 }
 
-/**
- * champlain_zoom_level_get_actor:
- * @self: a #ChamplainZoomLevel
- *
- * Returns: the #ClutterActor containing all the tiles of a #ChamplainZoomLevel,
- * it should not be unref.
- *
- * Since: 0.4
- */
-ClutterActor *
-champlain_zoom_level_get_actor (ChamplainZoomLevel *self)
+gboolean
+champlain_zoom_level_zoom_to (ChamplainZoomLevel *self,
+    ChamplainMapSource *source,
+    guint zoom_level)
 {
-  g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), NULL);
+  g_return_val_if_fail (CHAMPLAIN_ZOOM_LEVEL (self), FALSE);
+
+  ChamplainZoomLevelPrivate *priv = GET_PRIVATE (self);
+
+  if (zoom_level <= champlain_map_source_get_max_zoom_level (source) &&
+      zoom_level >= champlain_map_source_get_min_zoom_level (source))
+    {
+      clutter_group_remove_all (CLUTTER_GROUP (self));
+
+      priv->width = champlain_map_source_get_row_count (source, zoom_level);
+      priv->height = champlain_map_source_get_column_count (source, zoom_level);
+      priv->zoom_level = zoom_level;
+      return TRUE;
+    }
 
-  return self->priv->actor;
+  return FALSE;
 }
diff --git a/champlain/champlain-zoom-level.h b/champlain/champlain-zoom-level.h
index bf17c00..450305c 100644
--- a/champlain/champlain-zoom-level.h
+++ b/champlain/champlain-zoom-level.h
@@ -49,12 +49,11 @@ typedef struct _ChamplainZoomLevel        ChamplainZoomLevel;
 typedef struct _ChamplainZoomLevelClass   ChamplainZoomLevelClass;
 
 struct _ChamplainZoomLevel{
-  GObject parent;
-  ChamplainZoomLevelPrivate *priv;
+  ClutterGroup parent;
 };
 
 struct _ChamplainZoomLevelClass{
-  GObjectClass parent_class;
+  ClutterGroupClass parent_class;
 };
 
 GType champlain_zoom_level_get_type (void);
@@ -64,7 +63,6 @@ ChamplainZoomLevel* champlain_zoom_level_new (void);
 guint champlain_zoom_level_get_width (ChamplainZoomLevel *self);
 guint champlain_zoom_level_get_height (ChamplainZoomLevel *self);
 gint champlain_zoom_level_get_zoom_level (ChamplainZoomLevel *self);
-ClutterActor* champlain_zoom_level_get_actor (ChamplainZoomLevel *self);
 
 void champlain_zoom_level_set_width (ChamplainZoomLevel *self,
     guint width);
@@ -73,13 +71,9 @@ void champlain_zoom_level_set_height (ChamplainZoomLevel *self,
 void champlain_zoom_level_set_zoom_level (ChamplainZoomLevel *self,
     gint zoom_level);
 
-void champlain_zoom_level_add_tile (ChamplainZoomLevel *self,
-    ChamplainTile *tile);
-void champlain_zoom_level_remove_tile (ChamplainZoomLevel *self,
-    ChamplainTile *tile);
-guint champlain_zoom_level_tile_count (ChamplainZoomLevel *self);
-ChamplainTile* champlain_zoom_level_get_nth_tile (ChamplainZoomLevel *self,
-    guint index);
+gboolean champlain_zoom_level_zoom_to (ChamplainZoomLevel *self,
+    ChamplainMapSource *source,
+    guint zoomLevel);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]