]> mj.ucw.cz Git - leo.git/blob - sym.c
Průvodce: Styling
[leo.git] / sym.c
1 /*
2  *      Hic Est Leo -- Symbols
3  *
4  *      (c) 2014 Martin Mares <mj@ucw.cz>
5  */
6
7 #include "leo.h"
8
9 #include <ucw/gary.h>
10 #include <ucw/mempool.h>
11 #include <ucw/stkstring.h>
12
13 #include <stdio.h>
14
15 #include "osm.h"
16 #include "style.h"
17 #include "sym.h"
18
19 #undef CLAMP            // FIXME: Fix in libucw?
20 #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
22 static struct symbolizer symbolizer_disabled = {
23   .name = "disabled",
24 };
25
26 static struct symbolizer *symbolizers[] = {
27   [SYMBOLIZER_INVALID] = NULL,
28   [SYMBOLIZER_POINT] = &symbolizer_point,
29   [SYMBOLIZER_ICON] = &symbolizer_icon,
30   [SYMBOLIZER_LINE] = &symbolizer_line,
31   [SYMBOLIZER_AREA] = &symbolizer_area,
32   [SYMBOLIZER_TEXT] = &symbolizer_text,
33   [SYMBOLIZER_LINEIMG] = &symbolizer_lineimg,
34   [SYMBOLIZER_DISABLED] = &symbolizer_disabled,
35 };
36
37 struct mempool *sym_mp;
38
39 struct sym_planned {
40   struct symbol *sym;
41   z_index_t zindex;
42 };
43
44 static struct sym_planned *sym_planned;
45
46 static inline bool sym_before(struct sym_planned *x, struct sym_planned *y)
47 {
48   COMPARE_LT(x->zindex, y->zindex);
49   COMPARE_LT(x->sym->o->type, y->sym->o->type);
50   COMPARE_LT(x->sym->o->id, y->sym->o->id);
51   return 0;
52 }
53
54 #define ASORT_PREFIX(x) sym_##x
55 #define ASORT_KEY_TYPE struct sym_planned
56 #define ASORT_LT(_x,_y) sym_before(&(_x), &(_y))
57 #include <ucw/sorter/array-simple.h>
58
59 void sym_init(void)
60 {
61   sym_mp = mp_new(65536);
62   GARY_INIT(sym_planned, 0);
63
64   for (uns i = SYMBOLIZER_INVALID + 1; i < SYMBOLIZER_MAX; i++)
65     if (symbolizers[i]->init)
66       (*symbolizers[i]->init)();
67 }
68
69 void *sym_new(enum symbolizer_type type, struct osm_object *o, size_t size)
70 {
71   struct symbol *s = mp_alloc_zero(sym_mp, size);
72   s->type = type;
73   s->o = o;
74   return s;
75 }
76
77 void sym_plan(struct symbol *sym, z_index_t zindex)
78 {
79   struct sym_planned *p = GARY_PUSH(sym_planned);
80   p->sym = sym;
81   p->zindex = zindex;
82   if (debug_dump_symbols)
83     printf("--> planning symbol <%s> with z-index %u for %s\n",
84       symbolizers[sym->type]->name, zindex, STK_OSM_NAME(sym->o));
85 }
86
87 z_index_t sym_zindex(struct osm_object *o, struct style_info *si, double default_mzi)
88 {
89   double zi = 0;
90   style_get_number(si, PROP_Z_INDEX, &zi);
91   double zi2 = CLAMP(zi, -100, 100);
92   if (zi2 != zi)
93     osm_obj_warn(o, "z-index clipped from %.6g to %.6g", zi, zi2);
94
95 #if 0
96   // FIXME: object-z-index not used yet
97   double ozi = 0;
98   style_get_number(si, PROP_OBJECT_Z_INDEX, &ozi);
99   double ozi2 = CLAMP(ozi, -100, 100);
100   if (ozi2 != ozi)
101     osm_obj_warn(o, "object-z-index clipped from %.6g to %.6g", ozi, ozi2);
102 #endif
103
104   double mzi = default_mzi;
105   if (mzi == 2)
106     {
107       // FIXME: This is a terrible hack.
108       style_get_number(si, PROP_CASING_MAJOR_Z_INDEX, &mzi);
109     }
110   else if (mzi == 4.9 || mzi == 5)
111     {
112       // FIXME: This is another terrible hack.
113       style_get_number(si, PROP_TEXT_MAJOR_Z_INDEX, &mzi);
114     }
115   else
116     style_get_number(si, PROP_MAJOR_Z_INDEX, &mzi);
117   double mzi2 = CLAMP(mzi, -100, 100);
118   if (mzi2 != mzi)
119     osm_obj_warn(o, "major-z-index clipped from %.6g to %.6g", mzi, mzi2);
120
121   return (z_index_t)(10000 + (z_index_t)(zi2 * 100) + 10000*( 10000 + (z_index_t)(mzi2 * 100) ));
122 }
123
124 void sym_from_style(struct osm_object *o, struct style_results *sr, struct svg *svg)
125 {
126   for (uns i=0; i < sr->num_active_layers; i++)
127     {
128       for (uns j = SYMBOLIZER_INVALID + 1; j < SYMBOLIZER_MAX; j++)
129         if (symbolizers[j]->gen)
130           (symbolizers[j]->gen)(o, sr->layers[sr->active_layers[i]], svg);
131     }
132 }
133
134 static void sym_draw(struct symbol *sym, z_index_t zindex, struct svg *svg)
135 {
136   ASSERT(sym->type && sym->type < SYMBOLIZER_MAX);
137   if (debug_dump_symbols)
138     printf("Drawing symbol <%s> at z-index %u for %s\n", symbolizers[sym->type]->name, zindex, STK_OSM_NAME(sym->o));
139   if (symbolizers[sym->type]->draw)
140     symbolizers[sym->type]->draw(sym, svg);
141 }
142
143 void sym_draw_all(struct svg *svg)
144 {
145   msg(L_INFO, "Sorting %u symbols by depth", (uns) GARY_SIZE(sym_planned));
146   sym_sort(sym_planned, GARY_SIZE(sym_planned));
147
148   msg(L_INFO, "Dumping icon library");
149   svg_icon_dump_library(svg);
150
151   msg(L_INFO, "Drawing symbols");
152   for (uns i = 0; i < GARY_SIZE(sym_planned); i++)
153     sym_draw(sym_planned[i].sym, sym_planned[i].zindex, svg);
154 }
155
156 void sym_for_all_planned(void (*callback)(struct symbol *s, z_index_t zindex))
157 {
158   for (uns i = 0; i < GARY_SIZE(sym_planned); i++)
159     callback(sym_planned[i].sym, sym_planned[i].zindex);
160 }
161
162 bool sym_same_attrs_p(struct symbol *x, struct symbol *y)
163 {
164   if (x->type != y->type)
165     return 0;
166
167   if (!symbolizers[x->type]->same_p)
168     return 0;
169
170   return (*symbolizers[x->type]->same_p)(x, y);
171 }
172
173 void sym_disable(struct symbol *sym)
174 {
175   sym->type = SYMBOLIZER_DISABLED;
176 }
177
178 struct symbol *sym_clone(struct symbol *s)
179 {
180   ASSERT(symbolizers[s->type]->clone);
181   return symbolizers[s->type]->clone(s);
182 }