[gnome-maps/wip/jonasdn/vector-tiles] Add support to render with vector-tile-glib



commit d27ccd9b0f736aee832a9f991f2b400bcd9b1b2c
Author: Jonas Danielsson <jonas threetimestwo org>
Date:   Sat Apr 18 12:22:51 2015 +0200

    Add support to render with vector-tile-glib

 configure.ac               |    2 +
 data/Makefile.am           |    4 +-
 data/gnome-maps.mapcss     |   88 +++++++++++++++++
 lib/Makefile.am            |   28 ++++--
 lib/maps-mapbox-renderer.c |  223 ++++++++++++++++++++++++++++++++++++++++++++
 lib/maps-mapbox-renderer.h |   75 +++++++++++++++
 src/mapView.js             |   42 ++++++++-
 7 files changed, 453 insertions(+), 9 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4d7b796..dced899 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,8 @@ PKG_CHECK_MODULES(GNOME_MAPS_LIB, [
     folks                        >= $FOLKS_MIN_VERSION
     geocode-glib-1.0             >= $GEOCODE_MIN_VERSION
     champlain-0.12               >= $CHAMPLAIN_MIN_VERSION
+    vector-tile-glib-1.0
+    cairo
 ])
 AC_SUBST(GNOME_MAPS_LIB_CFLAGS)
 AC_SUBST(GNOME_MAPS_LIB_LIBS)
