2 * Hic Est Leo -- MapCSS Stylesheets
4 * (c) 2014 Martin Mares <mj@ucw.cz>
11 #include <ucw/mempool.h>
15 void css_dump(struct css_sheet *ss)
17 printf("Style sheet <%s>:\n", ss->filename);
18 CLIST_FOR_EACH(struct css_rule *, r, ss->rules)
22 void css_dump_rule(struct css_rule *r)
25 CLIST_FOR_EACH(struct css_selector *, s, r->selectors)
27 CLIST_FOR_EACH(struct css_action *, a, r->actions)
31 void css_dump_selector(struct css_selector *s)
33 printf("\tSelector:\n");
34 CLIST_FOR_EACH(struct css_path *, p, s->path)
36 printf("\t\tMatch type=%u layer=%u role=%u mod=%u\n", p->type, p->layer, p->role, p->modifiers);
37 CLIST_FOR_EACH(struct css_condition *, c, p->conditions)
39 printf("\t\t\tCondition %u key=%s val=%s\n", c->op, osm_key_decode(c->key), osm_val_decode(c->val));
44 void css_dump_action(struct css_action *a)
47 style_dump_prop(&a->prop);
50 static bool css_match_condition(struct css_condition *c, struct osm_object *o)
52 osm_val_t val = osm_obj_find_tag(o, c->key);
57 return (val == c->val); // FIXME: Case sensitivity?
59 return (val != c->val);
74 case COND_OP_IS_UNSET:
77 return (val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
78 case COND_OP_IS_FALSE:
79 return !(val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
85 static bool css_match_path_component(struct css_path *p, struct osm_object *o)
93 case CSS_TYPE_RELATION:
94 if (o->type != p->type)
98 if (o->type == OSM_TYPE_WAY && osm_way_cyclic_p((struct osm_way *) o))
100 if (o->type == OSM_TYPE_MULTIPOLYGON)
107 if (p->modifiers & PATH_MOD_NEVER)
110 CLIST_FOR_EACH(struct css_condition *, c, p->conditions)
111 if (!css_match_condition(c, o))
117 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o);
119 static bool css_match_path_subtree(struct css_selector *s, struct css_path *p, struct osm_object *o)
121 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
122 if (css_match_path(s, p, ref->o))
125 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
126 if (css_match_path_subtree(s, p, ref->o))
132 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o)
134 if (!css_match_path_component(p, o))
137 p = clist_prev(&s->path, &p->n);
141 return css_match_path_subtree(s, p, o);
144 static bool css_match_selector(struct css_selector *s, struct style_results *r)
146 struct css_path *p = clist_tail(&s->path);
148 return css_match_path(s, p, r->obj);
151 static void css_apply_action(struct css_action *sa, struct style_results *r, layer_t layer)
153 style_set_by_layer(r, layer, &sa->prop);
156 void css_apply(struct css_sheet *ss, struct style_results *r)
158 CLIST_FOR_EACH(struct css_rule *, sr, ss->rules)
160 layer_t last_layer = ~0U;
161 CLIST_FOR_EACH(struct css_selector *, sel, sr->selectors)
163 if (css_match_selector(sel, r))
165 // XXX: Rules with selectors in multiple layers could be further optimized
166 struct css_path *cp = clist_tail(&sel->path);
167 layer_t layer = cp ? cp->layer : STYLE_LAYER_DEFAULT;
168 if (layer != last_layer)
171 CLIST_FOR_EACH(struct css_action *, sa, sr->actions)
172 css_apply_action(sa, r, layer);