diff options
Diffstat (limited to 'src/select/computed.c')
-rw-r--r-- | src/select/computed.c | 461 |
1 files changed, 273 insertions, 188 deletions
diff --git a/src/select/computed.c b/src/select/computed.c index 03e7c15..78f3b80 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -12,6 +12,7 @@ #include "select/dispatch.h" #include "select/propget.h" #include "select/propset.h" +#include "select/unit.h" #include "utils/utils.h" static css_error compute_absolute_color(css_computed_style *style, @@ -83,121 +84,83 @@ css_error css__computed_style_create(css_computed_style **result) } /** - * Destroy an uncommon computed style section + * Destroy a computed style * * \param style Style to destroy * \return CSS_OK on success, appropriate error otherwise */ -css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon) +css_error css_computed_style_destroy(css_computed_style *style) { - if (uncommon == NULL) + if (style == NULL) return CSS_BADPARM; - if (uncommon->count > 1) { - uncommon->count--; + if (style->count > 1) { + style->count--; return CSS_OK; - } else if (uncommon->count == 1) { - css__arena_remove_uncommon_style(uncommon); + } else if (style->count == 1) { + css__arena_remove_style(style); } - if (uncommon != NULL) { - if (uncommon->counter_increment != NULL) { - css_computed_counter *c; - - for (c = uncommon->counter_increment; - c->name != NULL; c++) { - lwc_string_unref(c->name); - } + if (style->counter_increment != NULL) { + css_computed_counter *c; - free(uncommon->counter_increment); + for (c = style->counter_increment; c->name != NULL; c++) { + lwc_string_unref(c->name); } - if (uncommon->counter_reset != NULL) { - css_computed_counter *c; - - for (c = uncommon->counter_reset; - c->name != NULL; c++) { - lwc_string_unref(c->name); - } - - free(uncommon->counter_reset); - } - - if (uncommon->cursor != NULL) { - lwc_string **s; - - for (s = uncommon->cursor; *s != NULL; s++) { - lwc_string_unref(*s); - } + free(style->counter_increment); + } - free(uncommon->cursor); - } + if (style->counter_reset != NULL) { + css_computed_counter *c; - if (uncommon->content != NULL) { - css_computed_content_item *c; - - for (c = uncommon->content; - c->type != CSS_COMPUTED_CONTENT_NONE; - c++) { - switch (c->type) { - case CSS_COMPUTED_CONTENT_STRING: - lwc_string_unref(c->data.string); - break; - case CSS_COMPUTED_CONTENT_URI: - lwc_string_unref(c->data.uri); - break; - case CSS_COMPUTED_CONTENT_ATTR: - lwc_string_unref(c->data.attr); - break; - case CSS_COMPUTED_CONTENT_COUNTER: - lwc_string_unref(c->data.counter.name); - break; - case CSS_COMPUTED_CONTENT_COUNTERS: - lwc_string_unref(c->data.counters.name); - lwc_string_unref(c->data.counters.sep); - break; - default: - break; - } - } - - free(uncommon->content); + for (c = style->counter_reset; c->name != NULL; c++) { + lwc_string_unref(c->name); } - free(uncommon); + free(style->counter_reset); } - return CSS_OK; -} - -/** - * Destroy a computed style - * - * \param style Style to destroy - * \return CSS_OK on success, appropriate error otherwise - */ -css_error css_computed_style_destroy(css_computed_style *style) -{ - if (style == NULL) - return CSS_BADPARM; - - css__computed_uncommon_destroy(style->i.uncommon); + if (style->cursor != NULL) { + lwc_string **s; - if (style->count > 1) { - style->count--; - return CSS_OK; + for (s = style->cursor; *s != NULL; s++) { + lwc_string_unref(*s); + } - } else if (style->count == 1) { - css__arena_remove_style(style); + free(style->cursor); } - if (style->page != NULL) { - free(style->page); - } + if (style->content != NULL) { + css_computed_content_item *c; + + for (c = style->content; + c->type != CSS_COMPUTED_CONTENT_NONE; + c++) { + switch (c->type) { + case CSS_COMPUTED_CONTENT_STRING: + lwc_string_unref(c->data.string); + break; + case CSS_COMPUTED_CONTENT_URI: + lwc_string_unref(c->data.uri); + break; + case CSS_COMPUTED_CONTENT_ATTR: + lwc_string_unref(c->data.attr); + break; + case CSS_COMPUTED_CONTENT_COUNTER: + lwc_string_unref(c->data.counter.name); + break; + case CSS_COMPUTED_CONTENT_COUNTERS: + lwc_string_unref(c->data.counters.name); + lwc_string_unref(c->data.counters.sep); + break; + default: + break; + } + } - if (style->i.aural != NULL) { - free(style->i.aural); + free(style->content); } if (style->font_family != NULL) { @@ -250,7 +213,7 @@ css_error css__computed_style_initialise(css_computed_style *style, return CSS_BADPARM; state.node = NULL; - state.media = CSS_MEDIA_ALL; + state.media = NULL; state.results = NULL; state.computed = style; state.handler = handler; @@ -259,8 +222,7 @@ css_error css__computed_style_initialise(css_computed_style *style, for (i = 0; i < CSS_N_PROPERTIES; i++) { /* No need to initialise anything other than the normal * properties -- the others are handled by the accessors */ - if (prop_dispatch[i].inherited == false && - prop_dispatch[i].group == GROUP_NORMAL) { + if (prop_dispatch[i].inherited == false) { error = prop_dispatch[i].initial(&state); if (error != CSS_OK) return error; @@ -271,6 +233,37 @@ css_error css__computed_style_initialise(css_computed_style *style, } /** + * Clone a computed style + * + * \param orig Style to copy + * \param clone_out Returns cloned style on success + * \return CSS_OK on success. + */ +css_error css__computed_style_clone( + const css_computed_style *orig, + css_computed_style **clone_out) +{ + css_error error; + css_computed_style *clone; + + error = css__computed_style_create(&clone); + if (error != CSS_OK) { + return error; + } + + for (size_t i = 0; i < CSS_N_PROPERTIES; i++) { + error = prop_dispatch[i].copy(orig, clone); + if (error != CSS_OK) { + css_computed_style_destroy(clone); + return error; + } + } + + *clone_out = clone; + return CSS_OK; +} + +/** * Compose two computed styles * * \param parent Parent style @@ -286,9 +279,7 @@ css_error css__computed_style_initialise(css_computed_style *style, 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, + const css_unit_ctx *unit_ctx, css_computed_style **restrict result) { css_computed_style *composed; @@ -307,25 +298,6 @@ css_error css_computed_style_compose( /* Iterate through the properties */ for (i = 0; i < CSS_N_PROPERTIES; i++) { - /* Skip any in extension blocks if the block does not exist */ - switch(prop_dispatch[i].group) { - case GROUP_NORMAL: - break; - case GROUP_UNCOMMON: - if (parent->i.uncommon == NULL && - child->i.uncommon == NULL) - continue; - break; - case GROUP_PAGE: - if (parent->page == NULL && child->page == NULL) - continue; - break; - case GROUP_AURAL: - if (parent->i.aural == NULL && child->i.aural == NULL) - continue; - break; - } - /* Compose the property */ error = prop_dispatch[i].compose(parent, child, composed); if (error != CSS_OK) @@ -333,8 +305,7 @@ css_error css_computed_style_compose( } /* Finally, compute absolute values for everything */ - error = css__compute_absolute_values(parent, composed, - compute_font_size, pw); + error = css__compute_absolute_values(parent, composed, unit_ctx); if (error != CSS_OK) { return error; } @@ -749,13 +720,39 @@ uint8_t css_computed_font_style(const css_computed_style *style) uint8_t css_computed_min_height(const css_computed_style *style, css_fixed *length, css_unit *unit) { - return get_min_height(style, length, unit); + uint8_t min_height = get_min_height(style, length, unit); + + if (min_height == CSS_MIN_HEIGHT_AUTO) { + uint8_t display = get_display(style); + + if (display != CSS_DISPLAY_FLEX && + display != CSS_DISPLAY_INLINE_FLEX) { + min_height = CSS_MIN_HEIGHT_SET; + *length = 0; + *unit = CSS_UNIT_PX; + } + } + + return min_height; } uint8_t css_computed_min_width(const css_computed_style *style, css_fixed *length, css_unit *unit) { - return get_min_width(style, length, unit); + uint8_t min_width = get_min_width(style, length, unit); + + if (min_width == CSS_MIN_WIDTH_AUTO) { + uint8_t display = get_display(style); + + if (display != CSS_DISPLAY_FLEX && + display != CSS_DISPLAY_INLINE_FLEX) { + min_width = CSS_MIN_WIDTH_SET; + *length = 0; + *unit = CSS_UNIT_PX; + } + } + + return min_width; } uint8_t css_computed_background_repeat(const css_computed_style *style) @@ -813,6 +810,18 @@ uint8_t css_computed_opacity(const css_computed_style *style, return get_opacity(style, opacity); } +uint8_t css_computed_fill_opacity(const css_computed_style *style, + css_fixed *fill_opacity) +{ + return get_fill_opacity(style, fill_opacity); +} + +uint8_t css_computed_stroke_opacity(const css_computed_style *style, + css_fixed *stroke_opacity) +{ + return get_stroke_opacity(style, stroke_opacity); +} + uint8_t css_computed_text_transform(const css_computed_style *style) { return get_text_transform(style); @@ -927,6 +936,10 @@ uint8_t css_computed_display(const css_computed_style *style, root /* 4. */) { if (display == CSS_DISPLAY_INLINE_TABLE) { return CSS_DISPLAY_TABLE; + } else if (display == CSS_DISPLAY_INLINE_FLEX) { + return CSS_DISPLAY_FLEX; + } else if (display == CSS_DISPLAY_INLINE_GRID) { + return CSS_DISPLAY_GRID; } else if (display == CSS_DISPLAY_INLINE || display == CSS_DISPLAY_RUN_IN || display == CSS_DISPLAY_TABLE_ROW_GROUP || @@ -1054,6 +1067,59 @@ uint8_t css_computed_widows(const css_computed_style *style, return get_widows(style, widows); } +uint8_t css_computed_align_content(const css_computed_style *style) +{ + return get_align_content(style); +} + +uint8_t css_computed_align_items(const css_computed_style *style) +{ + return get_align_items(style); +} + +uint8_t css_computed_align_self(const css_computed_style *style) +{ + return get_align_self(style); +} + +uint8_t css_computed_flex_basis(const css_computed_style *style, + css_fixed *length, css_unit *unit) +{ + return get_flex_basis(style, length, unit); +} + +uint8_t css_computed_flex_direction(const css_computed_style *style) +{ + return get_flex_direction(style); +} + +uint8_t css_computed_flex_grow(const css_computed_style *style, + css_fixed *number) +{ + return get_flex_grow(style, number); +} + +uint8_t css_computed_flex_shrink(const css_computed_style *style, + css_fixed *number) +{ + return get_flex_shrink(style, number); +} + +uint8_t css_computed_flex_wrap(const css_computed_style *style) +{ + return get_flex_wrap(style); +} + +uint8_t css_computed_justify_content(const css_computed_style *style) +{ + return get_justify_content(style); +} + +uint8_t css_computed_order(const css_computed_style *style, + int32_t *order) +{ + return get_order(style, order); +} /****************************************************************************** * Library internals * @@ -1064,31 +1130,36 @@ uint8_t css_computed_widows(const css_computed_style *style, * * \param parent Parent style, or NULL for tree root * \param style Computed style to process - * \param compute_font_size Callback to calculate an absolute font-size - * \param pw Private word for callback + * \param unit_ctx Client length conversion context. * \return CSS_OK on success. */ css_error css__compute_absolute_values(const css_computed_style *parent, css_computed_style *style, - css_error (*compute_font_size)(void *pw, - const css_hint *parent, css_hint *size), - void *pw) + const css_unit_ctx *unit_ctx) { + css_hint_length *ref_length = NULL; css_hint psize, size, ex_size; css_error error; - /* Ensure font-size is absolute */ + /* Get reference font-size for relative sizes. */ if (parent != NULL) { psize.status = get_font_size(parent, &psize.data.length.value, &psize.data.length.unit); + if (psize.status != CSS_FONT_SIZE_DIMENSION) { + return CSS_BADPARM; + } + ref_length = &psize.data.length; } size.status = get_font_size(style, &size.data.length.value, &size.data.length.unit); - error = compute_font_size(pw, parent != NULL ? &psize : NULL, &size); + error = css_unit_compute_absolute_font_size(ref_length, + unit_ctx->root_style, + unit_ctx->font_size_default, + &size); if (error != CSS_OK) return error; @@ -1102,7 +1173,12 @@ css_error css__compute_absolute_values(const css_computed_style *parent, ex_size.status = CSS_FONT_SIZE_DIMENSION; ex_size.data.length.value = INTTOFIX(1); ex_size.data.length.unit = CSS_UNIT_EX; - error = compute_font_size(pw, &size, &ex_size); + + error = css_unit_compute_absolute_font_size( + &size.data.length, + unit_ctx->root_style, + unit_ctx->font_size_default, + &ex_size); if (error != CSS_OK) return error; @@ -1205,76 +1281,79 @@ css_error css__compute_absolute_values(const css_computed_style *parent, if (error != CSS_OK) return error; - /* Uncommon properties */ - if (style->i.uncommon != NULL) { - /* Fix up border-spacing */ - error = compute_absolute_length_pair(style, - &ex_size.data.length, - get_border_spacing, - set_border_spacing); - if (error != CSS_OK) - return error; + /* Fix up flex-basis */ + error = compute_absolute_length(style, &ex_size.data.length, + get_flex_basis, set_flex_basis); + if (error != CSS_OK) + return error; - /* Fix up clip */ - error = compute_absolute_clip(style, &ex_size.data.length); - if (error != CSS_OK) - return error; + /* Fix up border-spacing */ + error = compute_absolute_length_pair(style, + &ex_size.data.length, + get_border_spacing, + set_border_spacing); + if (error != CSS_OK) + return error; - /* Fix up letter-spacing */ - error = compute_absolute_length(style, - &ex_size.data.length, - get_letter_spacing, - set_letter_spacing); - if (error != CSS_OK) - return error; + /* Fix up clip */ + error = compute_absolute_clip(style, &ex_size.data.length); + if (error != CSS_OK) + return error; - /* Fix up outline-color */ - error = compute_absolute_color(style, - get_outline_color, - set_outline_color); - if (error != CSS_OK) - return error; + /* Fix up letter-spacing */ + error = compute_absolute_length(style, + &ex_size.data.length, + get_letter_spacing, + set_letter_spacing); + if (error != CSS_OK) + return error; - /* Fix up outline-width */ - error = compute_absolute_border_side_width(style, - &ex_size.data.length, - get_outline_width, - set_outline_width); - if (error != CSS_OK) - return error; + /* Fix up outline-color */ + error = compute_absolute_color(style, + get_outline_color, + set_outline_color); + if (error != CSS_OK) + return error; - /* Fix up word-spacing */ - error = compute_absolute_length(style, - &ex_size.data.length, - get_word_spacing, - set_word_spacing); - if (error != CSS_OK) - return error; + /* Fix up outline-width */ + error = compute_absolute_border_side_width(style, + &ex_size.data.length, + get_outline_width, + set_outline_width); + if (error != CSS_OK) + return error; - /* Fix up column-rule-width */ - error = compute_absolute_border_side_width(style, - &ex_size.data.length, - get_column_rule_width, - set_column_rule_width); - if (error != CSS_OK) - return error; + /* Fix up word-spacing */ + error = compute_absolute_length(style, + &ex_size.data.length, + get_word_spacing, + set_word_spacing); + if (error != CSS_OK) + return error; - /* Fix up column-width */ - error = compute_absolute_length(style, - &ex_size.data.length, - get_column_width, - set_column_width); - if (error != CSS_OK) + /* Fix up column-rule-width */ + error = compute_absolute_border_side_width(style, + &ex_size.data.length, + get_column_rule_width, + set_column_rule_width); + if (error != CSS_OK) return error; - /* Fix up column-gap */ - error = compute_absolute_length(style, - &ex_size.data.length, - get_column_gap, - set_column_gap); - if (error != CSS_OK) + /* Fix up column-width */ + error = compute_absolute_length(style, + &ex_size.data.length, + get_column_width, + set_column_width); + if (error != CSS_OK) return error; - } + + /* Fix up column-gap */ + error = compute_absolute_length(style, + &ex_size.data.length, + get_column_gap, + set_column_gap); + if (error != CSS_OK) + return error; return CSS_OK; } @@ -1434,6 +1513,8 @@ css_error compute_absolute_border_side_width(css_computed_style *style, unit = ex_size->unit; } break; + default: + return CSS_INVALID; } return set(style, CSS_BORDER_WIDTH_WIDTH, length, unit); @@ -1674,8 +1755,8 @@ css_error compute_absolute_length(css_computed_style *style, css_error (*set)(css_computed_style *style, uint8_t type, css_fixed len, css_unit unit)) { + css_unit unit = CSS_UNIT_PX; css_fixed length; - css_unit unit; uint8_t type; type = get(style, &length, &unit); @@ -1715,6 +1796,10 @@ css_error compute_absolute_length_pair(css_computed_style *style, type = get(style, &length1, &unit1, &length2, &unit2); + if (type != CSS_BACKGROUND_POSITION_SET) { + return CSS_OK; + } + if (unit1 == CSS_UNIT_EX) { length1 = FMUL(length1, ex_size->value); unit1 = ex_size->unit; |