diff --git a/data/Makefile.am b/data/Makefile.am
index e0ce3e9..9c7511e 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -12,7 +12,9 @@ org.gnome.Maps.data.gresource: org.gnome.Maps.data.gresource.xml $(app_resource_
                --sourcedir=$(srcdir) $<
 
 resourcedir = $(pkgdatadir)
-resource_DATA = org.gnome.Maps.data.gresource
+resource_DATA =                                                        \
+       org.gnome.Maps.data.gresource                                   \
+       gnome-maps.mapcss
 
 appsdir = $(datadir)/applications
 apps_DATA = org.gnome.Maps.desktop
diff --git a/data/gnome-maps.mapcss b/data/gnome-maps.mapcss
new file mode 100644
index 0000000..ed2f0b7
--- /dev/null
+++ b/data/gnome-maps.mapcss
@@ -0,0 +1,88 @@
+canvas {
+    fill-color: #FAEBD7;
+}
+
+way {
+    color: #777777;
+    width: 1;
+    linecap: round;
+}
+
+way[highway] {
+    color: #ffffff;
+    linecap: round;
+    casing-linecap: round;
+    linejoin: miter;
+    casing-linejoin: miter;
+    casing-width: 1;
+    width: 5;
+    casing-color: #C7B8A4;
+}
+
+
+way[highway=motorway], way[highway=motorway_link],
+way[highway=trunk], way[highway=trunk_link] {
+    casing-width: 0.95;
+    color: #ff9966;
+    casing-color: #bb5500;
+    width: 5;
+}
+way[highway=primary], way[highway=primary_link] {
+    casing-width: 0.8;
+    width: 2;
+    color: #ffbb88;
+    casing-color: #cc6600;
+}
+
+way[highway=footway] {
+    color: #770000;
+    width: 1;
+    dashes: 2, 2;
+}
+
+way[highway=cycleway] {
+    color: #000077;
+    width: 1;
+    dashes: 2, 2;
+}
+
+area {
+    color: #FAEBD7;
+    fill-color: #FAEBD7;
+    width: 1;
+}
+
+area[landuse=park], area[landuse=playground], area[landuse=pitch] {
+    fill-color: #73D216;
+    color: #73D216;
+}
+
+area[landuse=wood], area[landuse=scrub] {
+    fill-color: #0D6C00;
+    color: #0D6C00;
+    z-index: 1;
+}
+
+area[water], way[water], area[natural=water] {
+    color: #4A90D9;
+    fill-color: #4A90D9;
+}
+
+area[building] {
+    color: #777777;
+    fill-color: #C7B8A4;
+}
+
+way[is_bridge=yes] {
+    color: #333333;
+    width: 2;
+}
+
+way[is_tunnel=yes] {
+    color: #333333;
+    width: 2;
+    dashes: 3, 3;
+}
+
+
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 35203da..f7e83f7 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,8 +4,17 @@ BUILT_SOURCES =                                                        \
        maps-enum-types.c                                               \
        maps-enum-types.h
 
-libgnome_maps_headers_private = maps-contact-store.h maps-contact.h maps.h
-libgnome_maps_sources = maps-contact-store.c maps-contact.c
+libgnome_maps_headers_private =                                        \
+       maps-contact-store.h                                            \
+       maps-contact.h                                                  \
+       maps-mapbox-renderer.h                                          \
+       maps.h
+
+libgnome_maps_sources =                                                \
+       maps-contact-store.c                                            \
+       maps-contact.c                                                  \
+       maps-mapbox-renderer.c
+
 libgnome_maps_la_SOURCES =                                             \
        $(libgnome_maps_sources)                                        \
        $(libgnome_maps_headers_private)                                \
@@ -19,12 +28,12 @@ AM_CPPFLAGS =                                                               \
 
 maps-enum-types.h: $(libgnome_maps_headers_private)
        $(AM_V_GEN) ($(GLIB_MKENUMS)                                    \
-               --template $(srcdir)/maps-enum-types.h.template                 \
+               --template $(srcdir)/maps-enum-types.h.template \
                $^ > xgen-$(@F) && mv -f xgen-$(@F) $@)
 
 maps-enum-types.c: $(libgnome_maps_headers_private) maps-enum-types.h
        $(AM_V_GEN) ($(GLIB_MKENUMS)                                    \
-               --template $(srcdir)/maps-enum-types.c.template                 \
+               --template $(srcdir)/maps-enum-types.c.template \
                $^ > xgen-$(@F) && mv -f xgen-$(@F) $@)
 
 if HAVE_INTROSPECTION
@@ -37,10 +46,15 @@ GnomeMaps_1_0_gir_INCLUDES =                                                \
        GObject-2.0                                                     \
        GeocodeGlib-1.0                                         \
        Champlain-0.12
-GnomeMaps_1_0_gir_PACKAGES = gobject-2.0 geocode-glib-1.0
+GnomeMaps_1_0_gir_PACKAGES = gobject-2.0 geocode-glib-1.0 champlain-0.12 cairo
 GnomeMaps_1_0_gir_FILES = $(libgnome_maps_la_SOURCES)
-GnomeMaps_1_0_gir_CFLAGS = $(MAPS_CFLAGS) -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
-GnomeMaps_1_0_gir_LIBS = libgnome-maps.la
+GnomeMaps_1_0_gir_CFLAGS =                                             \
+       $(GNOME_MAPS_LIB_CFLAGS)                                        \
+       $(GNOME_MAPS_LIB_LIBS)                                          \
+       -I$(top_srcdir)                                         \
+       -I$(top_builddir)                                               \
+       -I$(srcdir)
+GnomeMaps_1_0_gir_LIBS = libgnome-maps.la champlain-0.12
 GnomeMaps_1_0_gir_EXPORT_PACKAGES = gnome-maps-1.0
 GnomeMaps_1_0_gir_SCANNERFLAGS =                                       \
        --symbol-prefix=maps                                            \
diff --git a/lib/maps-mapbox-renderer.c b/lib/maps-mapbox-renderer.c
new file mode 100644
index 0000000..adf148b
--- /dev/null
+++ b/lib/maps-mapbox-renderer.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2015 Jonas Danielsson
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Jonas Danielsson <jonas threetimestwo org>
+ */
+
+#include <vector-tile-mapbox.h>
+#include <cairo.h>
+
+#include "maps-mapbox-renderer.h"
+
+struct _MapsMapboxRendererPrivate
+{
+  gchar *data;
+  guint size;
+
+  VTileMapCSS *stylesheet;
+};
+
+typedef struct _RenderData
+{
+  ChamplainTile *tile;
+  ClutterContent *canvas;
+  gchar *data;
+  guint size;
+  VTileMapCSS *stylesheet;
+} RenderData;
+
+G_DEFINE_TYPE_WITH_PRIVATE (MapsMapboxRenderer, maps_mapbox_renderer, CHAMPLAIN_TYPE_RENDERER)
+
+static void set_data (ChamplainRenderer *renderer,
+                      const gchar *data,
+                      guint size);
+static void render (ChamplainRenderer *renderer,
+                    ChamplainTile *tile);
+
+static void
+maps_mapbox_renderer_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (maps_mapbox_renderer_parent_class)->dispose (object);
+}
+
+
+static void
+maps_mapbox_renderer_finalize (GObject *object)
+{
+  MapsMapboxRenderer *renderer = MAPS_MAPBOX_RENDERER (object);
+  g_free (renderer->priv->data);
+
+  G_OBJECT_CLASS (maps_mapbox_renderer_parent_class)->finalize (object);
+}
+
+
+static void
+maps_mapbox_renderer_class_init (MapsMapboxRendererClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ChamplainRendererClass *renderer_class = CHAMPLAIN_RENDERER_CLASS (klass);
+
+  object_class->finalize = maps_mapbox_renderer_finalize;
+  object_class->dispose = maps_mapbox_renderer_dispose;
+
+  renderer_class->set_data = set_data;
+  renderer_class->render = render;
+}
+
+
+static void
+maps_mapbox_renderer_init (MapsMapboxRenderer *renderer)
+{
+  renderer->priv = maps_mapbox_renderer_get_instance_private (renderer);
+  renderer->priv->data = NULL;
+  renderer->priv->size = 0;
+}
+
+
+/**
+ * maps_mapbox_renderer_new:
+ *
+ * Returns: (transfer full): a new #MapsMapboxRenderer object, use g_object_unref() when done.
+ *
+ */
+MapsMapboxRenderer *
+maps_mapbox_renderer_new (void)
+{
+  return g_object_new (MAPS_TYPE_MAPBOX_RENDERER, NULL);
+}
+
+void
+maps_mapbox_renderer_load_css (MapsMapboxRenderer *renderer,
+                                    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)
+{
+  MapsMapboxRenderer *renderer = (MapsMapboxRenderer *) renderer_base;
+
+  if (renderer->priv->data)
+    g_free (renderer->priv->data);
+
+  renderer->priv->data = g_memdup (data, size);
+  renderer->priv->size = size;
+}
+
+static void
+on_mapbox_rendered (VTileMapbox *mapbox,
+                    GAsyncResult *res,
+                    RenderData *data)
+{
+
+}
+
+gboolean
+on_canvas_draw (ClutterCanvas *canvas,
+                cairo_t *cr,
+                gint width,
+                gint height,
+                RenderData *data)
+{
+  VTileMapbox *mapbox;
+  cairo_surface_t *surface;
+  char output[512];
+  ClutterActor *actor = NULL;
+  GError *error = NULL;
+  gboolean success;
+
+  mapbox = vtile_mapbox_new (data->data,
+                             data->size,
+                             width,
+                             champlain_tile_get_zoom_level (data->tile));
+
+  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);
+
+  /*  clutter_actor_set_offscreen_redirect (actor,
+      CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY);  */
+
+ finish:
+  if (actor)
+    champlain_tile_set_content (data->tile, actor);
+
+  g_signal_emit_by_name (data->tile, "render-complete",
+                         data->data, data->size, success);
+
+
+  g_object_unref (data->tile);
+  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;
+}
+
+static void
+render (ChamplainRenderer *renderer_base, ChamplainTile *tile)
+{
+  MapsMapboxRenderer *renderer = (MapsMapboxRenderer *) renderer_base;
+  RenderData *data;
+
+  if (!renderer->priv->data || renderer->priv->size == 0)
+    {
+      g_signal_emit_by_name (tile, "render-complete",
+                             renderer->priv->data, renderer->priv->size, TRUE);
+      return;
+    }
+
+  data = g_new0 (RenderData, 1);
+  data->tile = g_object_ref (tile);
+  data->data = g_memdup (renderer->priv->data, renderer->priv->size);
+  data->size = renderer->priv->size;
+  data->stylesheet = renderer->priv->stylesheet;
+  data->canvas = clutter_canvas_new ();
+
+  clutter_canvas_set_size ((ClutterCanvas *) data->canvas,
+                           champlain_tile_get_size (tile),
+                           champlain_tile_get_size (tile));
+  g_signal_connect (data->canvas, "draw",
+                    G_CALLBACK (on_canvas_draw), data);
+  clutter_content_invalidate (data->canvas);
+}
diff --git a/lib/maps-mapbox-renderer.h b/lib/maps-mapbox-renderer.h
new file mode 100644
index 0000000..d72fda4
--- /dev/null
+++ b/lib/maps-mapbox-renderer.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 Jonas Danielsson
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Jonas Danielsson <jonas threetimestwo org>
+ */
+
+#ifndef __MAPS_MAPBOX_RENDERER_H__
+#define __MAPS_MAPBOX_RENDERER_H__
+
+#include <champlain/champlain.h>
+
+G_BEGIN_DECLS
+
+#define MAPS_TYPE_MAPBOX_RENDERER maps_mapbox_renderer_get_type ()
+
+#define MAPS_MAPBOX_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAPS_TYPE_MAPBOX_RENDERER, MapsMapboxRenderer))
+
+#define MAPS_MAPBOX_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), MAPS_TYPE_MAPBOX_RENDERER, MapsMapboxRendererClass))
+
+#define MAPS_IS_MAPBOX_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAPS_TYPE_MAPBOX_RENDERER))
+
+#define MAPS_IS_MAPBOX_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), MAPS_TYPE_MAPBOX_RENDERER))
+
+#define MAPS_MAPBOX_RENDERER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), MAPS_TYPE_MAPBOX_RENDERER, MapsMapboxRendererClass))
+
+typedef struct _MapsMapboxRendererPrivate MapsMapboxRendererPrivate;
+typedef struct _MapsMapboxRenderer MapsMapboxRenderer;
+typedef struct _MapsMapboxRendererClass MapsMapboxRendererClass;
+
+/**
+ * MapsMapboxRenderer:
+ *
+ * The #MapsMapboxRenderer structure contains only private data
+ * and should be accessed using the provided API
+ */
+struct _MapsMapboxRenderer
+{
+  ChamplainRenderer parent;
+
+  MapsMapboxRendererPrivate *priv;
+};
+
+struct _MapsMapboxRendererClass
+{
+  ChamplainRendererClass parent_class;
+};
+
+GType maps_mapbox_renderer_get_type (void);
+
+MapsMapboxRenderer *maps_mapbox_renderer_new (void);
+
+void maps_mapbox_renderer_load_css (MapsMapboxRenderer *renderer,
+                                    const char *filename,
+                                    GError **error);
+G_END_DECLS
+
+#endif /* __MAPS_MAPBOX_RENDERER_H__ */
diff --git a/src/mapView.js b/src/mapView.js
index 36c2b7c..2fb762f 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -21,6 +21,7 @@
 
 const Champlain = imports.gi.Champlain;
 const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Geocode = imports.gi.GeocodeGlib;
 const GtkChamplain = imports.gi.GtkChamplain;
