From fb095fb2411d3127df035d93b7b33ff6064ad2e9 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 2 Nov 2015 16:10:36 +0000 Subject: Intern partial styles. Note this changes the public API. We can't compose directly over child style now, since it may be interned. --- src/select/computed.c | 30 ++++++++++++----- src/select/computed.h | 17 ++++++++++ src/select/select.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 9 deletions(-) (limited to 'src/select') diff --git a/src/select/computed.c b/src/select/computed.c index 107c884..2d3aea8 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -277,23 +277,34 @@ css_error css_computed_style_initialise(css_computed_style *style, * \param child Child style * \param compute_font_size Function to compute an absolute font size * \param pw Client data for compute_font_size - * \param result Pointer to style to compose into + * \param result Updated to point to new composed style + * Ownership passed to client. * \return CSS_OK on success, appropriate error otherwise. * * \pre \a parent is a fully composed style (thus has no inherited properties) - * - * \note \a child and \a result may point at the same object */ -css_error css_computed_style_compose(const css_computed_style *parent, - css_computed_style *child, +css_error css_computed_style_compose( + const css_computed_style *restrict parent, + const css_computed_style *restrict child, css_error (*compute_font_size)(void *pw, const css_hint *parent, css_hint *size), void *pw, - css_computed_style **result) + css_computed_style **restrict result) { - css_error error = CSS_OK; + css_computed_style *composed; + css_error error; size_t i; + /* TODO: + * Make this function take a composition context, to allow us + * to avoid the churn of unnecesaraly allocating and freeing + * the memory to compose styles into. + */ + error = css_computed_style_create(&composed); + if (error != CSS_OK) { + return error; + } + /* Iterate through the properties */ for (i = 0; i < CSS_N_PROPERTIES; i++) { /* Skip any in extension blocks if the block does not exist */ @@ -316,18 +327,19 @@ css_error css_computed_style_compose(const css_computed_style *parent, } /* Compose the property */ - error = prop_dispatch[i].compose(parent, child, *result); + error = prop_dispatch[i].compose(parent, child, composed); if (error != CSS_OK) break; } /* Finally, compute absolute values for everything */ - error = css__compute_absolute_values(parent, *result, + error = css__compute_absolute_values(parent, composed, compute_font_size, pw); if (error != CSS_OK) { return error; } + *result = composed; return css__arena_intern_style(result); } diff --git a/src/select/computed.h b/src/select/computed.h index f965993..230711d 100644 --- a/src/select/computed.h +++ b/src/select/computed.h @@ -325,6 +325,23 @@ struct css_computed_style { uint32_t bin; }; + +/** + * Take a new reference to a computed style + * + * \param style The style to take a new reference to. + * \return The new computed style reference + */ +static inline css_computed_style * css__computed_style_ref( + css_computed_style *style) +{ + if (style == NULL) + return NULL; + + style->count++; + return style; +} + css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon); css_error css__compute_absolute_values(const css_computed_style *parent, diff --git a/src/select/select.c b/src/select/select.c index 367c26a..a1ec746 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -15,6 +15,7 @@ #include "bytecode/bytecode.h" #include "bytecode/opcodes.h" #include "stylesheet.h" +#include "select/arena.h" #include "select/computed.h" #include "select/dispatch.h" #include "select/hash.h" @@ -74,6 +75,9 @@ struct css_select_ctx { lwc_string *first_letter; lwc_string *before; lwc_string *after; + + /* Interned default style */ + css_computed_style *default_style; }; /** @@ -258,6 +262,9 @@ css_error css_select_ctx_destroy(css_select_ctx *ctx) destroy_strings(ctx); + if (ctx->default_style != NULL) + css_computed_style_destroy(ctx->default_style); + if (ctx->sheets != NULL) free(ctx->sheets); @@ -406,6 +413,78 @@ css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index, return CSS_OK; } + +/** + * Create a default style on the selection context + * + * \param ctx Context to create default style in + * \param handler Dispatch table of handler functions + * \param pw Client-specific private data for handler functions + * \return CSS_OK on success, appropriate error otherwise + */ +static css_error css__select_ctx_create_default_style(css_select_ctx *ctx, + css_select_handler *handler, void *pw) +{ + css_computed_style *style; + css_error error; + + /* Need to construct the default style */ + error = css_computed_style_create(&style); + if (error != CSS_OK) + return error; + + error = css_computed_style_initialise(style, handler, pw); + if (error != CSS_OK) { + css_computed_style_destroy(style); + return error; + } + + /* Neither create nor initialise intern the style, so intern it now */ + error = css__arena_intern_style(&style); + if (error != CSS_OK) + return error; + + /* Store it on the ctx */ + ctx->default_style = style; + + return CSS_OK; +} + + +/** + * Get a default style, e.g. for an implied element's anonamous box + * + * \param ctx Selection context (used to avoid recreating default) + * \param handler Dispatch table of handler functions + * \param pw Client-specific private data for handler functions + * \param style Pointer to location to receive default style + * \return CSS_OK on success, appropriate error otherwise. + */ +css_error css_select_default_style(css_select_ctx *ctx, + css_select_handler *handler, void *pw, + css_computed_style **style) +{ + css_error error; + + if (ctx == NULL || style == NULL || handler == NULL || + handler->handler_version != + CSS_SELECT_HANDLER_VERSION_1) + return CSS_BADPARM; + + /* Ensure the ctx has a default style */ + if (ctx->default_style == NULL) { + error = css__select_ctx_create_default_style(ctx, handler, pw); + if (error != CSS_OK) { + return error; + } + } + + /* Pass a ref back to the client */ + *style = css__computed_style_ref(ctx->default_style); + return CSS_OK; +} + + /** * Select a style for the given node * @@ -659,6 +738,18 @@ css_error css_select_style(css_select_ctx *ctx, void *node, goto cleanup; } + /* Intern the partial computed styles */ + for (j = CSS_PSEUDO_ELEMENT_NONE; j < CSS_PSEUDO_ELEMENT_COUNT; j++) { + /* Skip non-existent pseudo elements */ + if (state.results->styles[j] == NULL) + continue; + + error = css__arena_intern_style(&state.results->styles[j]); + if (error != CSS_OK) { + goto cleanup; + } + } + /* Add node name to bloom */ if (lwc_string_caseless_hash_value(state.element.name, -- cgit v1.2.3