[libshumate] vector: Add fill layer



commit e7dbd71f6a3e18f4b824574d78049468457ae40e
Author: James Westman <james jwestman net>
Date:   Mon Aug 23 22:47:32 2021 -0500

    vector: Add fill layer
    
    Added fill layers. This involves parsing a vector tile in protobuf
    format and converting the features inside into cairo paths.
    
    vector_tile.pb-c.{c,h} is the generated protobuf parsing code. Since the
    spec is not likely to change, I checked these files into git instead of
    generating them as part of the build.
    
    This commit introduces dependencies on libprotobuf-c and libprotobuf.

 .gitlab-ci.yml                                     |   2 +-
 demos/map-style.json                               |   8 +
 demos/org.gnome.Shumate.Demo.json                  |  22 +
 meson.build                                        |   1 +
 shumate/meson.build                                |   7 +
 shumate/shumate-network-tile-source.c              |   2 +-
 shumate/shumate-vector-style.c                     |  25 +-
 shumate/shumate-vector-style.h                     |   2 +-
 shumate/vector/shumate-vector-background-layer.c   |   6 +-
 shumate/vector/shumate-vector-fill-layer-private.h |  32 ++
 shumate/vector/shumate-vector-fill-layer.c         |  78 ++++
 shumate/vector/shumate-vector-layer-private.h      |   6 +-
 shumate/vector/shumate-vector-layer.c              |  44 +-
 .../vector/shumate-vector-render-scope-private.h   |  37 ++
 shumate/vector/shumate-vector-render-scope.c       |  87 ++++
 shumate/vector/vector_tile.pb-c.c                  | 443 +++++++++++++++++++++
 shumate/vector/vector_tile.pb-c.h                  | 211 ++++++++++
 17 files changed, 995 insertions(+), 18 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0423729..032e99e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ fedora:
   stage: build
   image: registry.gitlab.gnome.org/gnome/gtk/fedora:v30
   script:
-    - sudo dnf install -y vala sqlite-devel libsoup-devel gtk4-devel
+    - sudo dnf install -y vala sqlite-devel libsoup-devel gtk4-devel protobuf-c-devel
     - meson _build -Db_coverage=true -Dgtk_doc=true
     - xvfb-run ninja -C _build test
     - ninja -C _build coverage
diff --git a/demos/map-style.json b/demos/map-style.json
index 890e370..0e6e5ed 100644
--- a/demos/map-style.json
+++ b/demos/map-style.json
@@ -6,6 +6,14 @@
       "paint": {
         "background-color": "#f6f5f4"
       }
+    },
+    {
+      "id": "water",
+      "type": "fill",
+      "source-layer": "water",
+      "paint": {
+        "fill-color": "#3584e4"
+      }
     }
   ]
 }
