[gnome-maps/wip/jonasdn/vector-tiles] Add text layer



commit 2f3f2a1f8e1fad11000445184b73a58a52625731
Author: Jonas Danielsson <jonas threetimestwo org>
Date:   Sat Apr 25 14:50:48 2015 +0200

    Add text layer

 data/gnome-maps.mapcss       |  137 +++++++++++++++++++++++++--
 lib/Makefile.am              |    2 +
 lib/maps-mapbox-renderer.c   |   56 ++++++-----
 lib/maps-mapbox-renderer.h   |    7 ++
 lib/maps-mapbox-text-layer.c |  216 ++++++++++++++++++++++++++++++++++++++++++
 lib/maps-mapbox-text-layer.h |   56 +++++++++++
 src/mapView.js               |    2 +
 7 files changed, 441 insertions(+), 35 deletions(-)
---
diff --git a/data/gnome-maps.mapcss b/data/gnome-maps.mapcss
index f72d7d5..57a5d1f 100644
--- a/data/gnome-maps.mapcss
+++ b/data/gnome-maps.mapcss
@@ -1,3 +1,19 @@
+node {
+    font-size: 10;
+    font-weight: bold;
+    font-variant: small-caps;
+    font-family: cantarell;
+}
+
+node|z5-10[place=country] {
+    text-color: #4A90D9;
+    text: name;
+}
+
+node|z5-10[place=sea] {
+    text-color: #770000;
+    text: name;
+}
 
 /* This applies to the Map as a whole, renders first */
 canvas {
@@ -13,6 +29,8 @@ way {
 }
 
 /* All lines with the tag 'highway' */
+
+
 way[highway] {
     color: #ffffff;
     linecap: round;
@@ -24,8 +42,46 @@ way[highway] {
     casing-color: #C7B8A4;
 }
 
+way|z0-7[highway] {
+   width: 1;
+   color: #777777;
+   casing-width: 0;
+}
+
+way[highway=service] {
+   width: 2;
+}
+
+way[highway=living_street] {
+   width: 3;
+}
+
+way[highway=pedestrian] {
+   color: #dddddd;
+}
+
 /* Applies to all lines drawn that passes these tests */
-way[highway=motorway], way[highway=motorway_link],
+way[highway=motorway] {
+    casing-width: 3;
+    casing-color: #ff9966;
+    color: #ffff00;
+    width: 2;
+}
+
+way|z15-18[highway=motorway] {
+    casing-width: 0.95;
+    casing-color: #774433;
+    color: #ff9966;
+    width: 5;
+}
+
+way[highway=motorway_link] {
+    casing-width: 0.95;
+    casing-color: #774433;
+    color: #ff9966;
+    width: 3;
+}
+
 way[highway=trunk], way[highway=trunk_link] {
     casing-width: 0.95;
     color: #ff9966;
@@ -43,28 +99,79 @@ way[highway=footway] {
     color: #770000;
     width: 1;
     dashes: 2, 2;
+    casing-width: 0;
 }
 
 way[highway=cycleway] {
     color: #000077;
     width: 1;
     dashes: 2, 2;
+    casing-width: 0;
+}
+
+way[highway=path] {
+    color: #000000;
+    width: 0.5;
+    dashes: 5, 4;
+    casing-width: 0;
+}
+
+way[highway=steps] {
+    color: #a00000;
+    width: 2;
+    dashes: 1, 1;
+    casing-width: 0;
+}
+
+way[highway=track] {
+    color: #826a52;
+    width: 1;
+    dashes: 8, 8;
+    casing-width: 0;
+}
+
+way[railway=rail] {
+    color: #ffffff;
+    width: 2;
+    casing-color: #777777;
+    casing-width: 1;
+    dashes: 7, 10;
+}
+
+way[railway=tram], way[railway=lightrail] {
+    color: #000000;
+    width: 2;
+    casing-width: 0;
+}
+
+way[railway=preserved], way[railway=narrow_gauge] {
+   width: 1;
 }
 
 area {
-    color: #FAEBD7;
+    color: #000000;
     fill-color: #FAEBD7;
     width: 1;
 }
 
-area[landuse=park], area[landuse=playground], area[landuse=pitch] {
-    fill-color: #73D216;
-    color: #73D216;
+area|z14-19 {
+    text: name;
+    text-color: #222233;
+    font-size: 8;
+    font-family: cantarell;
+    font-weight: bold;
 }
 
-area[landuse=wood], area[landuse=scrub] {
-    fill-color: #0D6C00;
-    color: #0D6C00;
+area[landuse=park], area[landuse=playground], area[landuse=pitch],
+area[leisure=park], area[leasure=playground], area[leisure=pitch] {
+    fill-color: #ABCA8A;
+    color: #ABCA8a;
+}
+
+area[landuse=forest], area[landuse=wood], area[landuse=scrub],
+area[natural=wood] {
+    fill-color: #56A900;
+    color: #56A900;
     z-index: 1; /* z-index 0 is baseline */
 }
 
@@ -78,13 +185,25 @@ area[building] {
     fill-color: #C7B8A4;
 }
 
+area[amenity=parking] {
+    color: #ffff77;
+    fill-color: #C7B8A4;
+}
+
+area[highway=pedestrian] {
+    color: #dddddd;
+    fill-color: #C7B8A4;
+}
+
+/*
 way[is_bridge=yes] {
     color: #333333;
     width: 2;
 }
+*/
 
 way[is_tunnel=yes] {
-    color: #333333;
+    color: #EEEEEC;
     width: 2;
     dashes: 3, 3;
 }
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f7e83f7..ff9dd16 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -8,11 +8,13 @@ libgnome_maps_headers_private =                                       \
        maps-contact-store.h                                            \
        maps-contact.h                                                  \
        maps-mapbox-renderer.h                                          \
+       maps-mapbox-text-layer.h                                        \
        maps.h
 
 libgnome_maps_sources =                                                \
        maps-contact-store.c                                            \
        maps-contact.c                                                  \
+       maps-mapbox-text-layer.c                                        \
        maps-mapbox-renderer.c
 
 libgnome_maps_la_SOURCES =                                             \
diff --git a/lib/maps-mapbox-renderer.c b/lib/maps-mapbox-renderer.c
index adf148b..a1fbe34 100644
--- a/lib/maps-mapbox-renderer.c
+++ b/lib/maps-mapbox-renderer.c
@@ -21,11 +21,14 @@
 #include <cairo.h>
 
 #include "maps-mapbox-renderer.h"
+#include "maps-mapbox-text-layer.h"
 
 struct _MapsMapboxRendererPrivate
 {
   gchar *data;
   guint size;
+  MapsMapboxTextLayer *layer;
+  ChamplainView *view;
 
   VTileMapCSS *stylesheet;
 };
@@ -33,6 +36,8 @@ struct _MapsMapboxRendererPrivate
 typedef struct _RenderData
 {
   ChamplainTile *tile;
+  MapsMapboxTextLayer *layer;
+  ChamplainView *view;
   ClutterContent *canvas;
   gchar *data;
   guint size;
@@ -84,6 +89,7 @@ maps_mapbox_renderer_init (MapsMapboxRenderer *renderer)
   renderer->priv = maps_mapbox_renderer_get_instance_private (renderer);
   renderer->priv->data = NULL;
   renderer->priv->size = 0;
+  renderer->priv->view = NULL;
 }
 
 
@@ -94,21 +100,31 @@ maps_mapbox_renderer_init (MapsMapboxRenderer *renderer)
  *
  */
 MapsMapboxRenderer *
-maps_mapbox_renderer_new (void)
+maps_mapbox_renderer_new ()
 {
-  return g_object_new (MAPS_TYPE_MAPBOX_RENDERER, NULL);
+  MapsMapboxRenderer *renderer;
+  renderer = g_object_new (MAPS_TYPE_MAPBOX_RENDERER, NULL);
+}
+
+void
+maps_mapbox_renderer_set_view (MapsMapboxRenderer *renderer,
+                               ChamplainView *view)
+{
+  renderer->priv->view = view;
+  renderer->priv->layer = maps_mapbox_text_layer_new ();
+
+  champlain_view_add_layer (view, (ChamplainLayer *) renderer->priv->layer);
 }
 
 void
 maps_mapbox_renderer_load_css (MapsMapboxRenderer *renderer,
-                                    const char *filename,
-                                    GError **error)
+                               const char *filename,
+                               GError **error)
 {
   renderer->priv->stylesheet = vtile_mapcss_new ();
   vtile_mapcss_load (renderer->priv->stylesheet, filename, error);
 }
 
-
 static void
 set_data (ChamplainRenderer *renderer_base, const gchar *data, guint size)
 {
@@ -121,13 +137,6 @@ set_data (ChamplainRenderer *renderer_base, const gchar *data, guint size)
   renderer->priv->size = size;
 }
 
-static void
-on_mapbox_rendered (VTileMapbox *mapbox,
-                    GAsyncResult *res,
-                    RenderData *data)
-{
-
-}
 
 gboolean
 on_canvas_draw (ClutterCanvas *canvas,
@@ -142,6 +151,7 @@ on_canvas_draw (ClutterCanvas *canvas,
   ClutterActor *actor = NULL;
   GError *error = NULL;
   gboolean success;
+  GList *texts, *l;
 
   mapbox = vtile_mapbox_new (data->data,
                              data->size,
@@ -150,24 +160,25 @@ on_canvas_draw (ClutterCanvas *canvas,
 
   vtile_mapbox_set_stylesheet (mapbox, data->stylesheet);
 
-
-  cairo_save (cr);
   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
   cairo_paint (cr);
-  cairo_restore (cr);
   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
   vtile_mapbox_render (mapbox, cr, NULL);
 
+
   actor = clutter_actor_new ();
   clutter_actor_set_size (actor,
                           champlain_tile_get_size (data->tile),
                           champlain_tile_get_size (data->tile));
   clutter_actor_set_content (actor, data->canvas);
   g_object_unref (data->canvas);
+  g_object_unref (mapbox);
 
-  /*  clutter_actor_set_offscreen_redirect (actor,
-      CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY);  */
+  texts = vtile_mapbox_get_texts (mapbox);
+  for (l = texts; l != NULL; l = l->next) {
+    maps_mapbox_text_layer_add_text (data->layer, data->tile, l->data);
+  }
 
  finish:
   if (actor)
@@ -181,15 +192,6 @@ on_canvas_draw (ClutterCanvas *canvas,
   g_free (data->data);
   g_free (data);
 
-  /*
-  sprintf (output, "%d-%d-%d.png\n",
-           champlain_tile_get_x (data->tile),
-           champlain_tile_get_y (data->tile),
-           champlain_tile_get_zoom_level (data->tile));
-  surface = cairo_get_target (cr);
-  cairo_surface_write_to_png (surface, output);
-  */
-
 
   return TRUE;
 }
@@ -213,6 +215,8 @@ render (ChamplainRenderer *renderer_base, ChamplainTile *tile)
   data->size = renderer->priv->size;
   data->stylesheet = renderer->priv->stylesheet;
   data->canvas = clutter_canvas_new ();
+  data->layer = renderer->priv->layer;
+  data->view = renderer->priv->view;
 
   clutter_canvas_set_size ((ClutterCanvas *) data->canvas,
                            champlain_tile_get_size (tile),
diff --git a/lib/maps-mapbox-renderer.h b/lib/maps-mapbox-renderer.h
index d72fda4..7995f75 100644
--- a/lib/maps-mapbox-renderer.h
+++ b/lib/maps-mapbox-renderer.h
@@ -21,6 +21,7 @@
 #define __MAPS_MAPBOX_RENDERER_H__
 
 #include <champlain/champlain.h>
+#include <vector-tile-mapbox.h>
 
 G_BEGIN_DECLS
 
@@ -66,10 +67,16 @@ struct _MapsMapboxRendererClass
 GType maps_mapbox_renderer_get_type (void);
 
 MapsMapboxRenderer *maps_mapbox_renderer_new (void);
+MapsMapboxRenderer *maps_mapbox_renderer_new_with_view (ChamplainView *view);
+
 
 void maps_mapbox_renderer_load_css (MapsMapboxRenderer *renderer,
                                     const char *filename,
                                     GError **error);
+
+void maps_mapbox_renderer_set_view (MapsMapboxRenderer *renderer,
+                                    ChamplainView *view);
+
 G_END_DECLS
 
 #endif /* __MAPS_MAPBOX_RENDERER_H__ */
diff --git a/lib/maps-mapbox-text-layer.c b/lib/maps-mapbox-text-layer.c
new file mode 100644
index 0000000..2eb70d2
--- /dev/null
+++ b/lib/maps-mapbox-text-layer.c
@@ -0,0 +1,216 @@
+#include "maps-mapbox-text-layer.h"
+
+#include <clutter/clutter.h>
+#include <glib.h>
+
+struct _MapsMapboxTextLayerPrivate
+{
+  ChamplainView *view;
+  GHashTable *objects;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MapsMapboxTextLayer, maps_mapbox_text_layer, CHAMPLAIN_TYPE_LAYER)
+
+static void set_view (ChamplainLayer *layer,
+                      ChamplainView *view);
+
+static ChamplainBoundingBox *get_bounding_box (ChamplainLayer *layer);
+
+static void
+maps_mapbox_text_layer_dispose (GObject *object)
+{
+  MapsMapboxTextLayer *self = MAPS_MAPBOX_TEXT_LAYER (object);
+  MapsMapboxTextLayerPrivate *priv = self->priv;
+
+  if (priv->view != NULL)
+    set_view (CHAMPLAIN_LAYER (self), NULL);
+
+  G_OBJECT_CLASS (maps_mapbox_text_layer_parent_class)->dispose (object);
+}
+
+
+static void
+maps_mapbox_text_layer_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (maps_mapbox_text_layer_parent_class)->finalize (object);
+}
+
+
+static void
+maps_mapbox_text_layer_class_init (MapsMapboxTextLayerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ChamplainLayerClass *layer_class = CHAMPLAIN_LAYER_CLASS (klass);
+
+  object_class->finalize = maps_mapbox_text_layer_finalize;
+  object_class->dispose = maps_mapbox_text_layer_dispose;
+
+  layer_class->set_view = set_view;
+  layer_class->get_bounding_box = get_bounding_box;
+}
+
+
+static void
+maps_mapbox_text_layer_init (MapsMapboxTextLayer *self)
+{
+  MapsMapboxTextLayerPrivate *priv;
+
+  self->priv = maps_mapbox_text_layer_get_instance_private (self);
+  self->priv->objects = g_hash_table_new (g_str_hash, g_str_equal);
+  self->priv->view = NULL;
+}
+
+
+/**
+ * maps_mapbox_text_layer_new:
+ *
+ * Creates a new instance of #MapsMapboxTextLayer.
+ *
+ * Returns: a new #MapsMapboxTextLayer ready to be used as a container for text.
+ *
+ */
+MapsMapboxTextLayer *
+maps_mapbox_text_layer_new ()
+{
+  return g_object_new (MAPS_TYPE_MAPBOX_TEXT_LAYER, NULL);
+}
+
+gboolean
+on_text_draw (ClutterCanvas *canvas,
+              cairo_t *cr,
+              gint width,
+              gint height,
+              VTileMapboxText *text)
+{
+  cairo_surface_t *surface;
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+  cairo_set_source_surface (cr, text->surface, 0, 0);
+  cairo_paint (cr);
+  surface = cairo_get_target (cr);
+  g_signal_handlers_disconnect_by_func (canvas, on_text_draw, text);
+
+  return TRUE;
+}
+
+
+void
+maps_mapbox_text_layer_add_text (MapsMapboxTextLayer *layer,
+                                 ChamplainTile *tile,
+                                 VTileMapboxText *text)
+{
+  g_return_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer));
+
+  ClutterContent *canvas;
+  ClutterActor *actor;
+  guint orig_x, orig_y;
+  gfloat tile_x, tile_y;
+
+  if (g_hash_table_lookup (layer->priv->objects, text->uid)) {
+    return;
+  } else {
+    g_hash_table_insert (layer->priv->objects, text->uid, text->uid);
+  }
+
+  canvas = clutter_canvas_new ();
+  clutter_canvas_set_size (CLUTTER_CANVAS (canvas), text->width, text->height);
+  g_signal_connect (canvas, "draw", G_CALLBACK (on_text_draw), text);
+  clutter_content_invalidate (canvas);
+
+  actor = clutter_actor_new ();
+  clutter_actor_set_size (actor, text->width, text->height);
+  clutter_actor_set_content (actor, canvas);
+  g_object_unref (canvas);
+
+  clutter_actor_get_position (tile, &tile_x, &tile_y);
+  champlain_view_get_viewport_origin (layer->priv->view, &orig_x, &orig_y);
+
+  clutter_actor_set_position (actor,
+                              tile_x + text->offset_x,
+                              tile_y + text->offset_y);
+
+  clutter_actor_add_child (CLUTTER_ACTOR (layer), actor);
+}
+
+
+/**
+ * maps_mapbox_text_layer_remove_all:
+ * @layer: a #MapsMapboxTextLayer
+ *
+ * Removes all texts from the layer.
+ *
+ * Since: 0.10
+ */
+void
+maps_mapbox_text_layer_remove_all (MapsMapboxTextLayer *layer)
+{
+  g_return_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer));
+
+  clutter_actor_remove_all_children (CLUTTER_ACTOR (layer));
+  g_hash_table_remove_all (layer->priv->objects);
+}
+
+static void
+relocate_cb (G_GNUC_UNUSED GObject *gobject,
+             MapsMapboxTextLayer *layer)
+{
+  g_return_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer));
+
+  maps_mapbox_text_layer_remove_all (layer);
+}
+
+
+static void
+zoom_reposition_cb (G_GNUC_UNUSED GObject *gobject,
+                    G_GNUC_UNUSED GParamSpec *arg1,
+                    MapsMapboxTextLayer *layer)
+{
+  g_return_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer));
+
+  maps_mapbox_text_layer_remove_all (layer);
+}
+
+static void
+set_view (ChamplainLayer *layer,
+          ChamplainView *view)
+{
+  g_return_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer) &&
+                    (CHAMPLAIN_IS_VIEW (view) || view == NULL));
+
+  MapsMapboxTextLayer *text_layer = MAPS_MAPBOX_TEXT_LAYER (layer);
+
+  if (text_layer->priv->view != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (text_layer->priv->view,
+          G_CALLBACK (relocate_cb), text_layer);
+      g_object_unref (text_layer->priv->view);
+    }
+
+  text_layer->priv->view = view;
+
+  if (view != NULL)
+    {
+      g_object_ref (view);
+
+      g_signal_connect (view, "layer-relocated",
+          G_CALLBACK (relocate_cb), layer);
+
+      g_signal_connect (view, "notify::zoom-level",
+          G_CALLBACK (zoom_reposition_cb), layer);
+
+      maps_mapbox_text_layer_remove_all (text_layer);
+    }
+}
+
+static ChamplainBoundingBox *
+get_bounding_box (ChamplainLayer *layer)
+{
+  ChamplainBoundingBox *bbox;
+
+  g_return_val_if_fail (MAPS_IS_MAPBOX_TEXT_LAYER (layer), NULL);
+
+  return champlain_bounding_box_new ();
+}
diff --git a/lib/maps-mapbox-text-layer.h b/lib/maps-mapbox-text-layer.h
new file mode 100644
index 0000000..deb882c
--- /dev/null
+++ b/lib/maps-mapbox-text-layer.h
@@ -0,0 +1,56 @@
+#ifndef MAPS_MAPBOX_TEXT_LAYER_H
+#define MAPS_MAPBOX_TEXT_LAYER_H
+
+#include <champlain/champlain.h>
+#include <vector-tile-mapbox.h>
+
+#include <glib-object.h>
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define MAPS_TYPE_MAPBOX_TEXT_LAYER maps_mapbox_text_layer_get_type ()
+
+#define MAPS_MAPBOX_TEXT_LAYER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAPS_TYPE_MAPBOX_TEXT_LAYER, MapsMapboxTextLayer))
+
+#define MAPS_MAPBOX_TEXT_LAYER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), MAPS_TYPE_MAPBOX_TEXT_LAYER, MapsMapboxTextLayerClass))
+
+#define MAPS_IS_MAPBOX_TEXT_LAYER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAPS_TYPE_MAPBOX_TEXT_LAYER))
+
+#define MAPS_IS_MAPBOX_TEXT_LAYER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), MAPS_TYPE_MAPBOX_TEXT_LAYER))
+
+#define MAPS_MAPBOX_TEXT_LAYER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), MAPS_TYPE_MAPBOX_TEXT_LAYER, MapsMapboxTextLayerClass))
+
+typedef struct _MapsMapboxTextLayerPrivate MapsMapboxTextLayerPrivate;
+typedef struct _MapsMapboxTextLayer MapsMapboxTextLayer;
+typedef struct _MapsMapboxTextLayerClass MapsMapboxTextLayerClass;
+
+struct _MapsMapboxTextLayer
+{
+  ChamplainLayer parent;
+
+  MapsMapboxTextLayerPrivate *priv;
+};
+
+struct _MapsMapboxTextLayerClass
+{
+  ChamplainLayerClass parent_class;
+};
+
+GType maps_mapbox_text_layer_get_type (void);
+
+MapsMapboxTextLayer *maps_mapbox_text_layer_new (void);
+void maps_mapbox_text_layer_add_text (MapsMapboxTextLayer *layer,
+                                      ChamplainTile *tile,
+                                      VTileMapboxText *mapbox_text);
+void maps_mapbox_text_layer_remove_all (MapsMapboxTextLayer *layer);
+
+
+G_END_DECLS
+
+#endif
diff --git a/src/mapView.js b/src/mapView.js
index 2fb762f..51f8b72 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -149,6 +149,8 @@ const MapView = new Lang.Class({
     _vectorSource: function() {
         let id = 'vector-tile-glib';
         let renderer = new Maps.MapboxRenderer();
+        renderer.set_view(this.view);
+
         renderer.load_css(GLib.build_filenamev([pkg.pkgdatadir,
                                                 'gnome-maps.mapcss']));
 


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