summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2015-07-08 22:05:34 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2016-02-02 10:55:16 +0000
commit761a9a99b72cfd2aa9e4d159c1bbd859cf70bd3f (patch)
treee34db76f0bbb2e4f975c91eb2ed114ff856acc84
parent842120bede2ef48f04f8bb3a1c8967d0d7457cac (diff)
downloadlibcss-761a9a99b72cfd2aa9e4d159c1bbd859cf70bd3f.tar.gz
libcss-761a9a99b72cfd2aa9e4d159c1bbd859cf70bd3f.tar.bz2
Change how presentational hints are handled.
Previously, we performed normal selection from CSS sources, and then iterated over all the properties in the populated computed style. If the properties were unset or their values were not from either a UA stylesheet or user stylesheet with !important set, then we asked the client program (e.g. NetSurf) if there were any presentational hints for that node, for each such property. In the worst case this triggered N_PROPERTIES * N_NODES calls back to the client program, even for properties that can't be set via HTML attributes. The new API asks the client to supply a list of all the presentational hints that apply to the given node. For most nodes on modern documents, this is 0. Any presentational hints are applied before selection from CSS sources.
-rw-r--r--include/libcss/hint.h3
-rw-r--r--include/libcss/select.h4
-rw-r--r--src/select/select.c69
-rw-r--r--test/select-common.c13
4 files changed, 47 insertions, 42 deletions
diff --git a/include/libcss/hint.h b/include/libcss/hint.h
index c3e928d..629d2f6 100644
--- a/include/libcss/hint.h
+++ b/include/libcss/hint.h
@@ -49,7 +49,8 @@ typedef struct css_hint {
lwc_string **strings;
} data;
- uint8_t status;
+ uint32_t prop; /**< Property index */
+ uint8_t status; /**< Property value */
} css_hint;
#ifdef __cplusplus
diff --git a/include/libcss/select.h b/include/libcss/select.h
index d504e81..bd2fed2 100644
--- a/include/libcss/select.h
+++ b/include/libcss/select.h
@@ -117,8 +117,8 @@ typedef struct css_select_handler {
css_error (*node_is_lang)(void *pw, void *node,
lwc_string *lang, bool *match);
- css_error (*node_presentational_hint)(void *pw, void *node,
- uint32_t property, css_hint *hint);
+ css_error (*node_presentational_hint)(void *pw, void *node,
+ uint32_t *nhints, css_hint **hints);
css_error (*ua_default_for_property)(void *pw, uint32_t property,
css_hint *hint);
diff --git a/src/select/select.c b/src/select/select.c
index 17dff31..2c14eb6 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -110,7 +110,7 @@ typedef struct css_select_rule_source {
} css_select_rule_source;
-static css_error set_hint(css_select_state *state, uint32_t prop);
+static css_error set_hint(css_select_state *state, css_hint *hint);
static css_error set_initial(css_select_state *state,
uint32_t prop, css_pseudo_element pseudo,
void *parent);
@@ -433,10 +433,11 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
css_select_handler *handler, void *pw,
css_select_results **result)
{
- uint32_t i, j;
+ uint32_t i, j, nhints;
css_error error;
css_select_state state;
void *parent = NULL;
+ css_hint *hints = NULL;
css_bloom *bloom = NULL;
css_bloom *parent_bloom = NULL;
@@ -536,6 +537,29 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
if (error != CSS_OK)
goto cleanup;
+ /* Apply presentational hints */
+ error = handler->node_presentational_hint(pw, node, &nhints, &hints);
+ if (error != CSS_OK)
+ goto cleanup;
+ if (nhints > 0) {
+ /* Ensure that the appropriate computed style exists */
+ struct css_computed_style *computed_style =
+ state.results->styles[CSS_PSEUDO_ELEMENT_NONE];
+ if (computed_style == NULL) {
+ error = css_computed_style_create(&computed_style);
+ if (error != CSS_OK)
+ return error;
+ }
+ state.results->styles[CSS_PSEUDO_ELEMENT_NONE] = computed_style;
+ state.computed = computed_style;
+
+ for (i = 0; i < nhints; i++) {
+ error = set_hint(&state, &hints[i]);
+ if (error != CSS_OK)
+ goto cleanup;
+ }
+ }
+
/* Iterate through the top-level stylesheets, selecting styles
* from those which apply to our current media requirements and
* are not disabled */
@@ -577,8 +601,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
}
}
- /* Take account of presentational hints and fix up any remaining
- * unset properties. */
+ /* Fix up any remaining unset properties. */
/* Base element */
state.current_pseudo = CSS_PSEUDO_ELEMENT_NONE;
@@ -587,17 +610,6 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
const prop_state *prop =
&state.props[i][CSS_PSEUDO_ELEMENT_NONE];
- /* Apply presentational hints if the property is unset or
- * the existing property value did not come from an author
- * stylesheet or a user sheet using !important. */
- if (prop->set == false ||
- (prop->origin != CSS_ORIGIN_AUTHOR &&
- prop->important == false)) {
- error = set_hint(&state, i);
- if (error != CSS_OK)
- goto cleanup;
- }
-
/* If the property is still unset or it's set to inherit
* and we're the root element, then set it to its initial
* value. */
@@ -1118,32 +1130,23 @@ void destroy_strings(css_select_ctx *ctx)
lwc_string_unref(ctx->after);
}
-css_error set_hint(css_select_state *state, uint32_t prop)
+css_error set_hint(css_select_state *state, css_hint *hint)
{
- css_hint hint;
+ uint32_t prop = hint->prop;
+ prop_state *existing = &state->props[prop][CSS_PSEUDO_ELEMENT_NONE];
css_error error;
- /* Initialise hint */
- memset(&hint, 0, sizeof(css_hint));
-
- /* Retrieve this property's hint from the client */
- error = state->handler->node_presentational_hint(state->pw,
- state->node, prop, &hint);
- if (error != CSS_OK)
- return (error == CSS_PROPERTY_NOT_SET) ? CSS_OK : error;
-
/* Hint defined -- set it in the result */
- error = prop_dispatch[prop].set_from_hint(&hint, state->computed);
+ error = prop_dispatch[prop].set_from_hint(hint, state->computed);
if (error != CSS_OK)
return error;
/* Keep selection state in sync with reality */
- state->props[prop][CSS_PSEUDO_ELEMENT_NONE].set = 1;
- state->props[prop][CSS_PSEUDO_ELEMENT_NONE].specificity = 0;
- state->props[prop][CSS_PSEUDO_ELEMENT_NONE].origin = CSS_ORIGIN_AUTHOR;
- state->props[prop][CSS_PSEUDO_ELEMENT_NONE].important = 0;
- state->props[prop][CSS_PSEUDO_ELEMENT_NONE].inherit =
- (hint.status == 0);
+ existing->set = 1;
+ existing->specificity = 0;
+ existing->origin = CSS_ORIGIN_AUTHOR;
+ existing->important = 0;
+ existing->inherit = (hint->status == 0);
return CSS_OK;
}
diff --git a/test/select-common.c b/test/select-common.c
index f1762a6..432bd54 100644
--- a/test/select-common.c
+++ b/test/select-common.c
@@ -156,9 +156,9 @@ static css_error node_is_target(void *pw, void *node, bool *match);
static css_error node_is_lang(void *pw, void *node,
lwc_string *lang, bool *match);
static css_error node_presentational_hint(void *pw, void *node,
- uint32_t property, css_hint *hint);
+ uint32_t *nhints, css_hint **hints);
static css_error ua_default_for_property(void *pw, uint32_t property,
- css_hint *hint);
+ css_hint *hints);
static css_error compute_font_size(void *pw, const css_hint *parent,
css_hint *size);
static css_error set_libcss_node_data(void *pw, void *n,
@@ -1566,14 +1566,15 @@ css_error node_is_lang(void *pw, void *n,
}
css_error node_presentational_hint(void *pw, void *node,
- uint32_t property, css_hint *hint)
+ uint32_t *nhints, css_hint **hints)
{
UNUSED(pw);
UNUSED(node);
- UNUSED(property);
- UNUSED(hint);
- return CSS_PROPERTY_NOT_SET;
+ *nhints = 0;
+ *hints = NULL;
+
+ return CSS_OK;
}
css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint)