2 * Hic Est Leo -- Symbols
4 * (c) 2014--2015 Martin Mares <mj@ucw.cz>
13 #include <ucw/mempool.h>
14 #include <ucw/stkstring.h>
18 #undef CLAMP // FIXME: Fix in libucw?
19 #define CLAMP(x,min,max) ({ typeof(x) _t=x; (_t < min) ? min : (_t > max) ? max : _t; }) /** Clip a number @x to interval [@min,@max] **/
21 static struct symbolizer *symbolizers[SYMBOLIZER_MAX] = {
22 [SYMBOLIZER_INVALID] = NULL,
23 [SYMBOLIZER_POINT] = &symbolizer_point,
24 [SYMBOLIZER_ICON] = &symbolizer_icon,
25 [SYMBOLIZER_LINE] = &symbolizer_line,
26 [SYMBOLIZER_AREA] = &symbolizer_area,
27 [SYMBOLIZER_TEXT] = &symbolizer_text,
28 [SYMBOLIZER_LINEIMG] = &symbolizer_lineimg,
29 [SYMBOLIZER_SCALE] = &symbolizer_scale,
32 struct mempool *sym_mp;
39 static struct sym_planned *sym_planned;
41 static inline bool sym_before(struct sym_planned *x, struct sym_planned *y)
43 COMPARE_LT(x->zindex, y->zindex);
44 COMPARE_LT(x->sym->o->type, y->sym->o->type);
45 COMPARE_LT(x->sym->o->id, y->sym->o->id);
49 #define ASORT_PREFIX(x) sym_##x
50 #define ASORT_KEY_TYPE struct sym_planned
51 #define ASORT_LT(_x,_y) sym_before(&(_x), &(_y))
52 #include <ucw/sorter/array-simple.h>
56 sym_mp = mp_new(65536);
57 GARY_INIT(sym_planned, 0);
59 for (uns i = SYMBOLIZER_INVALID + 1; i < SYMBOLIZER_MAX; i++)
60 if (symbolizers[i]->init)
61 (*symbolizers[i]->init)();
64 void *sym_new(enum symbolizer_type type, struct osm_object *o, size_t size)
66 struct symbol *s = mp_alloc_zero(sym_mp, size);
72 void sym_plan(struct symbol *sym, z_index_t zindex)
74 struct sym_planned *p = GARY_PUSH(sym_planned);
77 if (debug_dump_symbols)
78 printf("--> planning symbol <%s> with z-index %u for %s\n",
79 symbolizers[sym->type]->name, zindex, STK_OSM_NAME(sym->o));
82 z_index_t sym_zindex(struct osm_object *o, struct style_info *si, double default_mzi)
85 style_get_number(si, PROP_Z_INDEX, &zi);
86 double zi2 = CLAMP(zi, -100, 100);
88 osm_obj_warn(o, "z-index clipped from %.6g to %.6g", zi, zi2);
91 // FIXME: object-z-index not used yet
93 style_get_number(si, PROP_OBJECT_Z_INDEX, &ozi);
94 double ozi2 = CLAMP(ozi, -100, 100);
96 osm_obj_warn(o, "object-z-index clipped from %.6g to %.6g", ozi, ozi2);
99 double mzi = default_mzi;
102 // FIXME: This is a terrible hack.
103 style_get_number(si, PROP_CASING_MAJOR_Z_INDEX, &mzi);
105 else if (mzi == 4.9 || mzi == 5)
107 // FIXME: This is another terrible hack.
108 style_get_number(si, PROP_TEXT_MAJOR_Z_INDEX, &mzi);
111 style_get_number(si, PROP_MAJOR_Z_INDEX, &mzi);
112 double mzi2 = CLAMP(mzi, -100, 100);
114 osm_obj_warn(o, "major-z-index clipped from %.6g to %.6g", mzi, mzi2);
116 return (z_index_t)(10000 + (z_index_t)(zi2 * 100) + 10000*( 10000 + (z_index_t)(mzi2 * 100) ));
119 void sym_from_style(struct osm_object *o, struct style_results *sr, struct svg *svg)
121 osm_val_t special = osm_obj_find_tag(o, KEY_LEO_SPECIAL);
123 style_enable_default_layer(sr);
125 for (uns i=0; i < sr->num_active_layers; i++)
127 for (uns j = SYMBOLIZER_INVALID + 1; j < SYMBOLIZER_MAX; j++)
129 struct symbolizer *sy = symbolizers[j];
130 // Either a generic symbolizer with a generic object,
131 // or a special symbolizer with its special object.
132 if (sy->special == special && sy->gen)
133 (sy->gen)(o, sr->layers[sr->active_layers[i]], svg);
138 static void sym_draw(struct symbol *sym, z_index_t zindex, struct svg *svg)
140 ASSERT(sym->type && sym->type < SYMBOLIZER_MAX);
141 if (debug_dump_symbols)
142 printf("Drawing symbol <%s> at z-index %u for %s\n", symbolizers[sym->type]->name, zindex, STK_OSM_NAME(sym->o));
143 symbolizers[sym->type]->draw(sym, svg);
146 void sym_draw_all(struct svg *svg)
148 msg(L_INFO, "Sorting %u symbols by depth", (uns) GARY_SIZE(sym_planned));
149 sym_sort(sym_planned, GARY_SIZE(sym_planned));
151 msg(L_INFO, "Dumping icon library");
152 svg_icon_dump_library(svg);
154 msg(L_INFO, "Drawing symbols");
155 for (uns i = 0; i < GARY_SIZE(sym_planned); i++)
156 sym_draw(sym_planned[i].sym, sym_planned[i].zindex, svg);