]> git.street.me.uk Git - andy/viking.git/commitdiff
Create a mapnik interface object so each Mapnik Layer will render using a separate...
authorRob Norris <rw_norris@hotmail.com>
Sat, 6 Dec 2014 23:25:48 +0000 (23:25 +0000)
committerRob Norris <rw_norris@hotmail.com>
Tue, 27 Jan 2015 23:42:55 +0000 (23:42 +0000)
src/mapnik_interface.cpp
src/mapnik_interface.h
src/vikmapniklayer.c

index d7c1507dfe5efd810c3211257cc9263a912695ae..bd2fef2fbcc551ca97c6f693f764ab2d9577e34e 100644 (file)
 #include <mapnik/box2d.hpp>
 #endif
 
-static mapnik::Map myMap;
+#define MAPNIK_INTERFACE_TYPE            (mapnik_interface_get_type ())
+#define MAPNIK_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAPNIK_INTERFACE_TYPE, MapnikInterface))
+#define MAPNIK_INTERFACE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), MAPNIK_INTERFACE_TYPE, MapnikInterfaceClass))
+#define IS_MAPNIK_INTERFACE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAPNIK_INTERFACE_TYPE))
+#define IS_MAPNIK_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAPNIK_INTERFACE_TYPE))
+
+typedef struct _MapnikInterfaceClass MapnikInterfaceClass;
+typedef struct _MapnikInterface MapnikInterface;
+
+GType mapnik_interface_get_type ();
+struct _MapnikInterfaceClass
+{
+       GObjectClass object_class;
+};
+
+static void mapnik_interface_class_init ( MapnikInterfaceClass *mic )
+{
+}
+
+static void mapnik_interface_init ( MapnikInterface *mi )
+{
+}
+
+struct _MapnikInterface {
+       GObject obj;
+       mapnik::Map *myMap;
+};
+
+G_DEFINE_TYPE (MapnikInterface, mapnik_interface, G_TYPE_OBJECT)
 
 // Can't change prj after init - but ATM only support drawing in Spherical Mercator
 static mapnik::projection prj( mapnik::MAPNIK_GMERC_PROJ );
 
