void fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *node) { fz_css_rule *rule; fz_css_selector *sel; fz_css_property *prop, *head, *tail; const char *s; for (rule = css; rule; rule = rule->next) { sel = rule->selector; while (sel) { if (match_selector(sel, node)) { for (prop = rule->declaration; prop; prop = prop->next) add_property(match, prop->name, prop->value, selector_specificity(sel, prop->important)); break; } sel = sel->next; } } s = fz_xml_att(node, "style"); if (s) { fz_try(ctx) { head = tail = prop = fz_parse_css_properties(ctx, s); while (prop) { add_property(match, prop->name, prop->value, INLINE_SPECIFICITY); tail = prop; prop = prop->next; } if (tail) tail->next = css->garbage; css->garbage = head; } fz_catch(ctx) { fz_warn(ctx, "ignoring style attribute"); } } sort_properties(match); /* speed up subsequent value_from_raw_property lookups */ }
void fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *node) { fz_css_rule *rule; fz_css_selector *sel; fz_css_property *prop, *head, *tail; const char *s; for (rule = css; rule; rule = rule->next) { sel = rule->selector; while (sel) { if (match_selector(sel, node)) { for (prop = rule->declaration; prop; prop = prop->next) add_property(match, prop->name, prop->value, selector_specificity(sel)); break; } sel = sel->next; } } s = fz_xml_att(node, "style"); if (s) { head = tail = prop = fz_parse_css_properties(ctx, s); while (prop) { add_property(match, prop->name, prop->value, INLINE_SPECIFICITY); tail = prop; prop = prop->next; } if (tail) tail->next = css->garbage; css->garbage = head; } }
static int match_selector(fz_css_selector *sel, fz_xml *node) { if (!node) return 0; if (sel->combine) { /* descendant */ if (sel->combine == ' ') { fz_xml *parent = fz_xml_up(node); while (parent) { if (match_selector(sel->left, parent)) if (match_selector(sel->right, node)) return 1; parent = fz_xml_up(parent); } return 0; } /* child */ if (sel->combine == '>') { fz_xml *parent = fz_xml_up(node); if (!parent) return 0; if (!match_selector(sel->left, parent)) return 0; if (!match_selector(sel->right, node)) return 0; } /* adjacent */ if (sel->combine == '+') { fz_xml *prev = fz_xml_prev(node); while (prev && !fz_xml_tag(prev)) prev = fz_xml_prev(prev); if (!prev) return 0; if (!fz_xml_tag(prev)) return 0; if (!match_selector(sel->left, prev)) return 0; if (!match_selector(sel->right, node)) return 0; } } if (sel->name) { if (strcmp(sel->name, fz_xml_tag(node))) return 0; } if (sel->cond) { if (!match_condition(sel->cond, node)) return 0; } return 1; }