Previously, drawing of map scale was hard-wired to leo.c.
This patch adds special symbolizers, which are applied only
on explicit request. The first such symbolizer draws the map
scale, controlled by a set of style properties.
PROGS+=$(o)/leo
CFLAGS+=$(LIBUCW_CFLAGS)
-LEO_MODULES=leo xml osm svg svg-icon css-parse css-lex style css dict sym sym-point sym-line sym-text map shp fixed
+LEO_MODULES=leo xml osm svg svg-icon css-parse css-lex style css dict sym sym-point sym-line sym-scale sym-text map shp fixed
LEO_OBJECTS=$(addprefix $(o)/, $(addsuffix .o, $(LEO_MODULES)))
$(o)/leo: $(LEO_OBJECTS)
brand
highway
leisure
+leo:special
name
name:cz
operator
text-offset-y
text-opacity
text-position
+tick-length
z-index
# The following properties come in couples, which must not be split
outer
right
round
+scale
square
top
true
}
};
-// FIXME: Make generic
-static void draw_scale(struct svg *svg)
-{
- double dist = 1000;
- double width = dist * map_scale;
- double x = page_width - 10 - width;
- double y = 50;
-
- svg_push_element(svg, "g");
- svg_set_attr(svg, "id", "scale");
- svg_set_attr_format(svg, "transform", "translate(%s,%s)", svg_format_dimen(svg, x), svg_format_dimen(svg, y));
-
- for (int outline=1; outline>=0; outline--)
- {
- svg_push_element(svg, "g");
- svg_set_attr(svg, "stroke-linecap", "square");
- if (outline)
- {
- svg_set_attr_dimen(svg, "stroke-width", 1.5);
- svg_set_attr_color(svg, "stroke", 0xffffff);
- }
- else
- {
- svg_set_attr_dimen(svg, "stroke-width", 0.5);
- svg_set_attr_color(svg, "stroke", 0);
- }
-
- svg_push_element(svg, "line");
- svg_set_attr_dimen(svg, "x1", 0);
- svg_set_attr_dimen(svg, "y1", 0);
- svg_set_attr_dimen(svg, "x2", width);
- svg_set_attr_dimen(svg, "y2", 0);
- svg_pop(svg);
-
- for (int i=0; i<=10; i++)
- {
- double tick;
- switch (i)
- {
- case 0:
- case 10:
- tick = 3;
- break;
- case 5:
- tick = 2;
- break;
- default:
- tick = 1;
- }
- svg_push_element(svg, "line");
- svg_set_attr_dimen(svg, "x1", width * i/10);
- svg_set_attr_dimen(svg, "y1", 0);
- svg_set_attr_dimen(svg, "x2", width * i/10);
- svg_set_attr_dimen(svg, "y1", -tick);
- svg_pop(svg);
- }
-
- svg_pop(svg);
- }
-
- scale_text(svg, 0, 5, osm_val_encode("0"));
- scale_text(svg, width, 5, osm_val_encode("1 km"));
- svg_pop(svg);
-}
-
int main(int argc UNUSED, char **argv)
{
cf_def_file = "map.cf";
sym_draw_all(svg);
- draw_scale(svg);
-
if (map_clip)
svg_pop(svg);
# Fixed objects may be placed at specific positions on the paper
# with specific tags. Remember to enable the "fixed" data source.
Object {
+ # Image with a logo
X 374
Y 25
Tag style:icon-image '"icons/logo.svg"'
Tag style:icon-width 36
Tag style:z-index 99
}
+ Object {
+ # Map scale
+ X 325
+ Y 50
+ Tag leo:special scale
+ }
}
Debug {
return r->layers[layer];
}
+void style_enable_default_layer(struct style_results *r)
+{
+ style_get_info(r, STYLE_LAYER_DEFAULT);
+}
+
void style_set_by_layer(struct style_results *r, layer_t layer, struct style_prop *p)
{
if (layer == STYLE_LAYER_ALL)
void style_cleanup(struct style_results *r);
void style_begin(struct style_results *r, struct osm_object *o);
void style_end(struct style_results *r);
+void style_enable_default_layer(struct style_results *r);
void style_set_by_layer(struct style_results *r, layer_t layer, struct style_prop *p);
--- /dev/null
+/*
+ * Hic Est Leo -- Map Scale Symbolizer
+ *
+ * (c) 2014--2015 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+
+#include "leo.h"
+#include "osm.h"
+#include "map.h"
+#include "sym.h"
+
+static void sym_scale_draw(struct symbol *sym, struct svg *svg)
+{
+ struct sym_scale *sc = (struct sym_scale *) sym;
+ double dist = 1000;
+ double width = dist * map_scale;
+ struct osm_node *n = (struct osm_node *) sym->o;
+
+ svg_push_element(svg, "g");
+ // svg_set_attr(svg, "id", "scale");
+ svg_set_attr_format(svg, "transform", "translate(%s,%s)", svg_format_dimen(svg, n->x), svg_format_dimen(svg, n->y));
+
+ for (int outline=1; outline>=0; outline--)
+ {
+ svg_push_element(svg, "g");
+ svg_set_attr(svg, "stroke-linecap", "square");
+ if (outline)
+ {
+ svg_set_attr_dimen(svg, "stroke-width", sc->width + sc->casing_width);
+ svg_set_attr_color(svg, "stroke", sc->casing_color);
+ }
+ else
+ {
+ svg_set_attr_dimen(svg, "stroke-width", sc->width);
+ svg_set_attr_color(svg, "stroke", sc->color);
+ }
+
+ svg_push_element(svg, "line");
+ svg_set_attr_dimen(svg, "x1", 0);
+ svg_set_attr_dimen(svg, "y1", 0);
+ svg_set_attr_dimen(svg, "x2", width);
+ svg_set_attr_dimen(svg, "y2", 0);
+ svg_pop(svg);
+
+ for (int i=0; i<=10; i++)
+ {
+ double tick;
+ switch (i)
+ {
+ case 0:
+ case 10:
+ tick = 3;
+ break;
+ case 5:
+ tick = 2;
+ break;
+ default:
+ tick = 1;
+ }
+ tick *= sc->tick_length;
+ svg_push_element(svg, "line");
+ svg_set_attr_dimen(svg, "x1", width * i/10);
+ svg_set_attr_dimen(svg, "y1", 0);
+ svg_set_attr_dimen(svg, "x2", width * i/10);
+ svg_set_attr_dimen(svg, "y1", -tick);
+ svg_pop(svg);
+ }
+
+ svg_pop(svg);
+ }
+
+ scale_text(svg, 0, 5, osm_val_encode("0"));
+ scale_text(svg, width, 5, osm_val_encode("1 km"));
+ svg_pop(svg);
+}
+
+static void sym_scale_gen(struct osm_object *o, struct style_info *si, struct svg *svg UNUSED)
+{
+ if (o->type != OSM_TYPE_NODE)
+ die("Map scale must be a node");
+
+ struct sym_scale *sc = sym_scale_new(o);
+
+ sc->width = 0.5;
+ style_get_number(si, PROP_WIDTH, &sc->width);
+
+ sc->color = 0;
+ style_get_color(si, PROP_COLOR, &sc->color);
+
+ sc->casing_width = 0.5;
+ style_get_number(si, PROP_CASING_WIDTH, &sc->casing_width);
+
+ sc->casing_color = 0xffffff;
+ style_get_color(si, PROP_CASING_COLOR, &sc->casing_color);
+
+ sc->tick_length = 1;
+ style_get_number(si, PROP_TICK_LENGTH, &sc->tick_length);
+
+ sym_plan(&sc->s, sym_zindex(o, si, 4));
+}
+
+struct symbolizer symbolizer_scale = {
+ .name = "scale",
+ .draw = sym_scale_draw,
+ .gen = sym_scale_gen,
+ .special = VALUE_SCALE,
+};
+
+struct sym_scale *sym_scale_new(struct osm_object *o)
+{
+ return sym_new(SYMBOLIZER_SCALE, o, sizeof(struct sym_scale));
+}
/*
* Hic Est Leo -- Symbols
*
- * (c) 2014 Martin Mares <mj@ucw.cz>
+ * (c) 2014--2015 Martin Mares <mj@ucw.cz>
*/
#include <ucw/lib.h>
#undef CLAMP // FIXME: Fix in libucw?
#define CLAMP(x,min,max) ({ typeof(x) _t=x; (_t < min) ? min : (_t > max) ? max : _t; }) /** Clip a number @x to interval [@min,@max] **/
-static struct symbolizer *symbolizers[] = {
+static struct symbolizer *symbolizers[SYMBOLIZER_MAX] = {
[SYMBOLIZER_INVALID] = NULL,
[SYMBOLIZER_POINT] = &symbolizer_point,
[SYMBOLIZER_ICON] = &symbolizer_icon,
[SYMBOLIZER_AREA] = &symbolizer_area,
[SYMBOLIZER_TEXT] = &symbolizer_text,
[SYMBOLIZER_LINEIMG] = &symbolizer_lineimg,
+ [SYMBOLIZER_SCALE] = &symbolizer_scale,
};
struct mempool *sym_mp;
void sym_from_style(struct osm_object *o, struct style_results *sr, struct svg *svg)
{
+ osm_val_t special = osm_obj_find_tag(o, KEY_LEO_SPECIAL);
+ if (special)
+ style_enable_default_layer(sr);
+
for (uns i=0; i < sr->num_active_layers; i++)
{
for (uns j = SYMBOLIZER_INVALID + 1; j < SYMBOLIZER_MAX; j++)
- if (symbolizers[j]->gen)
- (symbolizers[j]->gen)(o, sr->layers[sr->active_layers[i]], svg);
+ {
+ struct symbolizer *sy = symbolizers[j];
+ // Either a generic symbolizer with a generic object,
+ // or a special symbolizer with its special object.
+ if (sy->special == special && sy->gen)
+ (sy->gen)(o, sr->layers[sr->active_layers[i]], svg);
+ }
}
}
/*
* Hic Est Leo -- Symbolizers
*
- * (c) 2014 Martin Mares <mj@ucw.cz>
+ * (c) 2014--2015 Martin Mares <mj@ucw.cz>
*/
#ifndef _LEO_SYM_H
SYMBOLIZER_AREA,
SYMBOLIZER_TEXT,
SYMBOLIZER_LINEIMG,
+ SYMBOLIZER_SCALE,
SYMBOLIZER_MAX,
};
void (*draw)(struct symbol *sym, struct svg *svg);
void (*gen)(struct osm_object *o, struct style_info *si, struct svg *svg);
void (*init)(void);
+ osm_val_t special; // Generated automatically only upon request
};
extern struct mempool *sym_mp;
void scale_text(struct svg *svg, double x, double y, osm_val_t text);
+/* sym-scale.c */
+
+struct sym_scale {
+ struct symbol s;
+ double width;
+ color_t color;
+ double casing_width;
+ color_t casing_color;
+ double tick_length;
+};
+
+extern struct symbolizer symbolizer_scale;
+struct sym_scale *sym_scale_new(struct osm_object *o);
+
#endif