2 * Hic Est Leo -- MapCSS Stylesheets
4 * (c) 2014--2015 Martin Mares <mj@ucw.cz>
12 #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)
51 style_dump_prop(&a->prop);
60 static bool css_match_condition(struct css_condition *c, struct osm_object *o)
62 osm_val_t val = osm_obj_find_tag(o, c->key);
67 return (val == c->val); // FIXME: Case sensitivity?
69 return (val != c->val);
84 case COND_OP_IS_UNSET:
87 return (val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
88 case COND_OP_IS_FALSE:
89 return !(val == VALUE_1 || val == VALUE_YES || val == VALUE_TRUE);
95 static bool css_match_path_component(struct css_path *p, struct osm_object *o)
103 case CSS_TYPE_RELATION:
104 if (o->type != p->type)
108 if (o->type == OSM_TYPE_WAY && osm_way_cyclic_p((struct osm_way *) o))
110 if (o->type == OSM_TYPE_MULTIPOLYGON)
117 if (p->modifiers & PATH_MOD_NEVER)
120 CLIST_FOR_EACH(struct css_condition *, c, p->conditions)
121 if (!css_match_condition(c, o))
127 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o);
129 static bool css_match_path_subtree(struct css_selector *s, struct css_path *p, struct osm_object *o)
131 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
132 if (css_match_path(s, p, ref->o))
135 CLIST_FOR_EACH(struct osm_ref *, ref, o->backrefs)
136 if (css_match_path_subtree(s, p, ref->o))
142 static bool css_match_path(struct css_selector *s, struct css_path *p, struct osm_object *o)
144 if (!css_match_path_component(p, o))
147 p = clist_prev(&s->path, &p->n);
151 return css_match_path_subtree(s, p, o);
154 static bool css_match_selector(struct css_selector *s, struct style_results *r)
156 struct css_path *p = clist_tail(&s->path);
158 return css_match_path(s, p, r->obj);
161 static void css_apply_action(struct css_action *sa, struct style_results *r, layer_t layer)
166 style_set_by_layer(r, layer, &sa->prop);
168 case CSS_ACTION_EXPR:
169 expr_execute(sa, r, layer);
176 void css_apply(struct css_sheet *ss, struct style_results *r)
178 CLIST_FOR_EACH(struct css_rule *, sr, ss->rules)
180 layer_t last_layer = ~0U;
181 CLIST_FOR_EACH(struct css_selector *, sel, sr->selectors)
183 if (css_match_selector(sel, r))
185 // XXX: Rules with selectors in multiple layers could be further optimized
186 struct css_path *cp = clist_tail(&sel->path);
187 layer_t layer = cp ? cp->layer : STYLE_LAYER_DEFAULT;
188 if (layer != last_layer)
191 CLIST_FOR_EACH(struct css_action *, sa, sr->actions)
192 css_apply_action(sa, r, layer);