diff --git a/demos/org.gnome.Shumate.Demo.json b/demos/org.gnome.Shumate.Demo.json
index f43c207..6b4d8e5 100644
--- a/demos/org.gnome.Shumate.Demo.json
+++ b/demos/org.gnome.Shumate.Demo.json
@@ -28,6 +28,28 @@
         "*.a"
     ],
     "modules" : [
+        {
+            "name" : "protobuf",
+            "buildsystem" : "autotools",
+            "sources" : [
+                {
+                    "type" : "archive",
+                    "url" : 
"https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/protobuf-all-3.17.3.tar.gz";,
+                    "sha256" : "77ad26d3f65222fd96ccc18b055632b0bfedf295cb748b712a98ba1ac0b704b2"
+                }
+            ]
+        },
+        {
+            "name" : "protobuf-c",
+            "buildsystem" : "autotools",
+            "sources" : [
+                {
+                    "type" : "archive",
+                    "url" : 
"https://github.com/protobuf-c/protobuf-c/releases/download/v1.4.0/protobuf-c-1.4.0.tar.gz";,
+                    "sha256" : "26d98ee9bf18a6eba0d3f855ddec31dbe857667d269bc0b6017335572f85bbcb"
+                }
+            ]
+        },
         {
             "name" : "libshumate",
             "buildsystem" : "meson",
diff --git a/meson.build b/meson.build
index f1f74b1..dd421d8 100644
--- a/meson.build
+++ b/meson.build
@@ -70,6 +70,7 @@ sqlite_dep = dependency('sqlite3', version: sqlite_req)
 libsoup_dep = dependency('libsoup-2.4', version: libsoup_req)
 gtk_dep = dependency('gtk4')
 json_glib_dep = dependency('json-glib-1.0', version: json_glib_req)
+protobuf_c_dep = dependency('libprotobuf-c')
 
 introspection_dep = dependency('gobject-introspection-1.0', version: introspection_req, required: false)
 vapigen_dep = dependency('vapigen', version: vala_req, required: false)
diff --git a/shumate/meson.build b/shumate/meson.build
index e49354a..75b3224 100644
--- a/shumate/meson.build
+++ b/shumate/meson.build
@@ -27,8 +27,11 @@ libshumate_private_h = [
   'shumate-marker-private.h',
 
   'vector/shumate-vector-background-layer-private.h',
+  'vector/shumate-vector-fill-layer-private.h',
   'vector/shumate-vector-layer-private.h',
+  'vector/shumate-vector-render-scope-private.h',
   'vector/shumate-vector-utils-private.h',
+  'vector/vector_tile.pb-c.h',
 ]
 
 libshumate_sources = [
@@ -55,8 +58,11 @@ libshumate_sources = [
   'shumate-viewport.c',
 
   'vector/shumate-vector-background-layer.c',
+  'vector/shumate-vector-fill-layer.c',
   'vector/shumate-vector-layer.c',
+  'vector/shumate-vector-render-scope.c',
   'vector/shumate-vector-utils.c',
+  'vector/vector_tile.pb-c.c',
 ]
 
 libshumate_deps = [
@@ -69,6 +75,7 @@ libshumate_deps = [
   sqlite_dep,
   libsoup_dep,
   json_glib_dep,
+  protobuf_c_dep,
 ]
 
 libshumate_c_args = [
diff --git a/shumate/shumate-network-tile-source.c b/shumate/shumate-network-tile-source.c
index 1a18a16..3d04594 100644
--- a/shumate/shumate-network-tile-source.c
+++ b/shumate/shumate-network-tile-source.c
@@ -799,7 +799,7 @@ render_tile_async (ShumateNetworkTileSource *self,
       g_autoptr(GdkTexture) texture = NULL;
       g_autoptr(GError) error = NULL;
 
-      texture = shumate_vector_style_render (priv->style, shumate_tile_get_size (tile));
+      texture = shumate_vector_style_render (priv->style, shumate_tile_get_size (tile), bytes, 
shumate_tile_get_zoom_level (tile));
       if (error != NULL)
         {
           g_task_return_error (task, g_steal_pointer (&error));
diff --git a/shumate/shumate-vector-style.c b/shumate/shumate-vector-style.c
index e6de875..c692e4a 100644
--- a/shumate/shumate-vector-style.c
+++ b/shumate/shumate-vector-style.c
@@ -18,6 +18,7 @@
 #include <json-glib/json-glib.h>
 #include <cairo/cairo.h>
 
+#include "vector/shumate-vector-render-scope-private.h"
 #include "vector/shumate-vector-utils-private.h"
 #include "vector/shumate-vector-layer-private.h"
 #include "shumate-vector-style.h"
@@ -247,24 +248,34 @@ texture_new_for_surface (cairo_surface_t *surface)
  * Returns: (transfer full): a [class@Gdk.Texture] containing the rendered tile
  */
 GdkTexture *
-shumate_vector_style_render (ShumateVectorStyle *self, int size)
+shumate_vector_style_render (ShumateVectorStyle *self, int texture_size, GBytes *tile_data, double 
zoom_level)
 {
+  ShumateVectorRenderScope scope;
   GdkTexture *texture;
-  cairo_t *cr;
   cairo_surface_t *surface;
+  gconstpointer data;
+  gsize len;
 
   g_return_val_if_fail (SHUMATE_IS_VECTOR_STYLE (self), NULL);
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
-  cr = cairo_create (surface);
+  scope.target_size = texture_size;
+  scope.zoom_level = zoom_level;
 
-  for (int i = 0; i < self->layers->len; i ++)
-    shumate_vector_layer_render ((ShumateVectorLayer *)self->layers->pdata[i], cr);
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, texture_size, texture_size);
+  scope.cr = cairo_create (surface);
+
+  data = g_bytes_get_data (tile_data, &len);
+  scope.tile = vector_tile__tile__unpack (NULL, len, data);
+
+  if (scope.tile != NULL)
+    for (int i = 0; i < self->layers->len; i ++)
+      shumate_vector_layer_render ((ShumateVectorLayer *)self->layers->pdata[i], &scope);
 
   texture = texture_new_for_surface (surface);
 
-  cairo_destroy (cr);
+  cairo_destroy (scope.cr);
   cairo_surface_destroy (surface);
+  vector_tile__tile__free_unpacked (scope.tile, NULL);
 
   return texture;
 }
diff --git a/shumate/shumate-vector-style.h b/shumate/shumate-vector-style.h
index 48f7d75..908f0ac 100644
--- a/shumate/shumate-vector-style.h
+++ b/shumate/shumate-vector-style.h
@@ -56,6 +56,6 @@ ShumateVectorStyle *shumate_vector_style_create (const char *style_json, GError
 
 const char *shumate_vector_style_get_style_json (ShumateVectorStyle *self);
 
-GdkTexture *shumate_vector_style_render (ShumateVectorStyle *self, int size);
+GdkTexture *shumate_vector_style_render (ShumateVectorStyle *self, int texture_size, GBytes *tile_data, 
double zoom_level);
 
 G_END_DECLS
diff --git a/shumate/vector/shumate-vector-background-layer.c 
b/shumate/vector/shumate-vector-background-layer.c
index bc427a0..462398a 100644
--- a/shumate/vector/shumate-vector-background-layer.c
+++ b/shumate/vector/shumate-vector-background-layer.c
@@ -52,12 +52,12 @@ shumate_vector_background_layer_create_from_json (JsonObject *object, GError **e
 
 
 static void
-shumate_vector_background_layer_render (ShumateVectorLayer *layer, cairo_t *cr)
+shumate_vector_background_layer_render (ShumateVectorLayer *layer, ShumateVectorRenderScope *scope)
 {
   ShumateVectorBackgroundLayer *self = SHUMATE_VECTOR_BACKGROUND_LAYER (layer);
 
-  gdk_cairo_set_source_rgba (cr, &self->color);
-  cairo_paint_with_alpha (cr, self->opacity);
+  gdk_cairo_set_source_rgba (scope->cr, &self->color);
+  cairo_paint_with_alpha (scope->cr, self->opacity);
 }
 
 
diff --git a/shumate/vector/shumate-vector-fill-layer-private.h 
b/shumate/vector/shumate-vector-fill-layer-private.h
new file mode 100644
index 0000000..6a08816
--- /dev/null
+++ b/shumate/vector/shumate-vector-fill-layer-private.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <json-glib/json-glib.h>
+
+#include "shumate-vector-layer-private.h"
+
+G_BEGIN_DECLS
+
+#define SHUMATE_TYPE_VECTOR_FILL_LAYER (shumate_vector_fill_layer_get_type())
+
+G_DECLARE_FINAL_TYPE (ShumateVectorFillLayer, shumate_vector_fill_layer, SHUMATE, VECTOR_FILL_LAYER, 
ShumateVectorLayer)
+
+ShumateVectorLayer *shumate_vector_fill_layer_create_from_json (JsonObject *object, GError **error);
+
+G_END_DECLS
diff --git a/shumate/vector/shumate-vector-fill-layer.c b/shumate/vector/shumate-vector-fill-layer.c
new file mode 100644
index 0000000..b29f6a2
--- /dev/null
+++ b/shumate/vector/shumate-vector-fill-layer.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+#include "shumate-vector-fill-layer-private.h"
+#include "shumate-vector-utils-private.h"
+
+struct _ShumateVectorFillLayer
+{
+  ShumateVectorLayer parent_instance;
+
+  GdkRGBA color;
+  double opacity;
+};
+
+G_DEFINE_TYPE (ShumateVectorFillLayer, shumate_vector_fill_layer, SHUMATE_TYPE_VECTOR_LAYER)
+
+
+ShumateVectorLayer *
+shumate_vector_fill_layer_create_from_json (JsonObject *object, GError **error)
+{
+  ShumateVectorFillLayer *layer = g_object_new (SHUMATE_TYPE_VECTOR_FILL_LAYER, NULL);
+  JsonNode *paint_node;
+
+  if ((paint_node = json_object_get_member (object, "paint")))
+    {
+      JsonObject *paint;
+
+      if (!shumate_vector_json_get_object (paint_node, &paint, error))
+        return NULL;
+
+      gdk_rgba_parse (&layer->color, json_object_get_string_member_with_default (paint, "fill-color", 
"#000000"));
+      layer->opacity = json_object_get_double_member_with_default (paint, "fill-opacity", 1.0);
+    }
+
+  return (ShumateVectorLayer *)layer;
+}
+
+
+static void
+shumate_vector_fill_layer_render (ShumateVectorLayer *layer, ShumateVectorRenderScope *scope)
+{
+  ShumateVectorFillLayer *self = SHUMATE_VECTOR_FILL_LAYER (layer);
+
+  shumate_vector_render_scope_exec_geometry (scope);
+
+  cairo_set_source_rgba (scope->cr, self->color.red, self->color.green, self->color.blue, self->opacity);
+  cairo_fill (scope->cr);
+}
+
+
+static void
+shumate_vector_fill_layer_class_init (ShumateVectorFillLayerClass *klass)
+{
+  ShumateVectorLayerClass *layer_class = SHUMATE_VECTOR_LAYER_CLASS (klass);
+
+  layer_class->render = shumate_vector_fill_layer_render;
+}
+
+
+static void
+shumate_vector_fill_layer_init (ShumateVectorFillLayer *self)
+{
+}
diff --git a/shumate/vector/shumate-vector-layer-private.h b/shumate/vector/shumate-vector-layer-private.h
index 9252bdc..7ffaf3b 100644
--- a/shumate/vector/shumate-vector-layer-private.h
+++ b/shumate/vector/shumate-vector-layer-private.h
@@ -20,6 +20,7 @@
 #include <glib-object.h>
 #include <json-glib/json-glib.h>
 #include <cairo/cairo.h>
+#include "shumate-vector-render-scope-private.h"
 
 G_BEGIN_DECLS
 
@@ -31,11 +32,12 @@ struct _ShumateVectorLayerClass
 {
   GObjectClass parent_class;
 
-  void (*render) (ShumateVectorLayer *self, cairo_t *cr);
+  void (*render) (ShumateVectorLayer *self, ShumateVectorRenderScope *scope);
 };
 
 ShumateVectorLayer *shumate_vector_layer_create_from_json (JsonObject *object, GError **error);
 
-void shumate_vector_layer_render (ShumateVectorLayer *self, cairo_t *cr);
+void shumate_vector_layer_render (ShumateVectorLayer *self, ShumateVectorRenderScope *scope);
+const char *shumate_vector_layer_get_source_layer (ShumateVectorLayer *self);
 
 G_END_DECLS
diff --git a/shumate/vector/shumate-vector-layer.c b/shumate/vector/shumate-vector-layer.c
index 89064a2..f109a8e 100644
--- a/shumate/vector/shumate-vector-layer.c
+++ b/shumate/vector/shumate-vector-layer.c
@@ -17,6 +17,7 @@
 
 #include <json-glib/json-glib.h>
 #include "shumate-vector-background-layer-private.h"
+#include "shumate-vector-fill-layer-private.h"
 #include "shumate-vector-layer-private.h"
 
 typedef struct
@@ -46,6 +47,8 @@ shumate_vector_layer_create_from_json (JsonObject *object, GError **error)
 
   if (g_strcmp0 (type, "background") == 0)
     layer = shumate_vector_background_layer_create_from_json (object, error);
+  else if (g_strcmp0 (type, "fill") == 0)
+    layer = shumate_vector_fill_layer_create_from_json (object, error);
   else
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unsupported layer type \"%s\"", type);
@@ -99,12 +102,47 @@ shumate_vector_layer_init (ShumateVectorLayer *self)
  * shumate_vector_layer_render:
  * @self: a [class@VectorLayer]
  *
- * Renders the layer by calling the [vfunc@VectorLayer.render] virtual method.
+ * Renders the layer.
  */
 void
-shumate_vector_layer_render (ShumateVectorLayer *self, cairo_t *cr)
+shumate_vector_layer_render (ShumateVectorLayer *self, ShumateVectorRenderScope *scope)
 {
+  ShumateVectorLayerPrivate *priv = shumate_vector_layer_get_instance_private (self);
+
   g_return_if_fail (SHUMATE_IS_VECTOR_LAYER (self));
 
-  SHUMATE_VECTOR_LAYER_GET_CLASS (self)->render (self, cr);
+  if (scope->zoom_level < priv->minzoom || scope->zoom_level > priv->maxzoom)
+    return;
+
+  scope->feature = NULL;
+
+  if (priv->source_layer == NULL)
+    /* Style layers with no source layer are rendered once */
+    SHUMATE_VECTOR_LAYER_GET_CLASS (self)->render (self, scope);
+  else if (shumate_vector_render_scope_find_layer (scope, priv->source_layer))
+    {
+      /* Style layers with a source layer are rendered once for each feature
+       * in that layer, if it exists */
+
+      cairo_save (scope->cr);
+
+      scope->scale = (double) scope->layer->extent / scope->target_size;
+      cairo_scale (scope->cr, 1.0 / scope->scale, 1.0 / scope->scale);
+
+      for (int j = 0; j < scope->layer->n_features; j ++)
+        {
+          scope->feature = scope->layer->features[j];
+          SHUMATE_VECTOR_LAYER_GET_CLASS (self)->render (self, scope);
+        }
+
+      cairo_restore (scope->cr);
+    }
+}
+
+const char *
+shumate_vector_layer_get_source_layer (ShumateVectorLayer *self)
+{
+  ShumateVectorLayerPrivate *priv = shumate_vector_layer_get_instance_private (self);
+  g_return_val_if_fail (SHUMATE_IS_VECTOR_LAYER (self), NULL);
+  return priv->source_layer;
 }
diff --git a/shumate/vector/shumate-vector-render-scope-private.h 
b/shumate/vector/shumate-vector-render-scope-private.h
new file mode 100644
index 0000000..e28c043
--- /dev/null
+++ b/shumate/vector/shumate-vector-render-scope-private.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <cairo/cairo.h>
+#include "vector_tile.pb-c.h"
+
+typedef struct {
+  cairo_t *cr;
+  int target_size;
+  double scale;
+  double zoom_level;
+
+  VectorTile__Tile *tile;
+  VectorTile__Tile__Layer *layer;
+  VectorTile__Tile__Feature *feature;
+} ShumateVectorRenderScope;
+
+
+gboolean shumate_vector_render_scope_find_layer (ShumateVectorRenderScope *self, const char *layer_name);
+void shumate_vector_render_scope_exec_geometry (ShumateVectorRenderScope *self);
diff --git a/shumate/vector/shumate-vector-render-scope.c b/shumate/vector/shumate-vector-render-scope.c
new file mode 100644
index 0000000..58f8a1c
--- /dev/null
+++ b/shumate/vector/shumate-vector-render-scope.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "shumate-vector-render-scope-private.h"
+
+/* Sets the current layer by name. */
+gboolean
+shumate_vector_render_scope_find_layer (ShumateVectorRenderScope *self, const char *layer_name)
+{
+  for (int i = 0; i < self->tile->n_layers; i ++)
+    {
+      VectorTile__Tile__Layer *layer = self->tile->layers[i];
+      if (g_strcmp0 (layer->name, layer_name) == 0)
+        {
+          self->layer = layer;
+          return TRUE;
+        }
+    }
+
+  self->layer = NULL;
+  return FALSE;
+}
+
+static int
+zigzag (guint value)
+{
+  return (value >> 1) ^ (-(value & 1));
+}
+
+/* Draws the current feature as a path onto the scope's cairo context. */
+void
+shumate_vector_render_scope_exec_geometry (ShumateVectorRenderScope *self)
+{
+  g_return_if_fail (self->feature != NULL);
+
+  cairo_new_path (self->cr);
+  cairo_move_to (self->cr, 0, 0);
+
+  for (int i = 0; i < self->feature->n_geometry; i ++)
+    {
+      int cmd = self->feature->geometry[i];
+      double dx, dy;
+
+      /* See https://github.com/mapbox/vector-tile-spec/tree/master/2.1#43-geometry-encoding */
+      int op = cmd & 0x7;
+      int repeat = cmd >> 3;
+
+      for (int j = 0; j < repeat; j ++)
+        {
+          switch (op) {
+          case 1:
+            g_return_if_fail (i + 2 < self->feature->n_geometry);
+            dx = zigzag (self->feature->geometry[++i]);
+            dy = zigzag (self->feature->geometry[++i]);
+            cairo_rel_move_to (self->cr, dx, dy);
+            break;
+          case 2:
+            g_return_if_fail (i + 2 < self->feature->n_geometry);
+            dx = zigzag (self->feature->geometry[++i]);
+            dy = zigzag (self->feature->geometry[++i]);
+            cairo_rel_line_to (self->cr, dx, dy);
+            break;
+          case 7:
+            cairo_get_current_point (self->cr, &dx, &dy);
+            cairo_close_path (self->cr);
+            cairo_move_to (self->cr, dx, dy);
+            break;
+          default:
+            g_assert_not_reached ();
+          }
+        }
+    }
+}
diff --git a/shumate/vector/vector_tile.pb-c.c b/shumate/vector/vector_tile.pb-c.c
new file mode 100644
index 0000000..c15d332
--- /dev/null
+++ b/shumate/vector/vector_tile.pb-c.c
@@ -0,0 +1,443 @@
+/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
+/* Generated from: shumate/vector/vector_tile.proto */
+
+/* Do not generate deprecated warnings for self */
+#ifndef PROTOBUF_C__NO_DEPRECATED
+#define PROTOBUF_C__NO_DEPRECATED
+#endif
+
+#include "shumate/vector/vector_tile.pb-c.h"
+void   vector_tile__tile__value__init
+                     (VectorTile__Tile__Value         *message)
+{
+  static const VectorTile__Tile__Value init_value = VECTOR_TILE__TILE__VALUE__INIT;
+  *message = init_value;
+}
+void   vector_tile__tile__feature__init
+                     (VectorTile__Tile__Feature         *message)
+{
+  static const VectorTile__Tile__Feature init_value = VECTOR_TILE__TILE__FEATURE__INIT;
+  *message = init_value;
+}
+void   vector_tile__tile__layer__init
+                     (VectorTile__Tile__Layer         *message)
+{
+  static const VectorTile__Tile__Layer init_value = VECTOR_TILE__TILE__LAYER__INIT;
+  *message = init_value;
+}
+void   vector_tile__tile__init
+                     (VectorTile__Tile         *message)
+{
+  static const VectorTile__Tile init_value = VECTOR_TILE__TILE__INIT;
+  *message = init_value;
+}
+size_t vector_tile__tile__get_packed_size
+                     (const VectorTile__Tile *message)
+{
+  assert(message->base.descriptor == &vector_tile__tile__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t vector_tile__tile__pack
+                     (const VectorTile__Tile *message,
+                      uint8_t       *out)
+{
+  assert(message->base.descriptor == &vector_tile__tile__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t vector_tile__tile__pack_to_buffer
+                     (const VectorTile__Tile *message,
+                      ProtobufCBuffer *buffer)
+{
+  assert(message->base.descriptor == &vector_tile__tile__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+VectorTile__Tile *
+       vector_tile__tile__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (VectorTile__Tile *)
+     protobuf_c_message_unpack (&vector_tile__tile__descriptor,
+                                allocator, len, data);
+}
+void   vector_tile__tile__free_unpacked
+                     (VectorTile__Tile *message,
+                      ProtobufCAllocator *allocator)
+{
+  if(!message)
+    return;
+  assert(message->base.descriptor == &vector_tile__tile__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCFieldDescriptor vector_tile__tile__value__field_descriptors[7] =
+{
+  {
+    "string_value",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    offsetof(VectorTile__Tile__Value, string_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "float_value",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_FLOAT,
+    offsetof(VectorTile__Tile__Value, has_float_value),
+    offsetof(VectorTile__Tile__Value, float_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "double_value",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_DOUBLE,
+    offsetof(VectorTile__Tile__Value, has_double_value),
+    offsetof(VectorTile__Tile__Value, double_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "int_value",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_INT64,
+    offsetof(VectorTile__Tile__Value, has_int_value),
+    offsetof(VectorTile__Tile__Value, int_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "uint_value",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT64,
+    offsetof(VectorTile__Tile__Value, has_uint_value),
+    offsetof(VectorTile__Tile__Value, uint_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "sint_value",
+    6,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_SINT64,
+    offsetof(VectorTile__Tile__Value, has_sint_value),
+    offsetof(VectorTile__Tile__Value, sint_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "bool_value",
+    7,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    offsetof(VectorTile__Tile__Value, has_bool_value),
+    offsetof(VectorTile__Tile__Value, bool_value),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+};
+static const unsigned vector_tile__tile__value__field_indices_by_name[] = {
+  6,   /* field[6] = bool_value */
+  2,   /* field[2] = double_value */
+  1,   /* field[1] = float_value */
+  3,   /* field[3] = int_value */
+  5,   /* field[5] = sint_value */
+  0,   /* field[0] = string_value */
+  4,   /* field[4] = uint_value */
+};
+static const ProtobufCIntRange vector_tile__tile__value__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 7 }
+};
+const ProtobufCMessageDescriptor vector_tile__tile__value__descriptor =
+{
+  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+  "vector_tile.Tile.Value",
+  "Value",
+  "VectorTile__Tile__Value",
+  "vector_tile",
+  sizeof(VectorTile__Tile__Value),
+  7,
+  vector_tile__tile__value__field_descriptors,
+  vector_tile__tile__value__field_indices_by_name,
+  1,  vector_tile__tile__value__number_ranges,
+  (ProtobufCMessageInit) vector_tile__tile__value__init,
+  NULL,NULL,NULL    /* reserved[123] */
+};
+static const uint64_t vector_tile__tile__feature__id__default_value = 0ull;
+static const VectorTile__Tile__GeomType vector_tile__tile__feature__type__default_value = 
VECTOR_TILE__TILE__GEOM_TYPE__UNKNOWN;
+static const ProtobufCFieldDescriptor vector_tile__tile__feature__field_descriptors[4] =
+{
+  {
+    "id",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT64,
+    offsetof(VectorTile__Tile__Feature, has_id),
+    offsetof(VectorTile__Tile__Feature, id),
+    NULL,
+    &vector_tile__tile__feature__id__default_value,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "tags",
+    2,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    offsetof(VectorTile__Tile__Feature, n_tags),
+    offsetof(VectorTile__Tile__Feature, tags),
+    NULL,
+    NULL,
+    0 | PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "type",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_ENUM,
+    offsetof(VectorTile__Tile__Feature, has_type),
+    offsetof(VectorTile__Tile__Feature, type),
+    &vector_tile__tile__geom_type__descriptor,
+    &vector_tile__tile__feature__type__default_value,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "geometry",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    offsetof(VectorTile__Tile__Feature, n_geometry),
+    offsetof(VectorTile__Tile__Feature, geometry),
+    NULL,
+    NULL,
+    0 | PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+};
+static const unsigned vector_tile__tile__feature__field_indices_by_name[] = {
+  3,   /* field[3] = geometry */
+  0,   /* field[0] = id */
+  1,   /* field[1] = tags */
+  2,   /* field[2] = type */
+};
+static const ProtobufCIntRange vector_tile__tile__feature__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 4 }
+};
+const ProtobufCMessageDescriptor vector_tile__tile__feature__descriptor =
+{
+  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+  "vector_tile.Tile.Feature",
+  "Feature",
+  "VectorTile__Tile__Feature",
+  "vector_tile",
+  sizeof(VectorTile__Tile__Feature),
+  4,
+  vector_tile__tile__feature__field_descriptors,
+  vector_tile__tile__feature__field_indices_by_name,
+  1,  vector_tile__tile__feature__number_ranges,
+  (ProtobufCMessageInit) vector_tile__tile__feature__init,
+  NULL,NULL,NULL    /* reserved[123] */
+};
+static const uint32_t vector_tile__tile__layer__version__default_value = 1u;
+static const uint32_t vector_tile__tile__layer__extent__default_value = 4096u;
+static const ProtobufCFieldDescriptor vector_tile__tile__layer__field_descriptors[6] =
+{
+  {
+    "name",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    offsetof(VectorTile__Tile__Layer, name),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "features",
+    2,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    offsetof(VectorTile__Tile__Layer, n_features),
+    offsetof(VectorTile__Tile__Layer, features),
+    &vector_tile__tile__feature__descriptor,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "keys",
+    3,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_STRING,
+    offsetof(VectorTile__Tile__Layer, n_keys),
+    offsetof(VectorTile__Tile__Layer, keys),
+    NULL,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "values",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    offsetof(VectorTile__Tile__Layer, n_values),
+    offsetof(VectorTile__Tile__Layer, values),
+    &vector_tile__tile__value__descriptor,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "extent",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    offsetof(VectorTile__Tile__Layer, has_extent),
+    offsetof(VectorTile__Tile__Layer, extent),
+    NULL,
+    &vector_tile__tile__layer__extent__default_value,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+  {
+    "version",
+    15,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    offsetof(VectorTile__Tile__Layer, version),
+    NULL,
+    &vector_tile__tile__layer__version__default_value,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+};
+static const unsigned vector_tile__tile__layer__field_indices_by_name[] = {
+  4,   /* field[4] = extent */
+  1,   /* field[1] = features */
+  2,   /* field[2] = keys */
+  0,   /* field[0] = name */
+  3,   /* field[3] = values */
+  5,   /* field[5] = version */
+};
+static const ProtobufCIntRange vector_tile__tile__layer__number_ranges[2 + 1] =
+{
+  { 1, 0 },
+  { 15, 5 },
+  { 0, 6 }
+};
+const ProtobufCMessageDescriptor vector_tile__tile__layer__descriptor =
+{
+  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+  "vector_tile.Tile.Layer",
+  "Layer",
+  "VectorTile__Tile__Layer",
+  "vector_tile",
+  sizeof(VectorTile__Tile__Layer),
+  6,
+  vector_tile__tile__layer__field_descriptors,
+  vector_tile__tile__layer__field_indices_by_name,
+  2,  vector_tile__tile__layer__number_ranges,
+  (ProtobufCMessageInit) vector_tile__tile__layer__init,
+  NULL,NULL,NULL    /* reserved[123] */
+};
+static const ProtobufCEnumValue vector_tile__tile__geom_type__enum_values_by_number[4] =
+{
+  { "UNKNOWN", "VECTOR_TILE__TILE__GEOM_TYPE__UNKNOWN", 0 },
+  { "POINT", "VECTOR_TILE__TILE__GEOM_TYPE__POINT", 1 },
+  { "LINESTRING", "VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING", 2 },
+  { "POLYGON", "VECTOR_TILE__TILE__GEOM_TYPE__POLYGON", 3 },
+};
+static const ProtobufCIntRange vector_tile__tile__geom_type__value_ranges[] = {
+{0, 0},{0, 4}
+};
+static const ProtobufCEnumValueIndex vector_tile__tile__geom_type__enum_values_by_name[4] =
+{
+  { "LINESTRING", 2 },
+  { "POINT", 1 },
+  { "POLYGON", 3 },
+  { "UNKNOWN", 0 },
+};
+const ProtobufCEnumDescriptor vector_tile__tile__geom_type__descriptor =
+{
+  PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
+  "vector_tile.Tile.GeomType",
+  "GeomType",
+  "VectorTile__Tile__GeomType",
+  "vector_tile",
+  4,
+  vector_tile__tile__geom_type__enum_values_by_number,
+  4,
+  vector_tile__tile__geom_type__enum_values_by_name,
+  1,
+  vector_tile__tile__geom_type__value_ranges,
+  NULL,NULL,NULL,NULL   /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor vector_tile__tile__field_descriptors[1] =
+{
+  {
+    "layers",
+    3,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    offsetof(VectorTile__Tile, n_layers),
+    offsetof(VectorTile__Tile, layers),
+    &vector_tile__tile__layer__descriptor,
+    NULL,
+    0,             /* flags */
+    0,NULL,NULL    /* reserved1,reserved2, etc */
+  },
+};
+static const unsigned vector_tile__tile__field_indices_by_name[] = {
+  0,   /* field[0] = layers */
+};
+static const ProtobufCIntRange vector_tile__tile__number_ranges[1 + 1] =
+{
+  { 3, 0 },
+  { 0, 1 }
+};
+const ProtobufCMessageDescriptor vector_tile__tile__descriptor =
+{
+  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+  "vector_tile.Tile",
+  "Tile",
+  "VectorTile__Tile",
+  "vector_tile",
+  sizeof(VectorTile__Tile),
+  1,
+  vector_tile__tile__field_descriptors,
+  vector_tile__tile__field_indices_by_name,
+  1,  vector_tile__tile__number_ranges,
+  (ProtobufCMessageInit) vector_tile__tile__init,
+  NULL,NULL,NULL    /* reserved[123] */
+};
diff --git a/shumate/vector/vector_tile.pb-c.h b/shumate/vector/vector_tile.pb-c.h
new file mode 100644
index 0000000..27ad7e1
--- /dev/null
+++ b/shumate/vector/vector_tile.pb-c.h
@@ -0,0 +1,211 @@
+/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
+/* Generated from: shumate/vector/vector_tile.proto */
+
+#ifndef PROTOBUF_C_shumate_2fvector_2fvector_5ftile_2eproto__INCLUDED
+#define PROTOBUF_C_shumate_2fvector_2fvector_5ftile_2eproto__INCLUDED
+
+#include <protobuf-c/protobuf-c.h>
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if PROTOBUF_C_VERSION_NUMBER < 1000000
+# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c 
headers. Please update your headers.
+#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION
+# error This file was generated by an older version of protoc-c which is incompatible with your 
libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
+#endif
+
+
+typedef struct _VectorTile__Tile VectorTile__Tile;
+typedef struct _VectorTile__Tile__Value VectorTile__Tile__Value;
+typedef struct _VectorTile__Tile__Feature VectorTile__Tile__Feature;
+typedef struct _VectorTile__Tile__Layer VectorTile__Tile__Layer;
+
+
+/* --- enums --- */
+
+/*
+ * GeomType is described in section 4.3.4 of the specification
+ */
+typedef enum _VectorTile__Tile__GeomType {
+  VECTOR_TILE__TILE__GEOM_TYPE__UNKNOWN = 0,
+  VECTOR_TILE__TILE__GEOM_TYPE__POINT = 1,
+  VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING = 2,
+  VECTOR_TILE__TILE__GEOM_TYPE__POLYGON = 3
+    PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(VECTOR_TILE__TILE__GEOM_TYPE)
+} VectorTile__Tile__GeomType;
+
+/* --- messages --- */
+
+/*
+ * Variant type encoding
+ * The use of values is described in section 4.1 of the specification
+ */
+struct  _VectorTile__Tile__Value
+{
+  ProtobufCMessage base;
+  /*
+   * Exactly one of these values must be present in a valid message
+   */
+  char *string_value;
+  protobuf_c_boolean has_float_value;
+  float float_value;
+  protobuf_c_boolean has_double_value;
+  double double_value;
+  protobuf_c_boolean has_int_value;
+  int64_t int_value;
+  protobuf_c_boolean has_uint_value;
+  uint64_t uint_value;
+  protobuf_c_boolean has_sint_value;
+  int64_t sint_value;
+  protobuf_c_boolean has_bool_value;
+  protobuf_c_boolean bool_value;
+};
+#define VECTOR_TILE__TILE__VALUE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&vector_tile__tile__value__descriptor) \
+    , NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+
+/*
+ * Features are described in section 4.2 of the specification
+ */
+struct  _VectorTile__Tile__Feature
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_id;
+  uint64_t id;
+  /*
+   * Tags of this feature are encoded as repeated pairs of
+   * integers.
+   * A detailed description of tags is located in sections
+   * 4.2 and 4.4 of the specification
+   */
+  size_t n_tags;
+  uint32_t *tags;
+  /*
+   * The type of geometry stored in this feature.
+   */
+  protobuf_c_boolean has_type;
+  VectorTile__Tile__GeomType type;
+  /*
+   * Contains a stream of commands and parameters (vertices).
+   * A detailed description on geometry encoding is located in 
+   * section 4.3 of the specification.
+   */
+  size_t n_geometry;
+  uint32_t *geometry;
+};
+#define VECTOR_TILE__TILE__FEATURE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&vector_tile__tile__feature__descriptor) \
+    , 0, 0ull, 0,NULL, 0, VECTOR_TILE__TILE__GEOM_TYPE__UNKNOWN, 0,NULL }
+
+
+/*
+ * Layers are described in section 4.1 of the specification
+ */
+struct  _VectorTile__Tile__Layer
+{
+  ProtobufCMessage base;
+  /*
+   * Any compliant implementation must first read the version
+   * number encoded in this message and choose the correct
+   * implementation for this version number before proceeding to
+   * decode other parts of this message.
+   */
+  uint32_t version;
+  char *name;
+  /*
+   * The actual features in this tile.
+   */
+  size_t n_features;
+  VectorTile__Tile__Feature **features;
+  /*
+   * Dictionary encoding for keys
+   */
+  size_t n_keys;
+  char **keys;
+  /*
+   * Dictionary encoding for values
+   */
+  size_t n_values;
+  VectorTile__Tile__Value **values;
+  /*
+   * Although this is an "optional" field it is required by the specification.
+   * See https://github.com/mapbox/vector-tile-spec/issues/47
+   */
+  protobuf_c_boolean has_extent;
+  uint32_t extent;
+};
+#define VECTOR_TILE__TILE__LAYER__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&vector_tile__tile__layer__descriptor) \
+    , 1u, NULL, 0,NULL, 0,NULL, 0,NULL, 0, 4096u }
+
+
+struct  _VectorTile__Tile
+{
+  ProtobufCMessage base;
+  size_t n_layers;
+  VectorTile__Tile__Layer **layers;
+};
+#define VECTOR_TILE__TILE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&vector_tile__tile__descriptor) \
+    , 0,NULL }
+
+
+/* VectorTile__Tile__Value methods */
+void   vector_tile__tile__value__init
+                     (VectorTile__Tile__Value         *message);
+/* VectorTile__Tile__Feature methods */
+void   vector_tile__tile__feature__init
+                     (VectorTile__Tile__Feature         *message);
+/* VectorTile__Tile__Layer methods */
+void   vector_tile__tile__layer__init
+                     (VectorTile__Tile__Layer         *message);
+/* VectorTile__Tile methods */
+void   vector_tile__tile__init
+                     (VectorTile__Tile         *message);
+size_t vector_tile__tile__get_packed_size
+                     (const VectorTile__Tile   *message);
+size_t vector_tile__tile__pack
+                     (const VectorTile__Tile   *message,
+                      uint8_t             *out);
+size_t vector_tile__tile__pack_to_buffer
+                     (const VectorTile__Tile   *message,
+                      ProtobufCBuffer     *buffer);
+VectorTile__Tile *
+       vector_tile__tile__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   vector_tile__tile__free_unpacked
+                     (VectorTile__Tile *message,
+                      ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*VectorTile__Tile__Value_Closure)
+                 (const VectorTile__Tile__Value *message,
+                  void *closure_data);
+typedef void (*VectorTile__Tile__Feature_Closure)
+                 (const VectorTile__Tile__Feature *message,
+                  void *closure_data);
+typedef void (*VectorTile__Tile__Layer_Closure)
+                 (const VectorTile__Tile__Layer *message,
+                  void *closure_data);
+typedef void (*VectorTile__Tile_Closure)
+                 (const VectorTile__Tile *message,
+                  void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCMessageDescriptor vector_tile__tile__descriptor;
+extern const ProtobufCMessageDescriptor vector_tile__tile__value__descriptor;
+extern const ProtobufCMessageDescriptor vector_tile__tile__feature__descriptor;
+extern const ProtobufCMessageDescriptor vector_tile__tile__layer__descriptor;
+extern const ProtobufCEnumDescriptor    vector_tile__tile__geom_type__descriptor;
+
+PROTOBUF_C__END_DECLS
+
+
+#endif  /* PROTOBUF_C_shumate_2fvector_2fvector_5ftile_2eproto__INCLUDED */


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