@@ -29,6 +30,7 @@ const Lang = imports.lang;
 const Application = imports.application;
 const ContactPlace = imports.contactPlace;
 const Geoclue = imports.geoclue;
+const Maps = imports.gi.GnomeMaps;
 const MapWalker = imports.mapWalker;
 const Place = imports.place;
 const PlaceMarker = imports.placeMarker;
@@ -144,11 +146,49 @@ const MapView = new Lang.Class({
         }).bind(this));
     },
 
+    _vectorSource: function() {
+        let id = 'vector-tile-glib';
+        let renderer = new Maps.MapboxRenderer();
+        renderer.load_css(GLib.build_filenamev([pkg.pkgdatadir,
+                                                'gnome-maps.mapcss']));
+
+        let tile = Champlain.NetworkTileSource.new_full(
+            id,
+            'OpenStreetMap Mapbox vector tiles',
+            'Map Data ODBL OpenStreetMap Contributors',
+            'http://creativecommons.org/licenses/by-sa/2.0/',
+            2,
+            17,
+            256,
+            Champlain.MapProjection.MAP_PROJECTION_MERCATOR,
+            'http://vector.mapzen.com/osm/all/#Z#/#X#/#Y#.mapbox',
+            renderer);
+
+        let error = this._factory.create_error_source(256);
+        let file = Champlain.FileCache.new_full(100000000,
+                                                 null,
+                                                 renderer);
+        let mem = Champlain.MemoryCache.new_full (100, renderer);
+        let chain = new Champlain.MapSourceChain();
+
+        chain.push(error);
+        chain.push(tile);
+        chain.push(file);
+        chain.push(mem);
+
+        return chain;
+    },
+
     setMapType: function(mapType) {
         if (this.view.map_source.id === mapType)
             return;
 
-        let source = this._factory.create_cached_source(mapType);
+        let source;
+        if (mapType === MapType.AERIAL)
+            source = this._vectorSource();
+        else
+            source = this._factory.create_cached_source(mapType);
+
         this.view.map_source = source;
     },
 


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