summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/select/select.c59
-rw-r--r--src/select/select.h28
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;
};
/**