From 09bba6cc53772fe4b661f44fc5113b08296a2844 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 7 Jun 2015 18:34:54 +0200 Subject: [PATCH] Parametrized drawing of map scale 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. --- Makefile | 2 +- dict-keys.t | 1 + dict-props.t | 1 + dict-values.t | 1 + leo.c | 67 ----------------------------- map.cf | 7 ++++ style.c | 5 +++ style.h | 1 + sym-scale.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++ sym.c | 18 ++++++-- sym.h | 18 +++++++- 11 files changed, 162 insertions(+), 73 deletions(-) create mode 100644 sym-scale.c diff --git a/Makefile b/Makefile index e489923..b1c6eee 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include $(BUILDSYS)/Maketop 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) diff --git a/dict-keys.t b/dict-keys.t index 8cef811..a280fdf 100644 --- a/dict-keys.t +++ b/dict-keys.t @@ -5,6 +5,7 @@ addr:housenumber brand highway leisure +leo:special name name:cz operator diff --git a/dict-props.t b/dict-props.t index a164805..6ea8e57 100644 --- a/dict-props.t +++ b/dict-props.t @@ -47,6 +47,7 @@ text-offset-x text-offset-y text-opacity text-position +tick-length z-index # The following properties come in couples, which must not be split diff --git a/dict-values.t b/dict-values.t index 1d30763..8f2f346 100644 --- a/dict-values.t +++ b/dict-values.t @@ -24,6 +24,7 @@ normal outer right round +scale square top true diff --git a/leo.c b/leo.c index c884ae7..f8859e6 100644 --- a/leo.c +++ b/leo.c @@ -45,71 +45,6 @@ static const struct opt_section options = { } }; -// 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"; @@ -162,8 +97,6 @@ int main(int argc UNUSED, char **argv) sym_draw_all(svg); - draw_scale(svg); - if (map_clip) svg_pop(svg); diff --git a/map.cf b/map.cf index f1a33d3..1ea0845 100644 --- a/map.cf +++ b/map.cf @@ -57,12 +57,19 @@ FixedObjects { # 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 { diff --git a/style.c b/style.c index b2a342a..d8fd4c5 100644 --- a/style.c +++ b/style.c @@ -125,6 +125,11 @@ static struct style_info *style_get_info(struct style_results *r, layer_t layer) 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) diff --git a/style.h b/style.h index 8abeb84..eded29a 100644 --- a/style.h +++ b/style.h @@ -68,6 +68,7 @@ void style_init(struct style_results *r); 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); diff --git a/sym-scale.c b/sym-scale.c new file mode 100644 index 0000000..64b3233 --- /dev/null +++ b/sym-scale.c @@ -0,0 +1,114 @@ +/* + * Hic Est Leo -- Map Scale Symbolizer + * + * (c) 2014--2015 Martin Mares + */ + +#include + +#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)); +} diff --git a/sym.c b/sym.c index 00d8941..6a14364 100644 --- a/sym.c +++ b/sym.c @@ -1,7 +1,7 @@ /* * Hic Est Leo -- Symbols * - * (c) 2014 Martin Mares + * (c) 2014--2015 Martin Mares */ #include @@ -19,7 +19,7 @@ #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, @@ -27,6 +27,7 @@ static struct symbolizer *symbolizers[] = { [SYMBOLIZER_AREA] = &symbolizer_area, [SYMBOLIZER_TEXT] = &symbolizer_text, [SYMBOLIZER_LINEIMG] = &symbolizer_lineimg, + [SYMBOLIZER_SCALE] = &symbolizer_scale, }; struct mempool *sym_mp; @@ -118,11 +119,20 @@ z_index_t sym_zindex(struct osm_object *o, struct style_info *si, double default 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); + } } } diff --git a/sym.h b/sym.h index e53409e..1a45b7b 100644 --- a/sym.h +++ b/sym.h @@ -1,7 +1,7 @@ /* * Hic Est Leo -- Symbolizers * - * (c) 2014 Martin Mares + * (c) 2014--2015 Martin Mares */ #ifndef _LEO_SYM_H @@ -19,6 +19,7 @@ enum symbolizer_type { SYMBOLIZER_AREA, SYMBOLIZER_TEXT, SYMBOLIZER_LINEIMG, + SYMBOLIZER_SCALE, SYMBOLIZER_MAX, }; @@ -33,6 +34,7 @@ struct symbolizer { 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; @@ -148,4 +150,18 @@ struct sym_text *sym_text_new(struct osm_object *o); 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 -- 2.39.2