-void mapnik_interface_init (const char *plugins_dir, const char* font_dir, int font_dir_recurse)
+MapnikInterface* mapnik_interface_new ()
+{
+       MapnikInterface* mi = MAPNIK_INTERFACE ( g_object_new ( MAPNIK_INTERFACE_TYPE, NULL ) );
+       mi->myMap = new mapnik::Map;
+       return mi;
+}
+
+void mapnik_interface_free (MapnikInterface* mi)
+{
+       if ( mi )
+               delete mi->myMap;
+       g_object_unref ( G_OBJECT(mi) );
+}
+
+/**
+ * mapnik_interface_initialize:
+ */
+void mapnik_interface_initialize (const char *plugins_dir, const char* font_dir, int font_dir_recurse)
 {
        g_debug ("using mapnik version %s", MAPNIK_VERSION_STRING );
        try {
@@ -87,30 +132,33 @@ void mapnik_interface_init (const char *plugins_dir, const char* font_dir, int f
  *
  * Returns 0 on success.
  */
-int mapnik_interface_load_map_file ( const gchar *filename,
+int mapnik_interface_load_map_file ( MapnikInterface* mi,
+                                     const gchar *filename,
                                      guint width,
                                      guint height )
 {
+       if ( !mi ) return 1;
        try {
-               mapnik::load_map(myMap, filename);
+               mi->myMap->remove_all(); // Support reloading
+               mapnik::load_map(*mi->myMap, filename);
 
-               myMap.resize(width,height);
-               myMap.set_srs ( mapnik::MAPNIK_GMERC_PROJ ); // ONLY WEB MERCATOR output supported ATM
+               mi->myMap->resize(width,height);
+               mi->myMap->set_srs ( mapnik::MAPNIK_GMERC_PROJ ); // ONLY WEB MERCATOR output supported ATM
 
                // IIRC This size is the number of pixels outside the tile to be considered so stuff is shown (i.e. particularly labels)
                // Only set buffer size if the buffer size isn't explicitly set in the mapnik stylesheet.
                // Alternatively render a bigger 'virtual' tile and then only use the appropriate subset
-               if (myMap.buffer_size() == 0) {
-                       myMap.set_buffer_size((width+height/4)); // e.g. 128 for a 256x256 image.
+               if (mi->myMap->buffer_size() == 0) {
+                       mi->myMap->set_buffer_size((width+height/4)); // e.g. 128 for a 256x256 image.
                }
 
-               g_debug ("%s layers: %d", __FUNCTION__, myMap.layer_count() );
+               g_debug ("%s layers: %d", __FUNCTION__, mi->myMap->layer_count() );
        } catch (std::exception const& ex) {
                g_debug ("An error occurred while loading the mapnik config '%s': %s", filename, ex.what());
                return 2;
        } catch (...) {
                g_debug ("An unknown error occurred while loading the mapnik config '%s': %s", filename );
-               return 1;
+               return 3;
        }
        return 0;
 }
@@ -149,8 +197,10 @@ convert_argb32_to_gdkpixbuf_data (unsigned char const *Source, unsigned int widt
  *
  * Returns a #GdkPixbuf of the specified area. #GdkPixbuf may be NULL
  */
-GdkPixbuf* mapnik_interface_render ( double lat_tl, double lon_tl, double lat_br, double lon_br )
+GdkPixbuf* mapnik_interface_render ( MapnikInterface* mi, double lat_tl, double lon_tl, double lat_br, double lon_br )
 {
+       if ( !mi ) return NULL;
+
        // Note prj & bbox want stuff in lon,lat order!
        double p0x = lon_tl;
        double p0y = lat_tl;
@@ -163,13 +213,13 @@ GdkPixbuf* mapnik_interface_render ( double lat_tl, double lon_tl, double lat_br
 
        GdkPixbuf *pixbuf = NULL;
        try {
-               unsigned width  = myMap.width();
-               unsigned height = myMap.height();
+               unsigned width  = mi->myMap->width();
+               unsigned height = mi->myMap->height();
                mapnik::image_32 image(width,height);
                mapnik::box2d<double> bbox(p0x, p0y, p1x, p1y);
-               myMap.zoom_to_box(bbox);
+               mi->myMap->zoom_to_box(bbox);
                // FUTURE: option to use cairo / grid renderers?
-               mapnik::agg_renderer<mapnik::image_32> render(myMap,image);
+               mapnik::agg_renderer<mapnik::image_32> render(*mi->myMap,image);
                render.apply();
 
                if ( image.painted() ) {
index 9533c997e04546c645578b62a2fd7def1d3ded2e..159a8d395f9733d9734110d83ee98f19f09aee89 100644 (file)
@@ -28,13 +28,19 @@ extern "C" {
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
-void mapnik_interface_init (const char *plugins_dir, const char* font_dir, int font_dir_recurse);
+typedef struct _MapnikInterface MapnikInterface;
 
-int mapnik_interface_load_map_file ( const gchar *filename,
+void mapnik_interface_initialize (const char *plugins_dir, const char* font_dir, int font_dir_recurse);
+
+MapnikInterface* mapnik_interface_new ();
+void mapnik_interface_free (MapnikInterface* mi);
+
+int mapnik_interface_load_map_file ( MapnikInterface* mi,
+                                     const gchar *filename,
                                      guint width,
                                      guint height );
 
-GdkPixbuf* mapnik_interface_render ( double lat_tl, double lon_tl, double lat_br, double lon_br );
+GdkPixbuf* mapnik_interface_render ( MapnikInterface* mi, double lat_tl, double lon_tl, double lat_br, double lon_br );
 
 #ifdef __cplusplus
 }
index ee023d1173082e9ca28e78e2bc218ffdcc63a626..342a6d7e36f993288639b2489cf0424cc26d5250 100644 (file)
@@ -162,6 +162,7 @@ struct _VikMapnikLayer {
 
        guint tile_size_x; // Y is the same as X ATM
        gboolean loaded;
+       MapnikInterface* mi;
 };
 
 #define MAPNIK_PREFS_GROUP_KEY "mapnik"
@@ -208,9 +209,9 @@ static VikLayerParam prefs[] = {
 // NB Only performed once per program run
 static void mapnik_layer_class_init ( VikMapnikLayerClass *klass )
 {
-       mapnik_interface_init ( a_preferences_get (MAPNIK_PREFS_NAMESPACE"plugins_directory")->s,
-                               a_preferences_get (MAPNIK_PREFS_NAMESPACE"fonts_directory")->s,
-                               a_preferences_get (MAPNIK_PREFS_NAMESPACE"recurse_fonts_directory")->b );
+       mapnik_interface_initialize ( a_preferences_get (MAPNIK_PREFS_NAMESPACE"plugins_directory")->s,
+                                     a_preferences_get (MAPNIK_PREFS_NAMESPACE"fonts_directory")->s,
+                                     a_preferences_get (MAPNIK_PREFS_NAMESPACE"recurse_fonts_directory")->b );
 }
 
 void vik_mapnik_layer_init (void)
@@ -322,6 +323,7 @@ static VikMapnikLayer *mapnik_layer_new ( VikViewport *vvp )
        vik_layer_set_defaults ( VIK_LAYER(vml), vvp );
        vml->tile_size_x = size_default().u; // FUTURE: Is there any use in this being configurable?
        vml->loaded = FALSE;
+       vml->mi = mapnik_interface_new();
        return vml;
 }
 
@@ -332,7 +334,7 @@ static void mapnik_layer_post_read (VikLayer *vl, VikViewport *vvp, gboolean fro
 {
        VikMapnikLayer *vml = VIK_MAPNIK_LAYER(vl);
 
-       if ( mapnik_interface_load_map_file ( vml->filename_xml, vml->tile_size_x, vml->tile_size_x ) ) {
+       if ( mapnik_interface_load_map_file ( vml->mi, vml->filename_xml, vml->tile_size_x, vml->tile_size_x ) ) {
                if ( !from_file )
                        a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vvp),
                                                 _("Mapnik error loading configuration file: %s"),
@@ -458,6 +460,7 @@ static void mapnik_layer_draw ( VikMapnikLayer *vml, VikViewport *vvp )
  */
 static void mapnik_layer_free ( VikMapnikLayer *vml )
 {
+       mapnik_interface_free ( vml->mi );
        if ( vml->filename_xml )
                g_free ( vml->filename_xml );
 }