summaryrefslogtreecommitdiff
path: root/src/select
diff options
context:
space:
mode:
Diffstat (limited to 'src/select')
-rw-r--r--src/select/computed.c30
-rw-r--r--src/select/computed.h17
-rw-r--r--src/select/select.c91
3 files changed, 129 insertions, 9 deletions
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,