2 * Hic Est Leo -- MapCSS Stylesheets
4 * (c) 2014 Martin Mares <mj@ucw.cz>
9 #include <ucw/mempool.h>
16 void css_dump(struct css_sheet *ss)
18 printf("Style sheet <%s>:\n", ss->filename);
19 CLIST_FOR_EACH(struct css_rule *, r, ss->rules)
23 void css_dump_rule(struct css_rule *r)
26 CLIST_FOR_EACH(struct css_selector *, s, r->selectors)
28 CLIST_FOR_EACH(struct css_action *, a, r->actions)
32 void css_dump_selector(struct css_selector *s)
34 printf("\tSelector:\n");
35 CLIST_FOR_EACH(struct css_path *, p, s->path)
37 printf("\t\tMatch type=%u layer=%u role=%u mod=%u\n", p->type, p->layer, p->role, p->modifiers);
38 CLIST_FOR_EACH(struct css_condition *, c, p->conditions)
40 printf("\t\t\tCondition %u key=%s val=%s\n", c->op, osm_key_decode(c->key), osm_val_decode(c->val));
45 void css_dump_action(struct css_action *a)
48 style_dump_prop(&a->prop);
51 static bool css_match_condition(struct css_condition *c, struct osm_object *o)
53 osm_val_t val = osm_obj_find_tag(o, c->key);
58 return (val == c->val); // FIXME: Case sensitivity?
60 return (val != c->val);
75 case COND_OP_IS_UNSET:
78 return (val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
79 case COND_OP_IS_FALSE:
80 return !(val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
86 static bool css_match_path_component(struct css_path *p, struct osm_object *o)
94 case CSS_TYPE_RELATION:
95 if (o->type != p->type)
99 if (o->type == OSM_TYPE_WAY && osm_way_cyclic_p((struct osm_way *) o))
101 if (o->type == OSM_TYPE_MULTIPOLYGON)
108 if (p->modifiers & PATH_MOD_NEVER)
111 CLIST_FOR_EACH(struct css_condition *, c, p->conditions)
112 if (!css_match_condition(c, o))
118 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o);
120 static bool css_match_path_subtree(struct css_selector *s, struct css_path *p, struct osm_object *o)
122 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
123 if (css_match_path(s, p, ref->o))
126 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
127 if (css_match_path_subtree(s, p, ref->o))
133 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o)
135 if (!css_match_path_component(p, o))
138 p = clist_prev(&s->path, &p->n);
142 return css_match_path_subtree(s, p, o);
145 static bool css_match_selector(struct css_selector *s, struct style_results *r)
147 struct css_path *p = clist_tail(&s->path);
149 return css_match_path(s, p, r->obj);
152 static void css_apply_action(struct css_action *sa, struct style_results *r, layer_t layer)
154 style_set_by_layer(r, layer, &sa->prop);
157 void css_apply(struct css_sheet *ss, struct style_results *r)
159 CLIST_FOR_EACH(struct css_rule *, sr, ss->rules)
161 layer_t last_layer = ~0U;
162 CLIST_FOR_EACH(struct css_selector *, sel, sr->selectors)
164 if (css_match_selector(sel, r))
166 // XXX: Rules with selectors in multiple layers could be further optimized
167 struct css_path *cp = clist_tail(&sel->path);
168 layer_t layer = cp ? cp->layer : STYLE_LAYER_DEFAULT;
169 if (layer != last_layer)
172 CLIST_FOR_EACH(struct css_action *, sa, sr->actions)
173 css_apply_action(sa, r, layer);