/*
* Hic Est Leo -- Global Map Operations
*
- * (c) 2014 Martin Mares <mj@ucw.cz>
+ * (c) 2014--2015 Martin Mares <mj@ucw.cz>
*/
-#include <ucw/lib.h>
+#include "leo.h"
+#include "osm.h"
+#include "shp.h"
+#include "map.h"
+#include "css.h"
+#include "sym.h"
+#include "fixed.h"
+
#include <ucw/conf.h>
#include <ucw/gary.h>
#include <ucw/mempool.h>
#include <stdio.h>
#include <math.h>
-#include "leo.h"
-#include "osm.h"
-#include "map.h"
-#include "css.h"
-#include "sym.h"
-
double map_min_x, map_min_y;
double map_max_x, map_max_y;
double page_width, page_height;
static const char * const map_formats[] = {
"invalid",
"osmxml",
+ "fixed",
+ "shape",
};
static struct cf_section map_source_cf = {
CF_STRING("File", P(file)),
CF_LOOKUP("Format", P(format), map_formats),
CF_LIST("StyleSheet", P(styles), &map_style_cf),
+ CF_INT("InlineStyles", P(inline_styles)),
CF_END
}
#undef P
double rmin_y = INFINITY, rmax_y = -INFINITY;
CLIST_FOR_EACH(struct data_source *, ds, map_sources)
{
+ if (ds->format == DATA_SOURCE_FIXED)
+ continue;
CLIST_FOR_EACH(struct osm_node *, n, ds->osm->obj_list[OSM_TYPE_NODE])
{
pmin_x = MIN(pmin_x, n->x);
{
ds->osm = osm_init();
+ bool need_mp = 0;
+ bool need_proj = 0;
+
switch (ds->format)
{
case DATA_SOURCE_OSMXML:
msg(L_INFO, "Parsing %s as OSM XML", ds->file);
+ if (!ds->file)
+ die("OSM XML data sources must have a file name");
osm_xml_parse(ds->file);
- if (debug_dump_source)
- {
- puts("=== Source data ===");
- osm_dump();
- }
- osm_make_multipolygons();
+ need_mp = 1;
+ need_proj = 1;
+ break;
+ case DATA_SOURCE_FIXED:
+ msg(L_INFO, "Adding fixed objects");
+ if (!ds->file)
+ ds->file = "fixed";
+ fixed_add();
+ break;
+ case DATA_SOURCE_SHAPE:
+ msg(L_INFO, "Parsing %s as shape file", ds->file);
+ if (!ds->file)
+ die("Shape data sources must have a file name");
+ shp_parse(ds->file);
+ need_proj = 1;
break;
default:
die("Invalid data source format");
}
- msg(L_INFO, "Projecting");
- osm_project(map_projection);
- if (debug_dump_after_proj)
+ osm_stats();
+ if (debug_dump_source)
{
- puts("=== Map after projection ===");
+ puts("=== Source data ===");
osm_dump();
}
+ if (need_mp)
+ osm_make_multipolygons();
+
+ if (need_proj)
+ {
+ msg(L_INFO, "Projecting");
+ osm_project(map_projection);
+ if (debug_dump_after_proj)
+ {
+ puts("=== Map after projection ===");
+ osm_dump();
+ }
+ }
}
void map_load_sources(void)
map_load_source(ds);
}
+static void map_apply_inline_styles(struct osm_object *o, struct style_results *r)
+{
+ char *name = NULL;
+
+ CLIST_FOR_EACH(struct osm_tag *, t, o->tags)
+ {
+ const char *key = osm_key_decode(t->key);
+ if (!strncmp(key, "style:", 6))
+ {
+ key += 6;
+ layer_t layer = STYLE_LAYER_DEFAULT;
+ char *sep = strstr(key, "::");
+ if (sep)
+ {
+ if (sep[2])
+ {
+ // XXX: Only layers defined in the main stylesheet can be modified
+ layer = style_layer_encode_if_exists(sep+2);
+ if (!layer)
+ goto skip;
+ }
+ int keylen = sep - key;
+ char *t = mp_alloc(r->pool, keylen+1);
+ memcpy(t, key, keylen);
+ t[keylen] = 0;
+ key = t;
+ }
+
+ if (!name)
+ name = mp_printf(r->pool, "inline style of object #%ju", (uintmax_t) o->id);
+ struct style_prop *p= css_parse_prop(r->pool, name, key, osm_val_decode(t->val));
+ style_set_by_layer(r, layer, p);
+skip: ;
+ }
+ }
+}
+
void map_apply_styles(struct svg *svg)
{
struct style_results r;
style_begin(&r, o);
CLIST_FOR_EACH(struct data_source_style *, ss, ds->styles)
css_apply(ss->css, &r);
+ if (ds->inline_styles)
+ map_apply_inline_styles(o, &r);
if (debug_dump_styling)
style_dump(&r);
sym_from_style(o, &r, svg);
}
}
- // FIXME: Ought to destroy the style_results
+ style_cleanup(&r);
}