From ce28a1a8cb638ec2563f375277ee4950f5eb4bde Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 23 Oct 2016 15:57:43 +0100 Subject: Enable sharing where pseudo common pseudo classes are the same. --- src/select/select.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/select/select.h | 28 ++++++++++++++++++------- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index 4b9497c..1719b7f 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -30,6 +30,7 @@ /* Define this to enable verbose messages when attempting to share styles */ #undef DEBUG_STYLE_SHARING +#define DEBUG_STYLE_SHARING /** * Container for stylesheet selection info @@ -761,6 +762,19 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( return CSS_OK; } + /* If the node and candidate node had different pseudo classes, we + * can't share. */ + if ((node_data->flags & CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK) != + (state->node_data->flags & + CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK)) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: different pseudo classes\n", + lwc_string_data(state->element.name)); +#endif + return CSS_OK; + + } + /* If the node was affected by attribute or pseudo class rules, * it's not a candidate for sharing */ if (node_data->flags & ( @@ -1021,6 +1035,7 @@ static css_error css_select__initialise_selection_state( void *pw) { css_error error; + bool match; /* Set up the selection state */ memset(state, 0, sizeof(*state)); @@ -1067,6 +1082,42 @@ static css_error css_select__initialise_selection_state( goto failed; } + /* Node pseudo classes */ + error = handler->node_is_link(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_LINK; + } + + error = handler->node_is_visited(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED; + } + + error = handler->node_is_hover(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER; + } + + error = handler->node_is_active(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE; + } + + error = handler->node_is_focus(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS; + } + return CSS_OK; failed: @@ -2534,6 +2585,7 @@ css_error match_detail(css_select_ctx *ctx, void *node, { bool is_root = false; css_error error = CSS_OK; + css_node_flags flags = CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; switch (detail->type) { case CSS_SELECTOR_ELEMENT: @@ -2674,18 +2726,23 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else if (detail->qname.name == ctx->link) { error = state->handler->node_is_link(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->visited) { error = state->handler->node_is_visited(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->hover) { error = state->handler->node_is_hover(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->active) { error = state->handler->node_is_active(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->focus) { error = state->handler->node_is_focus(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->target) { error = state->handler->node_is_target(state->pw, node, match); @@ -2704,7 +2761,7 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else { *match = false; } - add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS); + add_node_flags(node, state, flags); break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; diff --git a/src/select/select.h b/src/select/select.h index 96f4546..1d9a813 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -31,16 +31,30 @@ typedef struct prop_state { inherit : 1; /* Property is set to inherit */ } prop_state; + +typedef enum css_node_flags { + CSS_NODE_FLAGS_NONE = 0, + CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE = (1 << 1), + CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS = (1 << 2), + CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER = (1 << 3), + CSS_NODE_FLAGS_PSEUDO_CLASS_LINK = (1 << 4), + CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED = (1 << 5), + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 6), + CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 7), + CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 8), + CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK = + (CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE | + CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS | + CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER | + CSS_NODE_FLAGS_PSEUDO_CLASS_LINK | + CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED), +} css_node_flags; + struct css_node_data { css_select_results partial; css_bloom *bloom; - enum { - CSS_NODE_FLAGS_NONE = 0, - CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), - CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 1), - CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 2), - CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 3), - } flags; + css_node_flags flags; }; /** -- cgit v1.2.3