summaryrefslogtreecommitdiff
path: root/src/select/computed.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/select/computed.c')
-rw-r--r--src/select/computed.c461
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;