From 70411030b0c35e2886fe29eef0fb832f259190b8 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 7 Mar 2015 21:34:23 +0000 Subject: Move trivially compared parts of computed styles to sub-structures. --- src/select/computed.c | 82 +++--- src/select/computed.h | 30 ++- src/select/properties/border_spacing.c | 6 +- src/select/properties/clip.c | 6 +- src/select/properties/column_count.c | 6 +- src/select/properties/column_gap.c | 6 +- src/select/properties/column_width.c | 6 +- src/select/properties/content.c | 6 +- src/select/properties/counter_increment.c | 6 +- src/select/properties/counter_reset.c | 6 +- src/select/properties/cursor.c | 6 +- src/select/properties/letter_spacing.c | 6 +- src/select/properties/outline_color.c | 6 +- src/select/properties/outline_width.c | 6 +- src/select/properties/word_spacing.c | 6 +- src/select/propget.h | 354 +++++++++++++------------- src/select/propset.h | 402 +++++++++++++++--------------- src/select/select.c | 4 +- 18 files changed, 496 insertions(+), 454 deletions(-) diff --git a/src/select/computed.c b/src/select/computed.c index dc632f9..817da31 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -75,59 +75,61 @@ css_error css_computed_style_create(css_computed_style **result) if (s == NULL) return CSS_NOMEM; + s->bin = UINT32_MAX; *result = s; return CSS_OK; } /** - * Destroy a computed style + * Destroy an uncommon computed style section * * \param style Style to destroy * \return CSS_OK on success, appropriate error otherwise */ -css_error css_computed_style_destroy(css_computed_style *style) +css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon) { - if (style == NULL) + if (uncommon == NULL) return CSS_BADPARM; - if (style->uncommon != NULL) { - if (style->uncommon->counter_increment != NULL) { + + if (uncommon != NULL) { + if (uncommon->counter_increment != NULL) { css_computed_counter *c; - for (c = style->uncommon->counter_increment; + for (c = uncommon->counter_increment; c->name != NULL; c++) { lwc_string_unref(c->name); } - free(style->uncommon->counter_increment); + free(uncommon->counter_increment); } - if (style->uncommon->counter_reset != NULL) { + if (uncommon->counter_reset != NULL) { css_computed_counter *c; - for (c = style->uncommon->counter_reset; + for (c = uncommon->counter_reset; c->name != NULL; c++) { lwc_string_unref(c->name); } - free(style->uncommon->counter_reset); + free(uncommon->counter_reset); } - if (style->uncommon->cursor != NULL) { + if (uncommon->cursor != NULL) { lwc_string **s; - for (s = style->uncommon->cursor; *s != NULL; s++) { + for (s = uncommon->cursor; *s != NULL; s++) { lwc_string_unref(*s); } - free(style->uncommon->cursor); + free(uncommon->cursor); } - if (style->uncommon->content != NULL) { + if (uncommon->content != NULL) { css_computed_content_item *c; - for (c = style->uncommon->content; + for (c = uncommon->content; c->type != CSS_COMPUTED_CONTENT_NONE; c++) { switch (c->type) { @@ -152,18 +154,35 @@ css_error css_computed_style_destroy(css_computed_style *style) } } - free(style->uncommon->content); + free(uncommon->content); } - free(style->uncommon); + free(uncommon); } + 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->page != NULL) { free(style->page); } - if (style->aural != NULL) { - free(style->aural); + if (style->i.aural != NULL) { + free(style->i.aural); } if (style->font_family != NULL) { @@ -186,11 +205,11 @@ css_error css_computed_style_destroy(css_computed_style *style) free(style->quotes); } - if (style->list_style_image != NULL) - lwc_string_unref(style->list_style_image); + if (style->i.list_style_image != NULL) + lwc_string_unref(style->i.list_style_image); - if (style->background_image != NULL) - lwc_string_unref(style->background_image); + if (style->i.background_image != NULL) + lwc_string_unref(style->i.background_image); free(style); @@ -264,8 +283,8 @@ css_error css_computed_style_compose(const css_computed_style *parent, for (i = 0; i < CSS_N_PROPERTIES; i++) { /* Skip any in extension blocks if the block does not exist */ if (prop_dispatch[i].group == GROUP_UNCOMMON && - parent->uncommon == NULL && - child->uncommon == NULL) + parent->i.uncommon == NULL && + child->i.uncommon == NULL) continue; if (prop_dispatch[i].group == GROUP_PAGE && @@ -273,7 +292,8 @@ css_error css_computed_style_compose(const css_computed_style *parent, continue; if (prop_dispatch[i].group == GROUP_AURAL && - parent->aural == NULL && child->aural == NULL) + parent->i.aural == NULL && + child->i.aural == NULL) continue; /* Compose the property */ @@ -444,7 +464,7 @@ uint8_t css_computed_top(const css_computed_style *style, *unit = CSS_UNIT_PX; } else if (top == CSS_TOP_AUTO) { /* Top is auto => -bottom */ - *length = -style->bottom; + *length = -style->i.bottom; *unit = (css_unit) (bottom >> 2); } @@ -474,7 +494,7 @@ uint8_t css_computed_right(const css_computed_style *style, *unit = CSS_UNIT_PX; } else if (right == CSS_RIGHT_AUTO) { /* Right is auto => -left */ - *length = -style->left; + *length = -style->i.left; *unit = (css_unit) (left >> 2); } else { /** \todo Consider containing block's direction @@ -508,7 +528,7 @@ uint8_t css_computed_bottom(const css_computed_style *style, } else if (bottom == CSS_BOTTOM_AUTO || (top & 0x3) != CSS_TOP_AUTO) { /* Bottom is auto or top is not auto => -top */ - *length = -style->top; + *length = -style->i.top; *unit = (css_unit) (top >> 2); } @@ -538,7 +558,7 @@ uint8_t css_computed_left(const css_computed_style *style, *unit = CSS_UNIT_PX; } else if (left == CSS_LEFT_AUTO) { /* Left is auto => -right */ - *length = -style->right; + *length = -style->i.right; *unit = (css_unit) (right >> 2); } else { /** \todo Consider containing block's direction @@ -1144,7 +1164,7 @@ css_error css__compute_absolute_values(const css_computed_style *parent, return error; /* Uncommon properties */ - if (style->uncommon != NULL) { + if (style->i.uncommon != NULL) { /* Fix up border-spacing */ error = compute_absolute_length_pair(style, &ex_size.data.length, diff --git a/src/select/computed.h b/src/select/computed.h index 0ca01d9..f965993 100644 --- a/src/select/computed.h +++ b/src/select/computed.h @@ -13,7 +13,7 @@ -typedef struct css_computed_uncommon { +struct css_computed_uncommon_i { /* * border_spacing 1 + 2(4) 2(4) * break_before 4 0 @@ -99,13 +99,20 @@ typedef struct css_computed_uncommon { css_color column_rule_color; css_fixed column_rule_width; css_fixed column_width; +}; + +typedef struct css_computed_uncommon { + struct css_computed_uncommon_i i; css_computed_counter *counter_increment; css_computed_counter *counter_reset; - lwc_string **cursor; - css_computed_content_item *content; + + lwc_string **cursor; + struct css_computed_uncommon *next; + uint32_t count; + uint32_t bin; } css_computed_uncommon; typedef struct css_computed_page { @@ -122,7 +129,7 @@ typedef struct css_computed_page { int32_t orphans; } css_computed_page; -struct css_computed_style { +struct css_computed_style_i { /* * background_attachment 2 * background_repeat 3 @@ -302,15 +309,24 @@ struct css_computed_style { int32_t z_index; + css_computed_uncommon *uncommon;/**< Uncommon properties */ + void *aural; /**< Aural properties */ +}; + +struct css_computed_style { + struct css_computed_style_i i; + lwc_string **font_family; lwc_string **quotes; - - css_computed_uncommon *uncommon;/**< Uncommon properties */ - void *aural; /**< Aural properties */ css_computed_page *page; /**< Page properties */ + struct css_computed_style *next; + uint32_t count; + uint32_t bin; }; +css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon); + css_error css__compute_absolute_values(const css_computed_style *parent, css_computed_style *style, css_error (*compute_font_size)(void *pw, diff --git a/src/select/properties/border_spacing.c b/src/select/properties/border_spacing.c index 1b32747..db7b1f2 100644 --- a/src/select/properties/border_spacing.c +++ b/src/select/properties/border_spacing.c @@ -71,10 +71,10 @@ css_error css__compose_border_spacing(const css_computed_style *parent, uint8_t type = get_border_spacing(child, &hlength, &hunit, &vlength, &vunit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_BORDER_SPACING_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_BORDER_SPACING_INHERIT) { type = get_border_spacing(parent, &hlength, &hunit, &vlength, &vunit); diff --git a/src/select/properties/clip.c b/src/select/properties/clip.c index d98c7eb..cc39d99 100644 --- a/src/select/properties/clip.c +++ b/src/select/properties/clip.c @@ -102,10 +102,10 @@ css_error css__compose_clip(const css_computed_style *parent, false, false, false, false }; uint8_t type = get_clip(child, &rect); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CLIP_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CLIP_INHERIT) { type = get_clip(parent, &rect); } diff --git a/src/select/properties/column_count.c b/src/select/properties/column_count.c index 92fdec2..4ded377 100644 --- a/src/select/properties/column_count.c +++ b/src/select/properties/column_count.c @@ -59,10 +59,10 @@ css_error css__compose_column_count(const css_computed_style *parent, int32_t count = 0; uint8_t type = get_column_count(child, &count); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_COUNT_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_COUNT_INHERIT) { type = get_column_count(parent, &count); } diff --git a/src/select/properties/column_gap.c b/src/select/properties/column_gap.c index 641f529..f544f44 100644 --- a/src/select/properties/column_gap.c +++ b/src/select/properties/column_gap.c @@ -41,10 +41,10 @@ css_error css__compose_column_gap(const css_computed_style *parent, css_unit unit = CSS_UNIT_EM; uint8_t type = get_column_gap(child, &length, &unit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_GAP_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_GAP_INHERIT) { type = get_column_gap(parent, &length, &unit); } diff --git a/src/select/properties/column_width.c b/src/select/properties/column_width.c index 45eb7fc..b6550ab 100644 --- a/src/select/properties/column_width.c +++ b/src/select/properties/column_width.c @@ -41,10 +41,10 @@ css_error css__compose_column_width(const css_computed_style *parent, css_unit unit = CSS_UNIT_EM; uint8_t type = get_column_width(child, &length, &unit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_WIDTH_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COLUMN_WIDTH_INHERIT) { type = get_column_width(parent, &length, &unit); } diff --git a/src/select/properties/content.c b/src/select/properties/content.c index c79dd0d..a9dd211 100644 --- a/src/select/properties/content.c +++ b/src/select/properties/content.c @@ -206,13 +206,13 @@ css_error css__compose_content(const css_computed_style *parent, const css_computed_content_item *items = NULL; uint8_t type = get_content(child, &items); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CONTENT_INHERIT || - (child->uncommon != NULL && result != child)) { + (child->i.uncommon != NULL && result != child)) { size_t n_items = 0; css_computed_content_item *copy = NULL; - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CONTENT_INHERIT) { type = get_content(parent, &items); } diff --git a/src/select/properties/counter_increment.c b/src/select/properties/counter_increment.c index 429e558..644607b 100644 --- a/src/select/properties/counter_increment.c +++ b/src/select/properties/counter_increment.c @@ -56,13 +56,13 @@ css_error css__compose_counter_increment(const css_computed_style *parent, const css_computed_counter *items = NULL; uint8_t type = get_counter_increment(child, &items); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COUNTER_INCREMENT_INHERIT || - (child->uncommon != NULL && result != child)) { + (child->i.uncommon != NULL && result != child)) { size_t n_items = 0; css_computed_counter *copy = NULL; - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COUNTER_INCREMENT_INHERIT) { type = get_counter_increment(parent, &items); } diff --git a/src/select/properties/counter_reset.c b/src/select/properties/counter_reset.c index ddf54aa..05559f5 100644 --- a/src/select/properties/counter_reset.c +++ b/src/select/properties/counter_reset.c @@ -55,13 +55,13 @@ css_error css__compose_counter_reset(const css_computed_style *parent, const css_computed_counter *items = NULL; uint8_t type = get_counter_reset(child, &items); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COUNTER_RESET_INHERIT || - (child->uncommon != NULL && result != child)) { + (child->i.uncommon != NULL && result != child)) { size_t n_items = 0; css_computed_counter *copy = NULL; - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_COUNTER_RESET_INHERIT) { type = get_counter_reset(parent, &items); } diff --git a/src/select/properties/cursor.c b/src/select/properties/cursor.c index a77d21b..1ca497f 100644 --- a/src/select/properties/cursor.c +++ b/src/select/properties/cursor.c @@ -172,13 +172,13 @@ css_error css__compose_cursor(const css_computed_style *parent, lwc_string **urls = NULL; uint8_t type = get_cursor(child, &urls); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CURSOR_INHERIT || - (child->uncommon != NULL && result != child)) { + (child->i.uncommon != NULL && result != child)) { size_t n_urls = 0; lwc_string **copy = NULL; - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_CURSOR_INHERIT) { type = get_cursor(parent, &urls); } diff --git a/src/select/properties/letter_spacing.c b/src/select/properties/letter_spacing.c index 322efef..cc00100 100644 --- a/src/select/properties/letter_spacing.c +++ b/src/select/properties/letter_spacing.c @@ -41,10 +41,10 @@ css_error css__compose_letter_spacing(const css_computed_style *parent, css_unit unit = CSS_UNIT_PX; uint8_t type = get_letter_spacing(child, &length, &unit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_LETTER_SPACING_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_LETTER_SPACING_INHERIT) { type = get_letter_spacing(parent, &length, &unit); } diff --git a/src/select/properties/outline_color.c b/src/select/properties/outline_color.c index 36aafd7..2613839 100644 --- a/src/select/properties/outline_color.c +++ b/src/select/properties/outline_color.c @@ -65,10 +65,10 @@ css_error css__compose_outline_color(const css_computed_style *parent, css_color color = 0; uint8_t type = get_outline_color(child, &color); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_OUTLINE_COLOR_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_OUTLINE_COLOR_INHERIT) { type = get_outline_color(parent, &color); } diff --git a/src/select/properties/outline_width.c b/src/select/properties/outline_width.c index 5380179..547c42a 100644 --- a/src/select/properties/outline_width.c +++ b/src/select/properties/outline_width.c @@ -41,10 +41,10 @@ css_error css__compose_outline_width(const css_computed_style *parent, css_unit unit = CSS_UNIT_PX; uint8_t type = get_outline_width(child, &length, &unit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_OUTLINE_WIDTH_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_OUTLINE_WIDTH_INHERIT) { type = get_outline_width(parent, &length, &unit); } diff --git a/src/select/properties/word_spacing.c b/src/select/properties/word_spacing.c index dd4e1d7..24eda89 100644 --- a/src/select/properties/word_spacing.c +++ b/src/select/properties/word_spacing.c @@ -41,10 +41,10 @@ css_error css__compose_word_spacing(const css_computed_style *parent, css_unit unit = CSS_UNIT_PX; uint8_t type = get_word_spacing(child, &length, &unit); - if ((child->uncommon == NULL && parent->uncommon != NULL) || + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_WORD_SPACING_INHERIT || - (child->uncommon != NULL && result != child)) { - if ((child->uncommon == NULL && parent->uncommon != NULL) || + (child->i.uncommon != NULL && result != child)) { + if ((child->i.uncommon == NULL && parent->i.uncommon != NULL) || type == CSS_WORD_SPACING_INHERIT) { type = get_word_spacing(parent, &length, &unit); } diff --git a/src/select/propget.h b/src/select/propget.h index 2a263aa..5552e39 100644 --- a/src/select/propget.h +++ b/src/select/propget.h @@ -21,15 +21,15 @@ static inline uint8_t get_letter_spacing( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[LETTER_SPACING_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[LETTER_SPACING_INDEX]; bits &= LETTER_SPACING_MASK; bits >>= LETTER_SPACING_SHIFT; /* 6bits: uuuutt : unit | type */ if ((bits & 3) == CSS_LETTER_SPACING_SET) { - *length = style->uncommon->letter_spacing; + *length = style->i.uncommon->i.letter_spacing; *unit = bits >> 2; } @@ -49,15 +49,15 @@ static inline uint8_t get_letter_spacing( static inline uint8_t get_outline_color( const css_computed_style *style, css_color *color) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[OUTLINE_COLOR_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[OUTLINE_COLOR_INDEX]; bits &= OUTLINE_COLOR_MASK; bits >>= OUTLINE_COLOR_SHIFT; /* 2bits: tt : type */ if ((bits & 3) == CSS_OUTLINE_COLOR_COLOR) { - *color = style->uncommon->outline_color; + *color = style->i.uncommon->i.outline_color; } return (bits & 3); @@ -77,15 +77,15 @@ static inline uint8_t get_outline_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[OUTLINE_WIDTH_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[OUTLINE_WIDTH_INDEX]; bits &= OUTLINE_WIDTH_MASK; bits >>= OUTLINE_WIDTH_SHIFT; /* 7bits: uuuuttt : unit | type */ if ((bits & 7) == CSS_OUTLINE_WIDTH_WIDTH) { - *length = style->uncommon->outline_width; + *length = style->i.uncommon->i.outline_width; *unit = bits >> 3; } @@ -110,24 +110,24 @@ static inline uint8_t get_border_spacing( css_fixed *hlength, css_unit *hunit, css_fixed *vlength, css_unit *vunit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[BORDER_SPACING_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[BORDER_SPACING_INDEX]; bits &= BORDER_SPACING_MASK; bits >>= BORDER_SPACING_SHIFT; /* 1 bit: type */ if (bits == CSS_BORDER_SPACING_SET) { uint8_t bits1 = - style->uncommon->bits[BORDER_SPACING_INDEX1]; + style->i.uncommon->i.bits[BORDER_SPACING_INDEX1]; bits1 &= BORDER_SPACING_MASK1; bits1 >>= BORDER_SPACING_SHIFT1; /* 8bits: hhhhvvvv : hunit | vunit */ - *hlength = style->uncommon->border_spacing[0]; + *hlength = style->i.uncommon->i.border_spacing[0]; *hunit = bits1 >> 4; - *vlength = style->uncommon->border_spacing[1]; + *vlength = style->i.uncommon->i.border_spacing[1]; *vunit = bits1 & 0xf; } @@ -152,8 +152,8 @@ static inline uint8_t get_border_spacing( static inline uint8_t get_break_after( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[BREAK_AFTER_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[BREAK_AFTER_INDEX]; bits &= BREAK_AFTER_MASK; bits >>= BREAK_AFTER_SHIFT; @@ -174,8 +174,8 @@ static inline uint8_t get_break_after( static inline uint8_t get_break_before( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[BREAK_BEFORE_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[BREAK_BEFORE_INDEX]; bits &= BREAK_BEFORE_MASK; bits >>= BREAK_BEFORE_SHIFT; @@ -196,8 +196,8 @@ static inline uint8_t get_break_before( static inline uint8_t get_break_inside( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[BREAK_INSIDE_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[BREAK_INSIDE_INDEX]; bits &= BREAK_INSIDE_MASK; bits >>= BREAK_INSIDE_SHIFT; @@ -219,15 +219,15 @@ static inline uint8_t get_word_spacing( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[WORD_SPACING_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[WORD_SPACING_INDEX]; bits &= WORD_SPACING_MASK; bits >>= WORD_SPACING_SHIFT; /* 6bits: uuuutt : unit | type */ if ((bits & 3) == CSS_WORD_SPACING_SET) { - *length = style->uncommon->word_spacing; + *length = style->i.uncommon->i.word_spacing; *unit = bits >> 2; } @@ -247,8 +247,8 @@ static inline uint8_t get_word_spacing( static inline uint8_t get_writing_mode( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[WRITING_MODE_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[WRITING_MODE_INDEX]; bits &= WRITING_MODE_MASK; bits >>= WRITING_MODE_SHIFT; @@ -270,13 +270,13 @@ static inline uint8_t get_counter_increment( const css_computed_style *style, const css_computed_counter **counters) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COUNTER_INCREMENT_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COUNTER_INCREMENT_INDEX]; bits &= COUNTER_INCREMENT_MASK; bits >>= COUNTER_INCREMENT_SHIFT; /* 1bit: type */ - *counters = style->uncommon->counter_increment; + *counters = style->i.uncommon->counter_increment; return bits; } @@ -295,13 +295,13 @@ static inline uint8_t get_counter_reset( const css_computed_style *style, const css_computed_counter **counters) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COUNTER_RESET_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COUNTER_RESET_INDEX]; bits &= COUNTER_RESET_MASK; bits >>= COUNTER_RESET_SHIFT; /* 1bit: type */ - *counters = style->uncommon->counter_reset; + *counters = style->i.uncommon->counter_reset; return bits; } @@ -320,13 +320,13 @@ static inline uint8_t get_cursor( const css_computed_style *style, lwc_string ***urls) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[CURSOR_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[CURSOR_INDEX]; bits &= CURSOR_MASK; bits >>= CURSOR_SHIFT; /* 5bits: type */ - *urls = style->uncommon->cursor; + *urls = style->i.uncommon->cursor; return bits; } @@ -351,8 +351,8 @@ static inline uint8_t get_clip( const css_computed_style *style, css_computed_clip_rect *rect) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[CLIP_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[CLIP_INDEX]; bits &= CLIP_MASK; bits >>= CLIP_SHIFT; @@ -368,33 +368,33 @@ static inline uint8_t get_clip( if (rect->top_auto == false || rect->right_auto == false) { /* 8bits: ttttrrrr : top | right */ - bits1 = style->uncommon->bits[CLIP_INDEX1]; + bits1 = style->i.uncommon->i.bits[CLIP_INDEX1]; bits1 &= CLIP_MASK1; bits1 >>= CLIP_SHIFT1; } else { bits1 = 0; } - rect->top = style->uncommon->clip[0]; + rect->top = style->i.uncommon->i.clip[0]; rect->tunit = bits1 >> 4; - rect->right = style->uncommon->clip[1]; + rect->right = style->i.uncommon->i.clip[1]; rect->runit = bits1 & 0xf; if (rect->bottom_auto == false || rect->left_auto == false) { /* 8bits: bbbbllll : bottom | left */ - bits1 = style->uncommon->bits[CLIP_INDEX2]; + bits1 = style->i.uncommon->i.bits[CLIP_INDEX2]; bits1 &= CLIP_MASK2; bits1 >>= CLIP_SHIFT2; } else { bits1 = 0; } - rect->bottom = style->uncommon->clip[2]; + rect->bottom = style->i.uncommon->i.clip[2]; rect->bunit = bits1 >> 4; - rect->left = style->uncommon->clip[3]; + rect->left = style->i.uncommon->i.clip[3]; rect->lunit = bits1 & 0xf; } @@ -420,13 +420,13 @@ static inline uint8_t get_clip( static inline uint8_t get_column_count( const css_computed_style *style, int32_t *count) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_COUNT_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_COUNT_INDEX]; bits &= COLUMN_COUNT_MASK; bits >>= COLUMN_COUNT_SHIFT; /* 2bits: tt : type */ - *count = style->uncommon->column_count; + *count = style->i.uncommon->i.column_count; return bits; } @@ -444,8 +444,8 @@ static inline uint8_t get_column_count( static inline uint8_t get_column_fill( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_FILL_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_FILL_INDEX]; bits &= COLUMN_FILL_MASK; bits >>= COLUMN_FILL_SHIFT; @@ -467,14 +467,14 @@ static inline uint8_t get_column_gap( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_GAP_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_GAP_INDEX]; bits &= COLUMN_GAP_MASK; bits >>= COLUMN_GAP_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_COLUMN_GAP_SET) { - *length = style->uncommon->column_gap; + *length = style->i.uncommon->i.column_gap; *unit = bits >> 2; } @@ -495,13 +495,13 @@ static inline uint8_t get_column_rule_color( const css_computed_style *style, css_color *color) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_RULE_COLOR_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_RULE_COLOR_INDEX]; bits &= COLUMN_RULE_COLOR_MASK; bits >>= COLUMN_RULE_COLOR_SHIFT; /* 2bits: type */ - *color = style->uncommon->column_rule_color; + *color = style->i.uncommon->i.column_rule_color; return bits; } @@ -520,8 +520,8 @@ static inline uint8_t get_column_rule_color( static inline uint8_t get_column_rule_style( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_RULE_STYLE_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_RULE_STYLE_INDEX]; bits &= COLUMN_RULE_STYLE_MASK; bits >>= COLUMN_RULE_STYLE_SHIFT; @@ -543,14 +543,14 @@ static inline uint8_t get_column_rule_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_RULE_WIDTH_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_RULE_WIDTH_INDEX]; bits &= COLUMN_RULE_WIDTH_MASK; bits >>= COLUMN_RULE_WIDTH_SHIFT; /* 7bits: uuuuttt : units | type */ if ((bits & 0x7) == CSS_COLUMN_RULE_WIDTH_WIDTH) { - *length = style->uncommon->column_rule_width; + *length = style->i.uncommon->i.column_rule_width; *unit = bits >> 3; } @@ -570,8 +570,8 @@ static inline uint8_t get_column_rule_width( static inline uint8_t get_column_span( const css_computed_style *style) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_SPAN_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_SPAN_INDEX]; bits &= COLUMN_SPAN_MASK; bits >>= COLUMN_SPAN_SHIFT; @@ -593,14 +593,14 @@ static inline uint8_t get_column_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[COLUMN_WIDTH_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[COLUMN_WIDTH_INDEX]; bits &= COLUMN_WIDTH_MASK; bits >>= COLUMN_WIDTH_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_COLUMN_WIDTH_SET) { - *length = style->uncommon->column_width; + *length = style->i.uncommon->i.column_width; *unit = bits >> 2; } @@ -621,13 +621,13 @@ static inline uint8_t get_content( const css_computed_style *style, const css_computed_content_item **content) { - if (style->uncommon != NULL) { - uint8_t bits = style->uncommon->bits[CONTENT_INDEX]; + if (style->i.uncommon != NULL) { + uint8_t bits = style->i.uncommon->i.bits[CONTENT_INDEX]; bits &= CONTENT_MASK; bits >>= CONTENT_SHIFT; /* 2bits: type */ - *content = style->uncommon->content; + *content = style->i.uncommon->content; return bits; } @@ -646,13 +646,13 @@ static inline uint8_t get_vertical_align( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[VERTICAL_ALIGN_INDEX]; + uint8_t bits = style->i.bits[VERTICAL_ALIGN_INDEX]; bits &= VERTICAL_ALIGN_MASK; bits >>= VERTICAL_ALIGN_SHIFT; /* 8bits: uuuutttt : units | type */ if ((bits & 0xf) == CSS_VERTICAL_ALIGN_SET) { - *length = style->vertical_align; + *length = style->i.vertical_align; *unit = bits >> 4; } @@ -669,13 +669,13 @@ static inline uint8_t get_font_size( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[FONT_SIZE_INDEX]; + uint8_t bits = style->i.bits[FONT_SIZE_INDEX]; bits &= FONT_SIZE_MASK; bits >>= FONT_SIZE_SHIFT; /* 8bits: uuuutttt : units | type */ if ((bits & 0xf) == CSS_FONT_SIZE_DIMENSION) { - *length = style->font_size; + *length = style->i.font_size; *unit = bits >> 4; } @@ -692,13 +692,13 @@ static inline uint8_t get_border_top_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[BORDER_TOP_WIDTH_INDEX]; + uint8_t bits = style->i.bits[BORDER_TOP_WIDTH_INDEX]; bits &= BORDER_TOP_WIDTH_MASK; bits >>= BORDER_TOP_WIDTH_SHIFT; /* 7bits: uuuuttt : units | type */ if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { - *length = style->border_width[0]; + *length = style->i.border_width[0]; *unit = bits >> 3; } @@ -715,13 +715,13 @@ static inline uint8_t get_border_right_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[BORDER_RIGHT_WIDTH_INDEX]; + uint8_t bits = style->i.bits[BORDER_RIGHT_WIDTH_INDEX]; bits &= BORDER_RIGHT_WIDTH_MASK; bits >>= BORDER_RIGHT_WIDTH_SHIFT; /* 7bits: uuuuttt : units | type */ if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { - *length = style->border_width[1]; + *length = style->i.border_width[1]; *unit = bits >> 3; } @@ -738,13 +738,13 @@ static inline uint8_t get_border_bottom_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[BORDER_BOTTOM_WIDTH_INDEX]; + uint8_t bits = style->i.bits[BORDER_BOTTOM_WIDTH_INDEX]; bits &= BORDER_BOTTOM_WIDTH_MASK; bits >>= BORDER_BOTTOM_WIDTH_SHIFT; /* 7bits: uuuuttt : units | type */ if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { - *length = style->border_width[2]; + *length = style->i.border_width[2]; *unit = bits >> 3; } @@ -761,13 +761,13 @@ static inline uint8_t get_border_left_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[BORDER_LEFT_WIDTH_INDEX]; + uint8_t bits = style->i.bits[BORDER_LEFT_WIDTH_INDEX]; bits &= BORDER_LEFT_WIDTH_MASK; bits >>= BORDER_LEFT_WIDTH_SHIFT; /* 7bits: uuuuttt : units | type */ if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { - *length = style->border_width[3]; + *length = style->i.border_width[3]; *unit = bits >> 3; } @@ -784,12 +784,12 @@ static inline uint8_t get_background_image( const css_computed_style *style, lwc_string **url) { - uint8_t bits = style->bits[BACKGROUND_IMAGE_INDEX]; + uint8_t bits = style->i.bits[BACKGROUND_IMAGE_INDEX]; bits &= BACKGROUND_IMAGE_MASK; bits >>= BACKGROUND_IMAGE_SHIFT; /* 1bit: type */ - *url = style->background_image; + *url = style->i.background_image; return bits; } @@ -804,12 +804,12 @@ static inline uint8_t get_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[COLOR_INDEX]; + uint8_t bits = style->i.bits[COLOR_INDEX]; bits &= COLOR_MASK; bits >>= COLOR_SHIFT; /* 1bit: type */ - *color = style->color; + *color = style->i.color; return bits; } @@ -824,12 +824,12 @@ static inline uint8_t get_list_style_image( const css_computed_style *style, lwc_string **url) { - uint8_t bits = style->bits[LIST_STYLE_IMAGE_INDEX]; + uint8_t bits = style->i.bits[LIST_STYLE_IMAGE_INDEX]; bits &= LIST_STYLE_IMAGE_MASK; bits >>= LIST_STYLE_IMAGE_SHIFT; /* 1bit: type */ - *url = style->list_style_image; + *url = style->i.list_style_image; return bits; } @@ -844,7 +844,7 @@ static inline uint8_t get_quotes( const css_computed_style *style, lwc_string ***quotes) { - uint8_t bits = style->bits[QUOTES_INDEX]; + uint8_t bits = style->i.bits[QUOTES_INDEX]; bits &= QUOTES_MASK; bits >>= QUOTES_SHIFT; @@ -864,13 +864,13 @@ static inline uint8_t get_top( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[TOP_INDEX]; + uint8_t bits = style->i.bits[TOP_INDEX]; bits &= TOP_MASK; bits >>= TOP_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_TOP_SET) { - *length = style->top; + *length = style->i.top; *unit = bits >> 2; } @@ -879,7 +879,7 @@ static inline uint8_t get_top( static inline uint8_t get_top_bits( const css_computed_style *style) { - uint8_t bits = style->bits[TOP_INDEX]; + uint8_t bits = style->i.bits[TOP_INDEX]; bits &= TOP_MASK; bits >>= TOP_SHIFT; @@ -897,13 +897,13 @@ static inline uint8_t get_right( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[RIGHT_INDEX]; + uint8_t bits = style->i.bits[RIGHT_INDEX]; bits &= RIGHT_MASK; bits >>= RIGHT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_RIGHT_SET) { - *length = style->right; + *length = style->i.right; *unit = bits >> 2; } @@ -912,7 +912,7 @@ static inline uint8_t get_right( static inline uint8_t get_right_bits( const css_computed_style *style) { - uint8_t bits = style->bits[RIGHT_INDEX]; + uint8_t bits = style->i.bits[RIGHT_INDEX]; bits &= RIGHT_MASK; bits >>= RIGHT_SHIFT; @@ -930,13 +930,13 @@ static inline uint8_t get_bottom( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[BOTTOM_INDEX]; + uint8_t bits = style->i.bits[BOTTOM_INDEX]; bits &= BOTTOM_MASK; bits >>= BOTTOM_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_BOTTOM_SET) { - *length = style->bottom; + *length = style->i.bottom; *unit = bits >> 2; } @@ -945,7 +945,7 @@ static inline uint8_t get_bottom( static inline uint8_t get_bottom_bits( const css_computed_style *style) { - uint8_t bits = style->bits[BOTTOM_INDEX]; + uint8_t bits = style->i.bits[BOTTOM_INDEX]; bits &= BOTTOM_MASK; bits >>= BOTTOM_SHIFT; @@ -963,13 +963,13 @@ static inline uint8_t get_left( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[LEFT_INDEX]; + uint8_t bits = style->i.bits[LEFT_INDEX]; bits &= LEFT_MASK; bits >>= LEFT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_LEFT_SET) { - *length = style->left; + *length = style->i.left; *unit = bits >> 2; } @@ -978,7 +978,7 @@ static inline uint8_t get_left( static inline uint8_t get_left_bits( const css_computed_style *style) { - uint8_t bits = style->bits[LEFT_INDEX]; + uint8_t bits = style->i.bits[LEFT_INDEX]; bits &= LEFT_MASK; bits >>= LEFT_SHIFT; @@ -996,12 +996,12 @@ static inline uint8_t get_border_top_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[BORDER_TOP_COLOR_INDEX]; + uint8_t bits = style->i.bits[BORDER_TOP_COLOR_INDEX]; bits &= BORDER_TOP_COLOR_MASK; bits >>= BORDER_TOP_COLOR_SHIFT; /* 2bits: type */ - *color = style->border_color[0]; + *color = style->i.border_color[0]; return bits; } @@ -1016,12 +1016,12 @@ static inline uint8_t get_border_right_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[BORDER_RIGHT_COLOR_INDEX]; + uint8_t bits = style->i.bits[BORDER_RIGHT_COLOR_INDEX]; bits &= BORDER_RIGHT_COLOR_MASK; bits >>= BORDER_RIGHT_COLOR_SHIFT; /* 2bits: type */ - *color = style->border_color[1]; + *color = style->i.border_color[1]; return bits; } @@ -1036,12 +1036,12 @@ static inline uint8_t get_border_bottom_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[BORDER_BOTTOM_COLOR_INDEX]; + uint8_t bits = style->i.bits[BORDER_BOTTOM_COLOR_INDEX]; bits &= BORDER_BOTTOM_COLOR_MASK; bits >>= BORDER_BOTTOM_COLOR_SHIFT; /* 2bits: type */ - *color = style->border_color[2]; + *color = style->i.border_color[2]; return bits; } @@ -1056,12 +1056,12 @@ static inline uint8_t get_border_left_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[BORDER_LEFT_COLOR_INDEX]; + uint8_t bits = style->i.bits[BORDER_LEFT_COLOR_INDEX]; bits &= BORDER_LEFT_COLOR_MASK; bits >>= BORDER_LEFT_COLOR_SHIFT; /* 2bits: type */ - *color = style->border_color[3]; + *color = style->i.border_color[3]; return bits; } @@ -1076,13 +1076,13 @@ static inline uint8_t get_height( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[HEIGHT_INDEX]; + uint8_t bits = style->i.bits[HEIGHT_INDEX]; bits &= HEIGHT_MASK; bits >>= HEIGHT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_HEIGHT_SET) { - *length = style->height; + *length = style->i.height; *unit = bits >> 2; } @@ -1099,14 +1099,14 @@ static inline uint8_t get_line_height( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[LINE_HEIGHT_INDEX]; + uint8_t bits = style->i.bits[LINE_HEIGHT_INDEX]; bits &= LINE_HEIGHT_MASK; bits >>= LINE_HEIGHT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_LINE_HEIGHT_NUMBER || (bits & 0x3) == CSS_LINE_HEIGHT_DIMENSION) { - *length = style->line_height; + *length = style->i.line_height; } if ((bits & 0x3) == CSS_LINE_HEIGHT_DIMENSION) { @@ -1126,12 +1126,12 @@ static inline uint8_t get_background_color( const css_computed_style *style, css_color *color) { - uint8_t bits = style->bits[BACKGROUND_COLOR_INDEX]; + uint8_t bits = style->i.bits[BACKGROUND_COLOR_INDEX]; bits &= BACKGROUND_COLOR_MASK; bits >>= BACKGROUND_COLOR_SHIFT; /* 2bits: type */ - *color = style->background_color; + *color = style->i.background_color; return bits; } @@ -1146,12 +1146,12 @@ static inline uint8_t get_z_index( const css_computed_style *style, int32_t *z_index) { - uint8_t bits = style->bits[Z_INDEX_INDEX]; + uint8_t bits = style->i.bits[Z_INDEX_INDEX]; bits &= Z_INDEX_MASK; bits >>= Z_INDEX_SHIFT; /* 2bits: type */ - *z_index = style->z_index; + *z_index = style->i.z_index; return bits; } @@ -1166,13 +1166,13 @@ static inline uint8_t get_margin_top( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MARGIN_TOP_INDEX]; + uint8_t bits = style->i.bits[MARGIN_TOP_INDEX]; bits &= MARGIN_TOP_MASK; bits >>= MARGIN_TOP_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MARGIN_SET) { - *length = style->margin[0]; + *length = style->i.margin[0]; *unit = bits >> 2; } @@ -1189,13 +1189,13 @@ static inline uint8_t get_margin_right( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MARGIN_RIGHT_INDEX]; + uint8_t bits = style->i.bits[MARGIN_RIGHT_INDEX]; bits &= MARGIN_RIGHT_MASK; bits >>= MARGIN_RIGHT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MARGIN_SET) { - *length = style->margin[1]; + *length = style->i.margin[1]; *unit = bits >> 2; } @@ -1212,13 +1212,13 @@ static inline uint8_t get_margin_bottom( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MARGIN_BOTTOM_INDEX]; + uint8_t bits = style->i.bits[MARGIN_BOTTOM_INDEX]; bits &= MARGIN_BOTTOM_MASK; bits >>= MARGIN_BOTTOM_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MARGIN_SET) { - *length = style->margin[2]; + *length = style->i.margin[2]; *unit = bits >> 2; } @@ -1235,13 +1235,13 @@ static inline uint8_t get_margin_left( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MARGIN_LEFT_INDEX]; + uint8_t bits = style->i.bits[MARGIN_LEFT_INDEX]; bits &= MARGIN_LEFT_MASK; bits >>= MARGIN_LEFT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MARGIN_SET) { - *length = style->margin[3]; + *length = style->i.margin[3]; *unit = bits >> 2; } @@ -1257,7 +1257,7 @@ static inline uint8_t get_margin_left( static inline uint8_t get_background_attachment( const css_computed_style *style) { - uint8_t bits = style->bits[BACKGROUND_ATTACHMENT_INDEX]; + uint8_t bits = style->i.bits[BACKGROUND_ATTACHMENT_INDEX]; bits &= BACKGROUND_ATTACHMENT_MASK; bits >>= BACKGROUND_ATTACHMENT_SHIFT; @@ -1274,7 +1274,7 @@ static inline uint8_t get_background_attachment( static inline uint8_t get_border_collapse( const css_computed_style *style) { - uint8_t bits = style->bits[BORDER_COLLAPSE_INDEX]; + uint8_t bits = style->i.bits[BORDER_COLLAPSE_INDEX]; bits &= BORDER_COLLAPSE_MASK; bits >>= BORDER_COLLAPSE_SHIFT; @@ -1291,7 +1291,7 @@ static inline uint8_t get_border_collapse( static inline uint8_t get_caption_side( const css_computed_style *style) { - uint8_t bits = style->bits[CAPTION_SIDE_INDEX]; + uint8_t bits = style->i.bits[CAPTION_SIDE_INDEX]; bits &= CAPTION_SIDE_MASK; bits >>= CAPTION_SIDE_SHIFT; @@ -1308,7 +1308,7 @@ static inline uint8_t get_caption_side( static inline uint8_t get_direction( const css_computed_style *style) { - uint8_t bits = style->bits[DIRECTION_INDEX]; + uint8_t bits = style->i.bits[DIRECTION_INDEX]; bits &= DIRECTION_MASK; bits >>= DIRECTION_SHIFT; @@ -1326,13 +1326,13 @@ static inline uint8_t get_max_height( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MAX_HEIGHT_INDEX]; + uint8_t bits = style->i.bits[MAX_HEIGHT_INDEX]; bits &= MAX_HEIGHT_MASK; bits >>= MAX_HEIGHT_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MAX_HEIGHT_SET) { - *length = style->max_height; + *length = style->i.max_height; *unit = bits >> 2; } @@ -1349,13 +1349,13 @@ static inline uint8_t get_max_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MAX_WIDTH_INDEX]; + uint8_t bits = style->i.bits[MAX_WIDTH_INDEX]; bits &= MAX_WIDTH_MASK; bits >>= MAX_WIDTH_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_MAX_WIDTH_SET) { - *length = style->max_width; + *length = style->i.max_width; *unit = bits >> 2; } @@ -1372,13 +1372,13 @@ static inline uint8_t get_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[WIDTH_INDEX]; + uint8_t bits = style->i.bits[WIDTH_INDEX]; bits &= WIDTH_MASK; bits >>= WIDTH_SHIFT; /* 6bits: uuuutt : units | type */ if ((bits & 0x3) == CSS_WIDTH_SET) { - *length = style->width; + *length = style->i.width; *unit = bits >> 2; } @@ -1394,7 +1394,7 @@ static inline uint8_t get_width( static inline uint8_t get_empty_cells( const css_computed_style *style) { - uint8_t bits = style->bits[EMPTY_CELLS_INDEX]; + uint8_t bits = style->i.bits[EMPTY_CELLS_INDEX]; bits &= EMPTY_CELLS_MASK; bits >>= EMPTY_CELLS_SHIFT; @@ -1411,7 +1411,7 @@ static inline uint8_t get_empty_cells( static inline uint8_t get_float( const css_computed_style *style) { - uint8_t bits = style->bits[FLOAT_INDEX]; + uint8_t bits = style->i.bits[FLOAT_INDEX]; bits &= FLOAT_MASK; bits >>= FLOAT_SHIFT; @@ -1428,7 +1428,7 @@ static inline uint8_t get_float( static inline uint8_t get_font_style( const css_computed_style *style) { - uint8_t bits = style->bits[FONT_STYLE_INDEX]; + uint8_t bits = style->i.bits[FONT_STYLE_INDEX]; bits &= FONT_STYLE_MASK; bits >>= FONT_STYLE_SHIFT; @@ -1446,13 +1446,13 @@ static inline uint8_t get_min_height( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MIN_HEIGHT_INDEX]; + uint8_t bits = style->i.bits[MIN_HEIGHT_INDEX]; bits &= MIN_HEIGHT_MASK; bits >>= MIN_HEIGHT_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_MIN_HEIGHT_SET) { - *length = style->min_height; + *length = style->i.min_height; *unit = bits >> 1; } @@ -1469,13 +1469,13 @@ static inline uint8_t get_min_width( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[MIN_WIDTH_INDEX]; + uint8_t bits = style->i.bits[MIN_WIDTH_INDEX]; bits &= MIN_WIDTH_MASK; bits >>= MIN_WIDTH_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_MIN_WIDTH_SET) { - *length = style->min_width; + *length = style->i.min_width; *unit = bits >> 1; } @@ -1491,7 +1491,7 @@ static inline uint8_t get_min_width( static inline uint8_t get_background_repeat( const css_computed_style *style) { - uint8_t bits = style->bits[BACKGROUND_REPEAT_INDEX]; + uint8_t bits = style->i.bits[BACKGROUND_REPEAT_INDEX]; bits &= BACKGROUND_REPEAT_MASK; bits >>= BACKGROUND_REPEAT_SHIFT; @@ -1508,7 +1508,7 @@ static inline uint8_t get_background_repeat( static inline uint8_t get_clear( const css_computed_style *style) { - uint8_t bits = style->bits[CLEAR_INDEX]; + uint8_t bits = style->i.bits[CLEAR_INDEX]; bits &= CLEAR_MASK; bits >>= CLEAR_SHIFT; @@ -1526,13 +1526,13 @@ static inline uint8_t get_padding_top( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[PADDING_TOP_INDEX]; + uint8_t bits = style->i.bits[PADDING_TOP_INDEX]; bits &= PADDING_TOP_MASK; bits >>= PADDING_TOP_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_PADDING_SET) { - *length = style->padding[0]; + *length = style->i.padding[0]; *unit = bits >> 1; } @@ -1549,13 +1549,13 @@ static inline uint8_t get_padding_right( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[PADDING_RIGHT_INDEX]; + uint8_t bits = style->i.bits[PADDING_RIGHT_INDEX]; bits &= PADDING_RIGHT_MASK; bits >>= PADDING_RIGHT_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_PADDING_SET) { - *length = style->padding[1]; + *length = style->i.padding[1]; *unit = bits >> 1; } @@ -1572,13 +1572,13 @@ static inline uint8_t get_padding_bottom( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[PADDING_BOTTOM_INDEX]; + uint8_t bits = style->i.bits[PADDING_BOTTOM_INDEX]; bits &= PADDING_BOTTOM_MASK; bits >>= PADDING_BOTTOM_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_PADDING_SET) { - *length = style->padding[2]; + *length = style->i.padding[2]; *unit = bits >> 1; } @@ -1595,13 +1595,13 @@ static inline uint8_t get_padding_left( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[PADDING_LEFT_INDEX]; + uint8_t bits = style->i.bits[PADDING_LEFT_INDEX]; bits &= PADDING_LEFT_MASK; bits >>= PADDING_LEFT_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_PADDING_SET) { - *length = style->padding[3]; + *length = style->i.padding[3]; *unit = bits >> 1; } @@ -1617,7 +1617,7 @@ static inline uint8_t get_padding_left( static inline uint8_t get_overflow_x( const css_computed_style *style) { - uint8_t bits = style->bits[OVERFLOW_X_INDEX]; + uint8_t bits = style->i.bits[OVERFLOW_X_INDEX]; bits &= OVERFLOW_X_MASK; bits >>= OVERFLOW_X_SHIFT; @@ -1634,7 +1634,7 @@ static inline uint8_t get_overflow_x( static inline uint8_t get_overflow_y( const css_computed_style *style) { - uint8_t bits = style->bits[OVERFLOW_Y_INDEX]; + uint8_t bits = style->i.bits[OVERFLOW_Y_INDEX]; bits &= OVERFLOW_Y_MASK; bits >>= OVERFLOW_Y_SHIFT; @@ -1651,7 +1651,7 @@ static inline uint8_t get_overflow_y( static inline uint8_t get_position( const css_computed_style *style) { - uint8_t bits = style->bits[POSITION_INDEX]; + uint8_t bits = style->i.bits[POSITION_INDEX]; bits &= POSITION_MASK; bits >>= POSITION_SHIFT; @@ -1669,13 +1669,13 @@ static inline uint8_t get_opacity( const css_computed_style *style, css_fixed *opacity) { - uint8_t bits = style->bits[OPACITY_INDEX]; + uint8_t bits = style->i.bits[OPACITY_INDEX]; bits &= OPACITY_MASK; bits >>= OPACITY_SHIFT; /* 1bit: t : type */ if ((bits & 0x1) == CSS_OPACITY_SET) { - *opacity = style->opacity; + *opacity = style->i.opacity; } return (bits & 0x1); @@ -1690,7 +1690,7 @@ static inline uint8_t get_opacity( static inline uint8_t get_text_transform( const css_computed_style *style) { - uint8_t bits = style->bits[TEXT_TRANSFORM_INDEX]; + uint8_t bits = style->i.bits[TEXT_TRANSFORM_INDEX]; bits &= TEXT_TRANSFORM_MASK; bits >>= TEXT_TRANSFORM_SHIFT; @@ -1708,13 +1708,13 @@ static inline uint8_t get_text_indent( const css_computed_style *style, css_fixed *length, css_unit *unit) { - uint8_t bits = style->bits[TEXT_INDENT_INDEX]; + uint8_t bits = style->i.bits[TEXT_INDENT_INDEX]; bits &= TEXT_INDENT_MASK; bits >>= TEXT_INDENT_SHIFT; /* 5bits: uuuut : units | type */ if ((bits & 0x1) == CSS_TEXT_INDENT_SET) { - *length = style->text_indent; + *length = style->i.text_indent; *unit = bits >> 1; } @@ -1730,7 +1730,7 @@ static inline uint8_t get_text_indent( static inline uint8_t get_white_space( const css_computed_style *style) { - uint8_t bits = style->bits[WHITE_SPACE_INDEX]; + uint8_t bits = style->i.bits[WHITE_SPACE_INDEX]; bits &= WHITE_SPACE_MASK; bits >>= WHITE_SPACE_SHIFT; @@ -1752,21 +1752,21 @@ static inline uint8_t get_background_position( css_fixed *hlength, css_unit *hunit, css_fixed *vlength, css_unit *vunit) { - uint8_t bits = style->bits[BACKGROUND_POSITION_INDEX]; + uint8_t bits = style->i.bits[BACKGROUND_POSITION_INDEX]; bits &= BACKGROUND_POSITION_MASK; bits >>= BACKGROUND_POSITION_SHIFT; /* 1bit: type */ if (bits == CSS_BACKGROUND_POSITION_SET) { - uint8_t bits1 = style->bits[BACKGROUND_POSITION_INDEX1]; + uint8_t bits1 = style->i.bits[BACKGROUND_POSITION_INDEX1]; bits1 &= BACKGROUND_POSITION_MASK1; bits1 >>= BACKGROUND_POSITION_SHIFT1; /* 8bits: hhhhvvvv : hunit | vunit */ - *hlength = style->background_position[0]; + *hlength = style->i.background_position[0]; *hunit = bits1 >> 4; - *vlength = style->background_position[1]; + *vlength = style->i.background_position[1]; *vunit = bits1 & 0xf; } @@ -1785,7 +1785,7 @@ static inline uint8_t get_background_position( static inline uint8_t get_display( const css_computed_style *style) { - uint8_t bits = style->bits[DISPLAY_INDEX]; + uint8_t bits = style->i.bits[DISPLAY_INDEX]; bits &= DISPLAY_MASK; bits >>= DISPLAY_SHIFT; @@ -1802,7 +1802,7 @@ static inline uint8_t get_display( static inline uint8_t get_font_variant( const css_computed_style *style) { - uint8_t bits = style->bits[FONT_VARIANT_INDEX]; + uint8_t bits = style->i.bits[FONT_VARIANT_INDEX]; bits &= FONT_VARIANT_MASK; bits >>= FONT_VARIANT_SHIFT; @@ -1819,7 +1819,7 @@ static inline uint8_t get_font_variant( static inline uint8_t get_text_decoration( const css_computed_style *style) { - uint8_t bits = style->bits[TEXT_DECORATION_INDEX]; + uint8_t bits = style->i.bits[TEXT_DECORATION_INDEX]; bits &= TEXT_DECORATION_MASK; bits >>= TEXT_DECORATION_SHIFT; @@ -1837,7 +1837,7 @@ static inline uint8_t get_font_family( const css_computed_style *style, lwc_string ***names) { - uint8_t bits = style->bits[FONT_FAMILY_INDEX]; + uint8_t bits = style->i.bits[FONT_FAMILY_INDEX]; bits &= FONT_FAMILY_MASK; bits >>= FONT_FAMILY_SHIFT; @@ -1856,7 +1856,7 @@ static inline uint8_t get_font_family( static inline uint8_t get_border_top_style( const css_computed_style *style) { - uint8_t bits = style->bits[BORDER_TOP_STYLE_INDEX]; + uint8_t bits = style->i.bits[BORDER_TOP_STYLE_INDEX]; bits &= BORDER_TOP_STYLE_MASK; bits >>= BORDER_TOP_STYLE_SHIFT; @@ -1873,7 +1873,7 @@ static inline uint8_t get_border_top_style( static inline uint8_t get_border_right_style( const css_computed_style *style) { - uint8_t bits = style->bits[BORDER_RIGHT_STYLE_INDEX]; + uint8_t bits = style->i.bits[BORDER_RIGHT_STYLE_INDEX]; bits &= BORDER_RIGHT_STYLE_MASK; bits >>= BORDER_RIGHT_STYLE_SHIFT; @@ -1890,7 +1890,7 @@ static inline uint8_t get_border_right_style( static inline uint8_t get_border_bottom_style( const css_computed_style *style) { - uint8_t bits = style->bits[BORDER_BOTTOM_STYLE_INDEX]; + uint8_t bits = style->i.bits[BORDER_BOTTOM_STYLE_INDEX]; bits &= BORDER_BOTTOM_STYLE_MASK; bits >>= BORDER_BOTTOM_STYLE_SHIFT; @@ -1907,7 +1907,7 @@ static inline uint8_t get_border_bottom_style( static inline uint8_t get_border_left_style( const css_computed_style *style) { - uint8_t bits = style->bits[BORDER_LEFT_STYLE_INDEX]; + uint8_t bits = style->i.bits[BORDER_LEFT_STYLE_INDEX]; bits &= BORDER_LEFT_STYLE_MASK; bits >>= BORDER_LEFT_STYLE_SHIFT; @@ -1924,7 +1924,7 @@ static inline uint8_t get_border_left_style( static inline uint8_t get_font_weight( const css_computed_style *style) { - uint8_t bits = style->bits[FONT_WEIGHT_INDEX]; + uint8_t bits = style->i.bits[FONT_WEIGHT_INDEX]; bits &= FONT_WEIGHT_MASK; bits >>= FONT_WEIGHT_SHIFT; @@ -1941,7 +1941,7 @@ static inline uint8_t get_font_weight( static inline uint8_t get_list_style_type( const css_computed_style *style) { - uint8_t bits = style->bits[LIST_STYLE_TYPE_INDEX]; + uint8_t bits = style->i.bits[LIST_STYLE_TYPE_INDEX]; bits &= LIST_STYLE_TYPE_MASK; bits >>= LIST_STYLE_TYPE_SHIFT; @@ -1958,7 +1958,7 @@ static inline uint8_t get_list_style_type( static inline uint8_t get_outline_style( const css_computed_style *style) { - uint8_t bits = style->bits[OUTLINE_STYLE_INDEX]; + uint8_t bits = style->i.bits[OUTLINE_STYLE_INDEX]; bits &= OUTLINE_STYLE_MASK; bits >>= OUTLINE_STYLE_SHIFT; @@ -1975,7 +1975,7 @@ static inline uint8_t get_outline_style( static inline uint8_t get_table_layout( const css_computed_style *style) { - uint8_t bits = style->bits[TABLE_LAYOUT_INDEX]; + uint8_t bits = style->i.bits[TABLE_LAYOUT_INDEX]; bits &= TABLE_LAYOUT_MASK; bits >>= TABLE_LAYOUT_SHIFT; @@ -1992,7 +1992,7 @@ static inline uint8_t get_table_layout( static inline uint8_t get_unicode_bidi( const css_computed_style *style) { - uint8_t bits = style->bits[UNICODE_BIDI_INDEX]; + uint8_t bits = style->i.bits[UNICODE_BIDI_INDEX]; bits &= UNICODE_BIDI_MASK; bits >>= UNICODE_BIDI_SHIFT; @@ -2009,7 +2009,7 @@ static inline uint8_t get_unicode_bidi( static inline uint8_t get_visibility( const css_computed_style *style) { - uint8_t bits = style->bits[VISIBILITY_INDEX]; + uint8_t bits = style->i.bits[VISIBILITY_INDEX]; bits &= VISIBILITY_MASK; bits >>= VISIBILITY_SHIFT; @@ -2026,7 +2026,7 @@ static inline uint8_t get_visibility( static inline uint8_t get_list_style_position( const css_computed_style *style) { - uint8_t bits = style->bits[LIST_STYLE_POSITION_INDEX]; + uint8_t bits = style->i.bits[LIST_STYLE_POSITION_INDEX]; bits &= LIST_STYLE_POSITION_MASK; bits >>= LIST_STYLE_POSITION_SHIFT; @@ -2043,7 +2043,7 @@ static inline uint8_t get_list_style_position( static inline uint8_t get_text_align( const css_computed_style *style) { - uint8_t bits = style->bits[TEXT_ALIGN_INDEX]; + uint8_t bits = style->i.bits[TEXT_ALIGN_INDEX]; bits &= TEXT_ALIGN_MASK; bits >>= TEXT_ALIGN_SHIFT; diff --git a/src/select/propset.h b/src/select/propset.h index 928b9e3..76e4fe6 100644 --- a/src/select/propset.h +++ b/src/select/propset.h @@ -19,54 +19,60 @@ /** Default values are 'initial value', unless the property is inherited, * in which case it is 'inherit'. */ static const css_computed_uncommon default_uncommon = { - .bits = { - (CSS_LETTER_SPACING_INHERIT << 2) | - CSS_OUTLINE_COLOR_INVERT, - (CSS_OUTLINE_WIDTH_MEDIUM << 1) | - CSS_BORDER_SPACING_INHERIT, - 0, - (CSS_WORD_SPACING_INHERIT << 2) | - (CSS_COUNTER_INCREMENT_NONE << 1) | - CSS_COUNTER_RESET_NONE, - (CSS_CURSOR_INHERIT << 3) | - (CSS_WRITING_MODE_INHERIT << 1), - 0, - 0, - (CSS_CLIP_AUTO << 2) | CSS_CONTENT_NORMAL, - (CSS_COLUMN_COUNT_AUTO << 6) | - (CSS_COLUMN_FILL_BALANCE << 4) | - (CSS_COLUMN_RULE_STYLE_NONE << 0), - (CSS_COLUMN_GAP_NORMAL << 2) | - (CSS_COLUMN_RULE_COLOR_CURRENT_COLOR), - (CSS_COLUMN_RULE_WIDTH_MEDIUM << 1), - (CSS_COLUMN_SPAN_NONE << 6) | CSS_COLUMN_WIDTH_AUTO, - (CSS_BREAK_BEFORE_AUTO << 4) | CSS_BREAK_AFTER_AUTO, - (CSS_BREAK_INSIDE_AUTO) + .i = { + .bits = { + (CSS_LETTER_SPACING_INHERIT << 2) | + CSS_OUTLINE_COLOR_INVERT, + (CSS_OUTLINE_WIDTH_MEDIUM << 1) | + CSS_BORDER_SPACING_INHERIT, + 0, + (CSS_WORD_SPACING_INHERIT << 2) | + (CSS_COUNTER_INCREMENT_NONE << 1) | + CSS_COUNTER_RESET_NONE, + (CSS_CURSOR_INHERIT << 3) | + (CSS_WRITING_MODE_INHERIT << 1), + 0, + 0, + (CSS_CLIP_AUTO << 2) | CSS_CONTENT_NORMAL, + (CSS_COLUMN_COUNT_AUTO << 6) | + (CSS_COLUMN_FILL_BALANCE << 4) | + (CSS_COLUMN_RULE_STYLE_NONE << 0), + (CSS_COLUMN_GAP_NORMAL << 2) | + (CSS_COLUMN_RULE_COLOR_CURRENT_COLOR), + (CSS_COLUMN_RULE_WIDTH_MEDIUM << 1), + (CSS_COLUMN_SPAN_NONE << 6) | CSS_COLUMN_WIDTH_AUTO, + (CSS_BREAK_BEFORE_AUTO << 4) | CSS_BREAK_AFTER_AUTO, + (CSS_BREAK_INSIDE_AUTO) + }, + .border_spacing = { 0, 0 }, + .clip = { 0, 0, 0, 0 }, + .letter_spacing = 0, + .outline_color = 0x0, + .outline_width = 0, + .word_spacing = 0, + .column_count = 0, + .column_gap = 0, + .column_rule_color = 0, + .column_rule_width = 0, + .column_width = 0 }, - .border_spacing = { 0, 0 }, - .clip = { 0, 0, 0, 0 }, - .letter_spacing = 0, - .outline_color = 0x0, - .outline_width = 0, - .word_spacing = 0, - .column_count = 0, - .column_gap = 0, - .column_rule_color = 0, - .column_rule_width = 0, - .column_width = 0, .counter_increment = NULL, .counter_reset = NULL, .content = NULL, - .cursor = NULL + .cursor = NULL, + .next = NULL, + .count = 0, + .bin = UINT32_MAX }; #define ENSURE_UNCOMMON do { \ - if (style->uncommon == NULL) { \ - style->uncommon = malloc(sizeof(css_computed_uncommon));\ - if (style->uncommon == NULL) \ + if (style->i.uncommon == NULL) { \ + style->i.uncommon = malloc( \ + sizeof(css_computed_uncommon)); \ + if (style->i.uncommon == NULL) \ return CSS_NOMEM; \ \ - memcpy(style->uncommon, &default_uncommon, \ + memcpy(style->i.uncommon, &default_uncommon, \ sizeof(css_computed_uncommon)); \ } \ } while(0) @@ -105,13 +111,13 @@ static inline css_error set_letter_spacing( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[LETTER_SPACING_INDEX]; + bits = &style->i.uncommon->i.bits[LETTER_SPACING_INDEX]; /* 6bits: uuuutt : unit | type */ *bits = (*bits & ~LETTER_SPACING_MASK) | (((type & 0x3) | unit << 2) << LETTER_SPACING_SHIFT); - style->uncommon->letter_spacing = length; + style->i.uncommon->i.letter_spacing = length; return CSS_OK; } @@ -129,13 +135,13 @@ static inline css_error set_outline_color( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[OUTLINE_COLOR_INDEX]; + bits = &style->i.uncommon->i.bits[OUTLINE_COLOR_INDEX]; /* 2bits: tt : type */ *bits = (*bits & ~OUTLINE_COLOR_MASK) | ((type & 0x3) << OUTLINE_COLOR_SHIFT); - style->uncommon->outline_color = color; + style->i.uncommon->i.outline_color = color; return CSS_OK; } @@ -154,13 +160,13 @@ static inline css_error set_outline_width( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[OUTLINE_WIDTH_INDEX]; + bits = &style->i.uncommon->i.bits[OUTLINE_WIDTH_INDEX]; /* 7bits: uuuuttt : unit | type */ *bits = (*bits & ~OUTLINE_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << OUTLINE_WIDTH_SHIFT); - style->uncommon->outline_width = length; + style->i.uncommon->i.outline_width = length; return CSS_OK; } @@ -182,20 +188,20 @@ static inline css_error set_border_spacing( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[BORDER_SPACING_INDEX]; + bits = &style->i.uncommon->i.bits[BORDER_SPACING_INDEX]; /* 1 bit: type */ *bits = (*bits & ~BORDER_SPACING_MASK) | ((type & 0x1) << BORDER_SPACING_SHIFT); - bits = &style->uncommon->bits[BORDER_SPACING_INDEX1]; + bits = &style->i.uncommon->i.bits[BORDER_SPACING_INDEX1]; /* 8bits: hhhhvvvv : hunit | vunit */ *bits = (((hunit << 4) | vunit) << BORDER_SPACING_SHIFT1); - style->uncommon->border_spacing[0] = hlength; - style->uncommon->border_spacing[1] = vlength; + style->i.uncommon->i.border_spacing[0] = hlength; + style->i.uncommon->i.border_spacing[1] = vlength; return CSS_OK; } @@ -215,7 +221,7 @@ static inline css_error set_break_after( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[BREAK_AFTER_INDEX]; + bits = &style->i.uncommon->i.bits[BREAK_AFTER_INDEX]; /* 4bits: type */ *bits = (*bits & ~BREAK_AFTER_MASK) | @@ -237,7 +243,7 @@ static inline css_error set_break_before( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[BREAK_BEFORE_INDEX]; + bits = &style->i.uncommon->i.bits[BREAK_BEFORE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BREAK_BEFORE_MASK) | @@ -259,7 +265,7 @@ static inline css_error set_break_inside( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[BREAK_INSIDE_INDEX]; + bits = &style->i.uncommon->i.bits[BREAK_INSIDE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BREAK_INSIDE_MASK) | @@ -282,13 +288,13 @@ static inline css_error set_word_spacing( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[WORD_SPACING_INDEX]; + bits = &style->i.uncommon->i.bits[WORD_SPACING_INDEX]; /* 6bits: uuuutt : unit | type */ *bits = (*bits & ~WORD_SPACING_MASK) | (((type & 0x3) | (unit << 2)) << WORD_SPACING_SHIFT); - style->uncommon->word_spacing = length; + style->i.uncommon->i.word_spacing = length; return CSS_OK; } @@ -306,7 +312,7 @@ static inline css_error set_writing_mode( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[WRITING_MODE_INDEX]; + bits = &style->i.uncommon->i.bits[WRITING_MODE_INDEX]; /* 2bits: type */ *bits = (*bits & ~WRITING_MODE_MASK) | @@ -331,8 +337,8 @@ static inline css_error set_counter_increment( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COUNTER_INCREMENT_INDEX]; - oldcounters = style->uncommon->counter_increment; + bits = &style->i.uncommon->i.bits[COUNTER_INCREMENT_INDEX]; + oldcounters = style->i.uncommon->counter_increment; /* 1bit: type */ *bits = (*bits & ~COUNTER_INCREMENT_MASK) | @@ -341,7 +347,7 @@ static inline css_error set_counter_increment( for (c = counters; c != NULL && c->name != NULL; c++) c->name = lwc_string_ref(c->name); - style->uncommon->counter_increment = counters; + style->i.uncommon->counter_increment = counters; /* Free existing array */ if (oldcounters != NULL) { @@ -371,8 +377,8 @@ static inline css_error set_counter_reset( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COUNTER_RESET_INDEX]; - oldcounters = style->uncommon->counter_reset; + bits = &style->i.uncommon->i.bits[COUNTER_RESET_INDEX]; + oldcounters = style->i.uncommon->counter_reset; /* 1bit: type */ *bits = (*bits & ~COUNTER_RESET_MASK) | @@ -381,7 +387,7 @@ static inline css_error set_counter_reset( for (c = counters; c != NULL && c->name != NULL; c++) c->name = lwc_string_ref(c->name); - style->uncommon->counter_reset = counters; + style->i.uncommon->counter_reset = counters; /* Free existing array */ if (oldcounters != NULL) { @@ -411,8 +417,8 @@ static inline css_error set_cursor( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[CURSOR_INDEX]; - oldurls = style->uncommon->cursor; + bits = &style->i.uncommon->i.bits[CURSOR_INDEX]; + oldurls = style->i.uncommon->cursor; /* 5bits: type */ *bits = (*bits & ~CURSOR_MASK) | @@ -421,7 +427,7 @@ static inline css_error set_cursor( for (s = urls; s != NULL && *s != NULL; s++) *s = lwc_string_ref(*s); - style->uncommon->cursor = urls; + style->i.uncommon->cursor = urls; /* Free existing array */ if (oldurls != NULL) { @@ -453,7 +459,7 @@ static inline css_error set_clip( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[CLIP_INDEX]; + bits = &style->i.uncommon->i.bits[CLIP_INDEX]; /* 6bits: trblyy : top | right | bottom | left | type */ *bits = (*bits & ~CLIP_MASK) | @@ -465,20 +471,20 @@ static inline css_error set_clip( (rect->bottom_auto ? 0x8 : 0) | (rect->left_auto ? 0x4 : 0)) << CLIP_SHIFT); - bits = &style->uncommon->bits[CLIP_INDEX1]; + bits = &style->i.uncommon->i.bits[CLIP_INDEX1]; /* 8bits: ttttrrrr : top | right */ *bits = (((rect->tunit << 4) | rect->runit) << CLIP_SHIFT1); - bits = &style->uncommon->bits[CLIP_INDEX2]; + bits = &style->i.uncommon->i.bits[CLIP_INDEX2]; /* 8bits: bbbbllll : bottom | left */ *bits = (((rect->bunit << 4) | rect->lunit) << CLIP_SHIFT2); - style->uncommon->clip[0] = rect->top; - style->uncommon->clip[1] = rect->right; - style->uncommon->clip[2] = rect->bottom; - style->uncommon->clip[3] = rect->left; + style->i.uncommon->i.clip[0] = rect->top; + style->i.uncommon->i.clip[1] = rect->right; + style->i.uncommon->i.clip[2] = rect->bottom; + style->i.uncommon->i.clip[3] = rect->left; } return CSS_OK; @@ -501,13 +507,13 @@ static inline css_error set_column_count( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_COUNT_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_COUNT_INDEX]; /* 2bits: tt : type */ *bits = (*bits & ~COLUMN_COUNT_MASK) | ((type & 0x3) << COLUMN_COUNT_SHIFT); - style->uncommon->column_count = count; + style->i.uncommon->i.column_count = count; return CSS_OK; } @@ -525,7 +531,7 @@ static inline css_error set_column_fill( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_FILL_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_FILL_INDEX]; /* 2bits: tt : type */ *bits = (*bits & ~COLUMN_FILL_MASK) | @@ -548,13 +554,13 @@ static inline css_error set_column_gap( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_GAP_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_GAP_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~COLUMN_GAP_MASK) | (((type & 0x3) | (unit << 2)) << COLUMN_GAP_SHIFT); - style->uncommon->column_gap = length; + style->i.uncommon->i.column_gap = length; return CSS_OK; } @@ -573,13 +579,13 @@ static inline css_error set_column_rule_color( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_RULE_COLOR_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_RULE_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~COLUMN_RULE_COLOR_MASK) | ((type & 0x3) << COLUMN_RULE_COLOR_SHIFT); - style->uncommon->column_rule_color = color; + style->i.uncommon->i.column_rule_color = color; return CSS_OK; } @@ -597,7 +603,7 @@ static inline css_error set_column_rule_style( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_RULE_STYLE_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_RULE_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~COLUMN_RULE_STYLE_MASK) | @@ -620,13 +626,13 @@ static inline css_error set_column_rule_width( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_RULE_WIDTH_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_RULE_WIDTH_INDEX]; /* 7bits: uuuuttt : units | type */ *bits = (*bits & ~COLUMN_RULE_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << COLUMN_RULE_WIDTH_SHIFT); - style->uncommon->column_rule_width = length; + style->i.uncommon->i.column_rule_width = length; return CSS_OK; } @@ -644,7 +650,7 @@ static inline css_error set_column_span( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_SPAN_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_SPAN_INDEX]; /* 2bits: tt : type */ *bits = (*bits & ~COLUMN_SPAN_MASK) | @@ -667,13 +673,13 @@ static inline css_error set_column_width( ENSURE_UNCOMMON; - bits = &style->uncommon->bits[COLUMN_WIDTH_INDEX]; + bits = &style->i.uncommon->i.bits[COLUMN_WIDTH_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~COLUMN_WIDTH_MASK) | (((type & 0x3) | (unit << 2)) << COLUMN_WIDTH_SHIFT); - style->uncommon->column_width = length; + style->i.uncommon->i.column_width = length; return CSS_OK; } @@ -695,8 +701,8 @@ static inline css_error set_content( ENSURE_UNCOMMON; /* 2bits: type */ - bits = &style->uncommon->bits[CONTENT_INDEX]; - oldcontent = style->uncommon->content; + bits = &style->i.uncommon->i.bits[CONTENT_INDEX]; + oldcontent = style->i.uncommon->content; *bits = (*bits & ~CONTENT_MASK) | ((type & 0x3) << CONTENT_SHIFT); @@ -728,7 +734,7 @@ static inline css_error set_content( } } - style->uncommon->content = content; + style->i.uncommon->content = content; /* Free existing array */ if (oldcontent != NULL) { @@ -773,12 +779,12 @@ static inline css_error set_vertical_align( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[VERTICAL_ALIGN_INDEX]; + uint8_t *bits = &style->i.bits[VERTICAL_ALIGN_INDEX]; /* 8bits: uuuutttt : units | type */ *bits = (((type & 0xf) | (unit << 4)) << VERTICAL_ALIGN_SHIFT); - style->vertical_align = length; + style->i.vertical_align = length; return CSS_OK; } @@ -791,12 +797,12 @@ static inline css_error set_font_size( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[FONT_SIZE_INDEX]; + uint8_t *bits = &style->i.bits[FONT_SIZE_INDEX]; /* 8bits: uuuutttt : units | type */ *bits = (((type & 0xf) | (unit << 4)) << FONT_SIZE_SHIFT); - style->font_size = length; + style->i.font_size = length; return CSS_OK; } @@ -810,13 +816,13 @@ static inline css_error set_border_top_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[BORDER_TOP_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_TOP_WIDTH_INDEX]; /* 7bits: uuuuttt : units | type */ *bits = (*bits & ~BORDER_TOP_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << BORDER_TOP_WIDTH_SHIFT); - style->border_width[0] = length; + style->i.border_width[0] = length; return CSS_OK; } @@ -831,13 +837,13 @@ static inline css_error set_border_right_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[BORDER_RIGHT_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_RIGHT_WIDTH_INDEX]; /* 7bits: uuuuttt : units | type */ *bits = (*bits & ~BORDER_RIGHT_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << BORDER_RIGHT_WIDTH_SHIFT); - style->border_width[1] = length; + style->i.border_width[1] = length; return CSS_OK; } @@ -852,13 +858,13 @@ static inline css_error set_border_bottom_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[BORDER_BOTTOM_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_BOTTOM_WIDTH_INDEX]; /* 7bits: uuuuttt : units | type */ *bits = (*bits & ~BORDER_BOTTOM_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << BORDER_BOTTOM_WIDTH_SHIFT); - style->border_width[2] = length; + style->i.border_width[2] = length; return CSS_OK; } @@ -873,13 +879,13 @@ static inline css_error set_border_left_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[BORDER_LEFT_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_LEFT_WIDTH_INDEX]; /* 7bits: uuuuttt : units | type */ *bits = (*bits & ~BORDER_LEFT_WIDTH_MASK) | (((type & 0x7) | (unit << 3)) << BORDER_LEFT_WIDTH_SHIFT); - style->border_width[3] = length; + style->i.border_width[3] = length; return CSS_OK; } @@ -894,17 +900,17 @@ static inline css_error set_background_image( css_computed_style *style, uint8_t type, lwc_string *url) { - uint8_t *bits = &style->bits[BACKGROUND_IMAGE_INDEX]; - lwc_string *oldurl = style->background_image; + uint8_t *bits = &style->i.bits[BACKGROUND_IMAGE_INDEX]; + lwc_string *oldurl = style->i.background_image; /* 1bit: type */ *bits = (*bits & ~BACKGROUND_IMAGE_MASK) | ((type & 0x1) << BACKGROUND_IMAGE_SHIFT); if (url != NULL) { - style->background_image = lwc_string_ref(url); + style->i.background_image = lwc_string_ref(url); } else { - style->background_image = NULL; + style->i.background_image = NULL; } if (oldurl != NULL) @@ -923,13 +929,13 @@ static inline css_error set_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[COLOR_INDEX]; + uint8_t *bits = &style->i.bits[COLOR_INDEX]; /* 1bit: type */ *bits = (*bits & ~COLOR_MASK) | ((type & 0x1) << COLOR_SHIFT); - style->color = color; + style->i.color = color; return CSS_OK; } @@ -944,17 +950,17 @@ static inline css_error set_list_style_image( css_computed_style *style, uint8_t type, lwc_string *url) { - uint8_t *bits = &style->bits[LIST_STYLE_IMAGE_INDEX]; - lwc_string *oldurl = style->list_style_image; + uint8_t *bits = &style->i.bits[LIST_STYLE_IMAGE_INDEX]; + lwc_string *oldurl = style->i.list_style_image; /* 1bit: type */ *bits = (*bits & ~LIST_STYLE_IMAGE_MASK) | ((type & 0x1) << LIST_STYLE_IMAGE_SHIFT); if (url != NULL) { - style->list_style_image = lwc_string_ref(url); + style->i.list_style_image = lwc_string_ref(url); } else { - style->list_style_image = NULL; + style->i.list_style_image = NULL; } if (oldurl != NULL) @@ -973,7 +979,7 @@ static inline css_error set_quotes( css_computed_style *style, uint8_t type, lwc_string **quotes) { - uint8_t *bits = &style->bits[QUOTES_INDEX]; + uint8_t *bits = &style->i.bits[QUOTES_INDEX]; lwc_string **oldquotes = style->quotes; lwc_string **s; @@ -1008,13 +1014,13 @@ static inline css_error set_top( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[TOP_INDEX]; + uint8_t *bits = &style->i.bits[TOP_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~TOP_MASK) | (((type & 0x3) | (unit << 2)) << TOP_SHIFT); - style->top = length; + style->i.top = length; return CSS_OK; } @@ -1029,13 +1035,13 @@ static inline css_error set_right( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[RIGHT_INDEX]; + uint8_t *bits = &style->i.bits[RIGHT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~RIGHT_MASK) | (((type & 0x3) | (unit << 2)) << RIGHT_SHIFT); - style->right = length; + style->i.right = length; return CSS_OK; } @@ -1050,13 +1056,13 @@ static inline css_error set_bottom( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[BOTTOM_INDEX]; + uint8_t *bits = &style->i.bits[BOTTOM_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~BOTTOM_MASK) | (((type & 0x3) | (unit << 2)) << BOTTOM_SHIFT); - style->bottom = length; + style->i.bottom = length; return CSS_OK; } @@ -1071,13 +1077,13 @@ static inline css_error set_left( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[LEFT_INDEX]; + uint8_t *bits = &style->i.bits[LEFT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~LEFT_MASK) | (((type & 0x3) | (unit << 2)) << LEFT_SHIFT); - style->left = length; + style->i.left = length; return CSS_OK; } @@ -1092,13 +1098,13 @@ static inline css_error set_border_top_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[BORDER_TOP_COLOR_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_TOP_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~BORDER_TOP_COLOR_MASK) | ((type & 0x3) << BORDER_TOP_COLOR_SHIFT); - style->border_color[0] = color; + style->i.border_color[0] = color; return CSS_OK; } @@ -1113,13 +1119,13 @@ static inline css_error set_border_right_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[BORDER_RIGHT_COLOR_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_RIGHT_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~BORDER_RIGHT_COLOR_MASK) | ((type & 0x3) << BORDER_RIGHT_COLOR_SHIFT); - style->border_color[1] = color; + style->i.border_color[1] = color; return CSS_OK; } @@ -1134,13 +1140,13 @@ static inline css_error set_border_bottom_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[BORDER_BOTTOM_COLOR_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_BOTTOM_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~BORDER_BOTTOM_COLOR_MASK) | ((type & 0x3) << BORDER_BOTTOM_COLOR_SHIFT); - style->border_color[2] = color; + style->i.border_color[2] = color; return CSS_OK; } @@ -1155,13 +1161,13 @@ static inline css_error set_border_left_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[BORDER_LEFT_COLOR_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_LEFT_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~BORDER_LEFT_COLOR_MASK) | ((type & 0x3) << BORDER_LEFT_COLOR_SHIFT); - style->border_color[3] = color; + style->i.border_color[3] = color; return CSS_OK; } @@ -1176,13 +1182,13 @@ static inline css_error set_height( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[HEIGHT_INDEX]; + uint8_t *bits = &style->i.bits[HEIGHT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~HEIGHT_MASK) | (((type & 0x3) | (unit << 2)) << HEIGHT_SHIFT); - style->height = length; + style->i.height = length; return CSS_OK; } @@ -1197,13 +1203,13 @@ static inline css_error set_line_height( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[LINE_HEIGHT_INDEX]; + uint8_t *bits = &style->i.bits[LINE_HEIGHT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~LINE_HEIGHT_MASK) | (((type & 0x3) | (unit << 2)) << LINE_HEIGHT_SHIFT); - style->line_height = length; + style->i.line_height = length; return CSS_OK; } @@ -1218,13 +1224,13 @@ static inline css_error set_background_color( css_computed_style *style, uint8_t type, css_color color) { - uint8_t *bits = &style->bits[BACKGROUND_COLOR_INDEX]; + uint8_t *bits = &style->i.bits[BACKGROUND_COLOR_INDEX]; /* 2bits: type */ *bits = (*bits & ~BACKGROUND_COLOR_MASK) | ((type & 0x3) << BACKGROUND_COLOR_SHIFT); - style->background_color = color; + style->i.background_color = color; return CSS_OK; } @@ -1239,13 +1245,13 @@ static inline css_error set_z_index( css_computed_style *style, uint8_t type, int32_t z_index) { - uint8_t *bits = &style->bits[Z_INDEX_INDEX]; + uint8_t *bits = &style->i.bits[Z_INDEX_INDEX]; /* 2bits: type */ *bits = (*bits & ~Z_INDEX_MASK) | ((type & 0x3) << Z_INDEX_SHIFT); - style->z_index = z_index; + style->i.z_index = z_index; return CSS_OK; } @@ -1260,13 +1266,13 @@ static inline css_error set_margin_top( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MARGIN_TOP_INDEX]; + uint8_t *bits = &style->i.bits[MARGIN_TOP_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MARGIN_TOP_MASK) | (((type & 0x3) | (unit << 2)) << MARGIN_TOP_SHIFT); - style->margin[0] = length; + style->i.margin[0] = length; return CSS_OK; } @@ -1281,13 +1287,13 @@ static inline css_error set_margin_right( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MARGIN_RIGHT_INDEX]; + uint8_t *bits = &style->i.bits[MARGIN_RIGHT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MARGIN_RIGHT_MASK) | (((type & 0x3) | (unit << 2)) << MARGIN_RIGHT_SHIFT); - style->margin[1] = length; + style->i.margin[1] = length; return CSS_OK; } @@ -1302,13 +1308,13 @@ static inline css_error set_margin_bottom( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MARGIN_BOTTOM_INDEX]; + uint8_t *bits = &style->i.bits[MARGIN_BOTTOM_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MARGIN_BOTTOM_MASK) | (((type & 0x3) | (unit << 2)) << MARGIN_BOTTOM_SHIFT); - style->margin[2] = length; + style->i.margin[2] = length; return CSS_OK; } @@ -1323,13 +1329,13 @@ static inline css_error set_margin_left( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MARGIN_LEFT_INDEX]; + uint8_t *bits = &style->i.bits[MARGIN_LEFT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MARGIN_LEFT_MASK) | (((type & 0x3) | (unit << 2)) << MARGIN_LEFT_SHIFT); - style->margin[3] = length; + style->i.margin[3] = length; return CSS_OK; } @@ -1343,7 +1349,7 @@ static inline css_error set_margin_left( static inline css_error set_background_attachment( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BACKGROUND_ATTACHMENT_INDEX]; + uint8_t *bits = &style->i.bits[BACKGROUND_ATTACHMENT_INDEX]; /* 2bits: type */ *bits = (*bits & ~BACKGROUND_ATTACHMENT_MASK) | @@ -1361,7 +1367,7 @@ static inline css_error set_background_attachment( static inline css_error set_border_collapse( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BORDER_COLLAPSE_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_COLLAPSE_INDEX]; /* 2bits: type */ *bits = (*bits & ~BORDER_COLLAPSE_MASK) | @@ -1379,7 +1385,7 @@ static inline css_error set_border_collapse( static inline css_error set_caption_side( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[CAPTION_SIDE_INDEX]; + uint8_t *bits = &style->i.bits[CAPTION_SIDE_INDEX]; /* 2bits: type */ *bits = (*bits & ~CAPTION_SIDE_MASK) | @@ -1397,7 +1403,7 @@ static inline css_error set_caption_side( static inline css_error set_direction( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[DIRECTION_INDEX]; + uint8_t *bits = &style->i.bits[DIRECTION_INDEX]; /* 2bits: type */ *bits = (*bits & ~DIRECTION_MASK) | @@ -1416,13 +1422,13 @@ static inline css_error set_max_height( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MAX_HEIGHT_INDEX]; + uint8_t *bits = &style->i.bits[MAX_HEIGHT_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MAX_HEIGHT_MASK) | (((type & 0x3) | (unit << 2)) << MAX_HEIGHT_SHIFT); - style->max_height = length; + style->i.max_height = length; return CSS_OK; } @@ -1437,13 +1443,13 @@ static inline css_error set_max_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MAX_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[MAX_WIDTH_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~MAX_WIDTH_MASK) | (((type & 0x3) | (unit << 2)) << MAX_WIDTH_SHIFT); - style->max_width = length; + style->i.max_width = length; return CSS_OK; } @@ -1458,13 +1464,13 @@ static inline css_error set_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[WIDTH_INDEX]; /* 6bits: uuuutt : units | type */ *bits = (*bits & ~WIDTH_MASK) | (((type & 0x3) | (unit << 2)) << WIDTH_SHIFT); - style->width = length; + style->i.width = length; return CSS_OK; } @@ -1478,7 +1484,7 @@ static inline css_error set_width( static inline css_error set_empty_cells( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[EMPTY_CELLS_INDEX]; + uint8_t *bits = &style->i.bits[EMPTY_CELLS_INDEX]; /* 2bits: type */ *bits = (*bits & ~EMPTY_CELLS_MASK) | @@ -1496,7 +1502,7 @@ static inline css_error set_empty_cells( static inline css_error set_float( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[FLOAT_INDEX]; + uint8_t *bits = &style->i.bits[FLOAT_INDEX]; /* 2bits: type */ *bits = (*bits & ~FLOAT_MASK) | @@ -1514,7 +1520,7 @@ static inline css_error set_float( static inline css_error set_font_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[FONT_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[FONT_STYLE_INDEX]; /* 2bits: type */ *bits = (*bits & ~FONT_STYLE_MASK) | @@ -1533,13 +1539,13 @@ static inline css_error set_min_height( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MIN_HEIGHT_INDEX]; + uint8_t *bits = &style->i.bits[MIN_HEIGHT_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~MIN_HEIGHT_MASK) | (((type & 0x1) | (unit << 1)) << MIN_HEIGHT_SHIFT); - style->min_height = length; + style->i.min_height = length; return CSS_OK; } @@ -1554,13 +1560,13 @@ static inline css_error set_min_width( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[MIN_WIDTH_INDEX]; + uint8_t *bits = &style->i.bits[MIN_WIDTH_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~MIN_WIDTH_MASK) | (((type & 0x1) | (unit << 1)) << MIN_WIDTH_SHIFT); - style->min_width = length; + style->i.min_width = length; return CSS_OK; } @@ -1574,7 +1580,7 @@ static inline css_error set_min_width( static inline css_error set_background_repeat( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BACKGROUND_REPEAT_INDEX]; + uint8_t *bits = &style->i.bits[BACKGROUND_REPEAT_INDEX]; /* 3bits: type */ *bits = (*bits & ~BACKGROUND_REPEAT_MASK) | @@ -1592,7 +1598,7 @@ static inline css_error set_background_repeat( static inline css_error set_clear( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[CLEAR_INDEX]; + uint8_t *bits = &style->i.bits[CLEAR_INDEX]; /* 3bits: type */ *bits = (*bits & ~CLEAR_MASK) | @@ -1611,13 +1617,13 @@ static inline css_error set_padding_top( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[PADDING_TOP_INDEX]; + uint8_t *bits = &style->i.bits[PADDING_TOP_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~PADDING_TOP_MASK) | (((type & 0x1) | (unit << 1)) << PADDING_TOP_SHIFT); - style->padding[0] = length; + style->i.padding[0] = length; return CSS_OK; } @@ -1632,13 +1638,13 @@ static inline css_error set_padding_right( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[PADDING_RIGHT_INDEX]; + uint8_t *bits = &style->i.bits[PADDING_RIGHT_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~PADDING_RIGHT_MASK) | (((type & 0x1) | (unit << 1)) << PADDING_RIGHT_SHIFT); - style->padding[1] = length; + style->i.padding[1] = length; return CSS_OK; } @@ -1653,13 +1659,13 @@ static inline css_error set_padding_bottom( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[PADDING_BOTTOM_INDEX]; + uint8_t *bits = &style->i.bits[PADDING_BOTTOM_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~PADDING_BOTTOM_MASK) | (((type & 0x1) | (unit << 1)) << PADDING_BOTTOM_SHIFT); - style->padding[2] = length; + style->i.padding[2] = length; return CSS_OK; } @@ -1674,13 +1680,13 @@ static inline css_error set_padding_left( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[PADDING_LEFT_INDEX]; + uint8_t *bits = &style->i.bits[PADDING_LEFT_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~PADDING_LEFT_MASK) | (((type & 0x1) | (unit << 1)) << PADDING_LEFT_SHIFT); - style->padding[3] = length; + style->i.padding[3] = length; return CSS_OK; } @@ -1694,7 +1700,7 @@ static inline css_error set_padding_left( static inline css_error set_overflow_x( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[OVERFLOW_X_INDEX]; + uint8_t *bits = &style->i.bits[OVERFLOW_X_INDEX]; /* 3bits: type */ *bits = (*bits & ~OVERFLOW_X_MASK) | @@ -1712,7 +1718,7 @@ static inline css_error set_overflow_x( static inline css_error set_overflow_y( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[OVERFLOW_Y_INDEX]; + uint8_t *bits = &style->i.bits[OVERFLOW_Y_INDEX]; /* 3bits: type */ *bits = (*bits & ~OVERFLOW_Y_MASK) | @@ -1730,7 +1736,7 @@ static inline css_error set_overflow_y( static inline css_error set_position( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[POSITION_INDEX]; + uint8_t *bits = &style->i.bits[POSITION_INDEX]; /* 3bits: type */ *bits = (*bits & ~POSITION_MASK) | @@ -1749,13 +1755,13 @@ static inline css_error set_opacity( css_computed_style *style, uint8_t type, css_fixed opacity) { - uint8_t *bits = &style->bits[OPACITY_INDEX]; + uint8_t *bits = &style->i.bits[OPACITY_INDEX]; /* 1bit: t : type */ *bits = (*bits & ~OPACITY_MASK) | ((type & 0x1) << OPACITY_SHIFT); - style->opacity = opacity; + style->i.opacity = opacity; return CSS_OK; } @@ -1769,7 +1775,7 @@ static inline css_error set_opacity( static inline css_error set_text_transform( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[TEXT_TRANSFORM_INDEX]; + uint8_t *bits = &style->i.bits[TEXT_TRANSFORM_INDEX]; /* 3bits: type */ *bits = (*bits & ~TEXT_TRANSFORM_MASK) | @@ -1788,13 +1794,13 @@ static inline css_error set_text_indent( css_computed_style *style, uint8_t type, css_fixed length, css_unit unit) { - uint8_t *bits = &style->bits[TEXT_INDENT_INDEX]; + uint8_t *bits = &style->i.bits[TEXT_INDENT_INDEX]; /* 5bits: uuuut : units | type */ *bits = (*bits & ~TEXT_INDENT_MASK) | (((type & 0x1) | (unit << 1)) << TEXT_INDENT_SHIFT); - style->text_indent = length; + style->i.text_indent = length; return CSS_OK; } @@ -1808,7 +1814,7 @@ static inline css_error set_text_indent( static inline css_error set_white_space( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[WHITE_SPACE_INDEX]; + uint8_t *bits = &style->i.bits[WHITE_SPACE_INDEX]; /* 3bits: type */ *bits = (*bits & ~WHITE_SPACE_MASK) | @@ -1832,19 +1838,19 @@ static inline css_error set_background_position( { uint8_t *bits; - bits = &style->bits[BACKGROUND_POSITION_INDEX]; + bits = &style->i.bits[BACKGROUND_POSITION_INDEX]; /* 1 bit: type */ *bits = (*bits & ~BACKGROUND_POSITION_MASK) | ((type & 0x1) << BACKGROUND_POSITION_SHIFT); - bits = &style->bits[BACKGROUND_POSITION_INDEX1]; + bits = &style->i.bits[BACKGROUND_POSITION_INDEX1]; /* 8bits: hhhhvvvv : hunit | vunit */ *bits = (((hunit << 4) | vunit) << BACKGROUND_POSITION_SHIFT1); - style->background_position[0] = hlength; - style->background_position[1] = vlength; + style->i.background_position[0] = hlength; + style->i.background_position[1] = vlength; return CSS_OK; } @@ -1860,7 +1866,7 @@ static inline css_error set_background_position( static inline css_error set_display( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[DISPLAY_INDEX]; + uint8_t *bits = &style->i.bits[DISPLAY_INDEX]; /* 5bits: type */ *bits = (*bits & ~DISPLAY_MASK) | @@ -1878,7 +1884,7 @@ static inline css_error set_display( static inline css_error set_font_variant( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[FONT_VARIANT_INDEX]; + uint8_t *bits = &style->i.bits[FONT_VARIANT_INDEX]; /* 2bits: type */ *bits = (*bits & ~FONT_VARIANT_MASK) | @@ -1896,7 +1902,7 @@ static inline css_error set_font_variant( static inline css_error set_text_decoration( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[TEXT_DECORATION_INDEX]; + uint8_t *bits = &style->i.bits[TEXT_DECORATION_INDEX]; /* 5bits: type */ *bits = (*bits & ~TEXT_DECORATION_MASK) | @@ -1915,7 +1921,7 @@ static inline css_error set_font_family( css_computed_style *style, uint8_t type, lwc_string **names) { - uint8_t *bits = &style->bits[FONT_FAMILY_INDEX]; + uint8_t *bits = &style->i.bits[FONT_FAMILY_INDEX]; lwc_string **oldnames = style->font_family; lwc_string **s; @@ -1949,7 +1955,7 @@ static inline css_error set_font_family( static inline css_error set_border_top_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BORDER_TOP_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_TOP_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BORDER_TOP_STYLE_MASK) | @@ -1967,7 +1973,7 @@ static inline css_error set_border_top_style( static inline css_error set_border_right_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BORDER_RIGHT_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_RIGHT_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BORDER_RIGHT_STYLE_MASK) | @@ -1985,7 +1991,7 @@ static inline css_error set_border_right_style( static inline css_error set_border_bottom_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BORDER_BOTTOM_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_BOTTOM_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BORDER_BOTTOM_STYLE_MASK) | @@ -2003,7 +2009,7 @@ static inline css_error set_border_bottom_style( static inline css_error set_border_left_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[BORDER_LEFT_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[BORDER_LEFT_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~BORDER_LEFT_STYLE_MASK) | @@ -2021,7 +2027,7 @@ static inline css_error set_border_left_style( static inline css_error set_font_weight( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[FONT_WEIGHT_INDEX]; + uint8_t *bits = &style->i.bits[FONT_WEIGHT_INDEX]; /* 4bits: type */ *bits = (*bits & ~FONT_WEIGHT_MASK) | @@ -2039,7 +2045,7 @@ static inline css_error set_font_weight( static inline css_error set_list_style_type( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[LIST_STYLE_TYPE_INDEX]; + uint8_t *bits = &style->i.bits[LIST_STYLE_TYPE_INDEX]; /* 4bits: type */ *bits = (*bits & ~LIST_STYLE_TYPE_MASK) | @@ -2057,7 +2063,7 @@ static inline css_error set_list_style_type( static inline css_error set_outline_style( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[OUTLINE_STYLE_INDEX]; + uint8_t *bits = &style->i.bits[OUTLINE_STYLE_INDEX]; /* 4bits: type */ *bits = (*bits & ~OUTLINE_STYLE_MASK) | @@ -2075,7 +2081,7 @@ static inline css_error set_outline_style( static inline css_error set_table_layout( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[TABLE_LAYOUT_INDEX]; + uint8_t *bits = &style->i.bits[TABLE_LAYOUT_INDEX]; /* 2bits: type */ *bits = (*bits & ~TABLE_LAYOUT_MASK) | @@ -2093,7 +2099,7 @@ static inline css_error set_table_layout( static inline css_error set_unicode_bidi( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[UNICODE_BIDI_INDEX]; + uint8_t *bits = &style->i.bits[UNICODE_BIDI_INDEX]; /* 2bits: type */ *bits = (*bits & ~UNICODE_BIDI_MASK) | @@ -2111,7 +2117,7 @@ static inline css_error set_unicode_bidi( static inline css_error set_visibility( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[VISIBILITY_INDEX]; + uint8_t *bits = &style->i.bits[VISIBILITY_INDEX]; /* 2bits: type */ *bits = (*bits & ~VISIBILITY_MASK) | @@ -2129,7 +2135,7 @@ static inline css_error set_visibility( static inline css_error set_list_style_position( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[LIST_STYLE_POSITION_INDEX]; + uint8_t *bits = &style->i.bits[LIST_STYLE_POSITION_INDEX]; /* 2bits: type */ *bits = (*bits & ~LIST_STYLE_POSITION_MASK) | @@ -2147,7 +2153,7 @@ static inline css_error set_list_style_position( static inline uint8_t set_text_align( css_computed_style *style, uint8_t type) { - uint8_t *bits = &style->bits[TEXT_ALIGN_INDEX]; + uint8_t *bits = &style->i.bits[TEXT_ALIGN_INDEX]; /* 4bits: type */ *bits = (*bits & ~TEXT_ALIGN_MASK) | diff --git a/src/select/select.c b/src/select/select.c index ce56def..367c26a 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -1172,7 +1172,7 @@ css_error set_initial(css_select_state *state, case GROUP_NORMAL: break; case GROUP_UNCOMMON: - if (state->computed->uncommon == NULL) + if (state->computed->i.uncommon == NULL) return CSS_OK; break; case GROUP_PAGE: @@ -1180,7 +1180,7 @@ css_error set_initial(css_select_state *state, return CSS_OK; break; case GROUP_AURAL: - if (state->computed->aural == NULL) + if (state->computed->i.aural == NULL) return CSS_OK; break; } -- cgit v1.2.3 From e1d710863493dc91c09e0a71dc09d137be8e6b6e Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 8 Mar 2015 11:45:52 +0000 Subject: Ensure computed content items are initialised to zero. This allows comparing them with memcmp. --- src/select/properties/content.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/select/properties/content.c b/src/select/properties/content.c index a9dd211..472a66a 100644 --- a/src/select/properties/content.c +++ b/src/select/properties/content.c @@ -49,6 +49,7 @@ css_error css__cascade_content(uint32_t opv, css_style *style, } content = temp; + memset(content + n_contents, 0, sizeof(css_computed_content_item)); switch (v & 0xff) { case CONTENT_COUNTER: -- cgit v1.2.3 From 60812fc682b8764c93020124bb43e7972f64cb73 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 7 Mar 2015 21:37:05 +0000 Subject: Add arena module for interning computed styles. Builds, but currently unused. --- src/select/Makefile | 2 +- src/select/arena.c | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/select/arena.h | 45 +++++++ 3 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 src/select/arena.c create mode 100644 src/select/arena.h diff --git a/src/select/Makefile b/src/select/Makefile index eb89c1f..e937191 100644 --- a/src/select/Makefile +++ b/src/select/Makefile @@ -1,4 +1,4 @@ # Sources -DIR_SOURCES := computed.c dispatch.c hash.c select.c font_face.c +DIR_SOURCES := arena.c computed.c dispatch.c hash.c select.c font_face.c include $(NSBUILD)/Makefile.subdir diff --git a/src/select/arena.c b/src/select/arena.c new file mode 100644 index 0000000..8f5a319 --- /dev/null +++ b/src/select/arena.c @@ -0,0 +1,377 @@ +/* + * This file is part of LibCSS + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2015 Michael Drake + */ + +#include + +#include "select/arena.h" +#include "select/computed.h" + +#define TU_SIZE 3037 +#define TS_SIZE 5101 + +struct css_computed_uncommon *table_u[TU_SIZE]; +struct css_computed_style *table_s[TS_SIZE]; + + +/** + * FNV-1 hash + */ +static inline uint32_t css__arena_hash(const uint8_t *data, size_t len) +{ + lwc_hash h = 0x811c9dc5; + + while (len > 0) { + h *= 0x01000193; + h ^= *data++; + len--; + } + + return h; +} + + +static inline uint32_t css__arena_hash_uncommon(struct css_computed_uncommon *u) +{ + return css__arena_hash((const uint8_t *) &u->i, sizeof(u->i)); +} + + +static inline uint32_t css__arena_hash_style(struct css_computed_style *s) +{ + return css__arena_hash((const uint8_t *) &s->i, sizeof(s->i)); +} + + +static inline bool arena__compare_computed_page( + const struct css_computed_page *a, + const struct css_computed_page *b) +{ + if (a == NULL && b == NULL) { + return true; + + } else if (a == NULL || b == NULL) { + return false; + } + + return memcmp(a, b, sizeof(struct css_computed_page)) == 0; +} + + +static inline bool arena__compare_computed_content_item( + const struct css_computed_content_item *a, + const struct css_computed_content_item *b) +{ + if (a == NULL && b == NULL) { + return true; + + } else if (a == NULL || b == NULL) { + return false; + } + + if (a->type != b->type) { + return false; + } + + return memcmp(a, b, sizeof(struct css_computed_content_item)) == 0; +} + + +static inline bool arena__compare_css_computed_counter( + const struct css_computed_counter *a, + const struct css_computed_counter *b) +{ + bool match; + + if (a == NULL && b == NULL) { + return true; + + } else if (a == NULL || b == NULL) { + return false; + } + + if (a->value == b->value && + lwc_string_isequal(a->name, b->name, + &match) == lwc_error_ok && + match == true) { + return true; + } + + return false; +} + +static inline bool arena__compare_string_list( + lwc_string **a, + lwc_string **b) +{ + if (a == NULL && b == NULL) { + return true; + + } else if (a == NULL || b == NULL) { + return false; + } + + while (*a != NULL && *b != NULL) { + bool match; + + if (lwc_string_isequal(*a, *b, &match) != lwc_error_ok || + match == false) { + return false; + } + + a++; + b++; + } + + if (*a != *b) { + return false; + } + + return true; +} + + +static inline bool css__arena_uncommon_is_equal( + struct css_computed_uncommon *a, + struct css_computed_uncommon *b) +{ + if (memcmp(&a->i, &b->i, sizeof(struct css_computed_uncommon_i)) != 0) { + return false; + } + + if (!arena__compare_css_computed_counter( + a->counter_increment, + b->counter_increment)) { + return false; + } + + if (!arena__compare_css_computed_counter( + a->counter_reset, + b->counter_reset)) { + return false; + } + + if (!arena__compare_computed_content_item( + a->content, + b->content)) { + return false; + } + + if (!arena__compare_string_list( + a->cursor, + b->cursor)) { + return false; + } + + return true; +} + + +static inline bool css__arena_style_is_equal( + struct css_computed_style *a, + struct css_computed_style *b) +{ + if (memcmp(&a->i, &b->i, sizeof(struct css_computed_style_i)) != 0) { + return false; + } + + if (!arena__compare_string_list( + a->font_family, + b->font_family)) { + return false; + } + + if (!arena__compare_string_list( + a->quotes, + b->quotes)) { + return false; + } + + if (!arena__compare_computed_page( + a->page, + b->page)) { + return false; + } + + return true; +} + + +static void css__arena_intern_uncommon( + struct css_computed_uncommon **uncommon) +{ + struct css_computed_uncommon *u = *uncommon; + uint32_t hash, index; + + /* Need to intern the uncommon block */ + hash = css__arena_hash_uncommon(u); + index = hash % TU_SIZE; + u->bin = index; + + if (table_u[index] == NULL) { + /* Can just insert */ + table_u[index] = u; + u->count = 1; + } else { + /* Check for existing */ + struct css_computed_uncommon *l = table_u[index]; + struct css_computed_uncommon *existing = NULL; + + do { + if (css__arena_uncommon_is_equal(l, u)) { + existing = l; + break; + } + l = l->next; + } while (l != NULL); + + if (existing != NULL) { + css__computed_uncommon_destroy(u); + existing->count++; + *uncommon = existing; + } else { + /* Add to list */ + u->next = table_u[index]; + table_u[index] = u; + u->count = 1; + } + } +} + + +/* Internally exported function, documented in src/select/arena.h */ +css_error css__arena_intern_style(struct css_computed_style **style) +{ + struct css_computed_style *s = *style; + uint32_t hash, index; + + if (s->count != 0) { + return CSS_BADPARM; + } + + if (s->i.uncommon != NULL) { + if (s->i.uncommon->count != 0) { + return CSS_BADPARM; + } + css__arena_intern_uncommon(&s->i.uncommon); + } + + /* Need to intern the style block */ + hash = css__arena_hash_style(s); + index = hash % TS_SIZE; + s->bin = index; + + if (table_s[index] == NULL) { + /* Can just insert */ + table_s[index] = s; + s->count = 1; + } else { + /* Check for existing */ + struct css_computed_style *l = table_s[index]; + struct css_computed_style *existing = NULL; + + do { + if (css__arena_style_is_equal(l, s)) { + existing = l; + break; + } + l = l->next; + } while (l != NULL); + + if (existing != NULL) { + s->i.uncommon = NULL; + css_computed_style_destroy(s); + existing->count++; + *style = existing; + } else { + /* Add to list */ + s->next = table_s[index]; + table_s[index] = s; + s->count = 1; + } + } + + return CSS_OK; +} + + +/* Internally exported function, documented in src/select/arena.h */ +enum css_error css__arena_remove_style(struct css_computed_style *style) +{ + uint32_t index = style->bin; + + if (table_s[index] == NULL) { + return CSS_BADPARM; + + } else { + /* Check for existing */ + struct css_computed_style *l = table_s[index]; + struct css_computed_style *existing = NULL; + struct css_computed_style *prev = NULL; + + do { + if (css__arena_style_is_equal(l, style)) { + existing = l; + break; + } + prev = l; + l = l->next; + } while (l != NULL); + + if (existing != NULL) { + if (prev != NULL) { + prev->next = existing->next; + } else { + table_s[index] = existing->next; + } + } else { + return CSS_BADPARM; + } + } + + return CSS_OK; +} + + +/* Internally exported function, documented in src/select/arena.h */ +enum css_error css__arena_remove_uncommon_style( + struct css_computed_uncommon *uncommon) +{ + uint32_t index = uncommon->bin; + + if (table_u[index] == NULL) { + return CSS_BADPARM; + + } else { + /* Check for existing */ + struct css_computed_uncommon *l = table_u[index]; + struct css_computed_uncommon *existing = NULL; + struct css_computed_uncommon *prev = NULL; + + do { + if (css__arena_uncommon_is_equal(l, uncommon)) { + existing = l; + break; + } + prev = l; + l = l->next; + } while (l != NULL); + + if (existing != NULL) { + if (prev != NULL) { + prev->next = existing->next; + } else { + table_u[index] = existing->next; + } + } else { + return CSS_BADPARM; + } + } + + return CSS_OK; +} + diff --git a/src/select/arena.h b/src/select/arena.h new file mode 100644 index 0000000..af06050 --- /dev/null +++ b/src/select/arena.h @@ -0,0 +1,45 @@ +/* + * This file is part of LibCSS + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2015 Michael Drake + */ + +#ifndef css_select_arena_h_ +#define css_select_arena_h_ + +struct css_computed_style; +struct css_computed_uncommon; + +/* + * Add computed style to the style sharing arena, or exchange for existing + * + * This takes a computed style. Note that the original computed style + * may be freed by this call and all future usage should be via the + * updated computed style parameter. + * + * \params style The style to intern; possibly freed and updated + * \return CSS_OK on success or appropriate error otherwise. + */ +enum css_error css__arena_intern_style(struct css_computed_style **style); + +/* + * Remove a computed style from the style sharing arena + * + * \params style The style to remove from the style sharing arena + * \return CSS_OK on success or appropriate error otherwise. + */ +enum css_error css__arena_remove_style(struct css_computed_style *style); + +/* + * Remove a computed style's uncommon block from the style sharing arena + * + * \params uncommon The uncommon style to remove from the style sharing arena + * \return CSS_OK on success or appropriate error otherwise. + */ +enum css_error css__arena_remove_uncommon_style( + struct css_computed_uncommon *uncommon); + +#endif + -- cgit v1.2.3 From fac1ad8641848a3d747b6c495cf443ccc29c077e Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 7 Mar 2015 21:41:28 +0000 Subject: After composing styles, intern the result in the style sharing arena. Note this changes the API. Selection tests updated. --- include/libcss/computed.h | 4 ++-- src/select/computed.c | 29 +++++++++++++++++++++++++---- test/select-common.c | 2 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/libcss/computed.h b/include/libcss/computed.h index 3470da8..0009267 100644 --- a/include/libcss/computed.h +++ b/include/libcss/computed.h @@ -83,12 +83,12 @@ css_error css_computed_style_initialise(css_computed_style *style, struct css_select_handler *handler, void *pw); css_error css_computed_style_compose(const css_computed_style *parent, - const css_computed_style *child, + css_computed_style *child, css_error (*compute_font_size)(void *pw, const struct css_hint *parent, struct css_hint *size), void *pw, - css_computed_style *result); + css_computed_style **result); /****************************************************************************** * Property accessors below here * diff --git a/src/select/computed.c b/src/select/computed.c index 817da31..182a7e7 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -7,6 +7,7 @@ #include +#include "select/arena.h" #include "select/computed.h" #include "select/dispatch.h" #include "select/propget.h" @@ -92,6 +93,13 @@ css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon) if (uncommon == NULL) return CSS_BADPARM; + if (uncommon->count > 1) { + uncommon->count--; + return CSS_OK; + + } else if (uncommon->count == 1) { + css__arena_remove_uncommon_style(uncommon); + } if (uncommon != NULL) { if (uncommon->counter_increment != NULL) { @@ -176,6 +184,13 @@ css_error css_computed_style_destroy(css_computed_style *style) css__computed_uncommon_destroy(style->i.uncommon); + if (style->count > 1) { + style->count--; + return CSS_OK; + + } else if (style->count == 1) { + css__arena_remove_style(style); + } if (style->page != NULL) { free(style->page); @@ -270,11 +285,11 @@ css_error css_computed_style_initialise(css_computed_style *style, * \note \a child and \a result may point at the same object */ css_error css_computed_style_compose(const css_computed_style *parent, - const css_computed_style *child, + css_computed_style *child, css_error (*compute_font_size)(void *pw, const css_hint *parent, css_hint *size), void *pw, - css_computed_style *result) + css_computed_style **result) { css_error error = CSS_OK; size_t i; @@ -297,13 +312,19 @@ css_error css_computed_style_compose(const css_computed_style *parent, continue; /* Compose the property */ - error = prop_dispatch[i].compose(parent, child, result); + error = prop_dispatch[i].compose(parent, child, *result); if (error != CSS_OK) break; } /* Finally, compute absolute values for everything */ - return css__compute_absolute_values(parent, result, compute_font_size, pw); + error = css__compute_absolute_values(parent, *result, + compute_font_size, pw); + if (error != CSS_OK) { + return error; + } + + return css__arena_intern_style(result); } /****************************************************************************** diff --git a/test/select-common.c b/test/select-common.c index 432bd54..c6d33c0 100644 --- a/test/select-common.c +++ b/test/select-common.c @@ -773,7 +773,7 @@ static void run_test_select_tree(css_select_ctx *select, node->parent->sr->styles[ctx->pseudo_element], sr->styles[ctx->pseudo_element], compute_font_size, NULL, - sr->styles[ctx->pseudo_element]) == CSS_OK); + &(sr->styles[ctx->pseudo_element])) == CSS_OK); } node->sr = sr; -- cgit v1.2.3 From c953724a1a4bcaf03fc33a9f3bef8b864cb865d0 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 7 Mar 2015 21:50:04 +0000 Subject: Change arena hash from FNV-1 to 32-bit MurmurHash2. --- src/select/arena.c | 18 +------------ src/select/arena_hash.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 src/select/arena_hash.h diff --git a/src/select/arena.c b/src/select/arena.c index 8f5a319..1b0ea57 100644 --- a/src/select/arena.c +++ b/src/select/arena.c @@ -9,6 +9,7 @@ #include #include "select/arena.h" +#include "select/arena_hash.h" #include "select/computed.h" #define TU_SIZE 3037 @@ -18,23 +19,6 @@ struct css_computed_uncommon *table_u[TU_SIZE]; struct css_computed_style *table_s[TS_SIZE]; -/** - * FNV-1 hash - */ -static inline uint32_t css__arena_hash(const uint8_t *data, size_t len) -{ - lwc_hash h = 0x811c9dc5; - - while (len > 0) { - h *= 0x01000193; - h ^= *data++; - len--; - } - - return h; -} - - static inline uint32_t css__arena_hash_uncommon(struct css_computed_uncommon *u) { return css__arena_hash((const uint8_t *) &u->i, sizeof(u->i)); diff --git a/src/select/arena_hash.h b/src/select/arena_hash.h new file mode 100644 index 0000000..58abcd4 --- /dev/null +++ b/src/select/arena_hash.h @@ -0,0 +1,67 @@ +/* + * This file is part of LibCSS + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2015 Michael Drake + */ + +#ifndef css_select_arena_hash_h_ +#define css_select_arena_hash_h_ + +#include + +/** + * Currently 32-bit MurmurHash2. + * + * Created by Austin Appleby, and placed in the public domain. + * https://sites.google.com/site/murmurhash/ + * + * Refactored and adapted a little for libcss. + */ +static inline uint32_t css__arena_hash(const uint8_t *data, size_t len) +{ + /* Hashing constants */ + const uint32_t m = 0x5bd1e995; + const int r = 24; + + /* Start with length */ + uint32_t h = len; + + /* Hash four bytes at a time */ + while (len >= 4) { + /* If we could ensure 4-byte alignment of the input, this + * could be faster. */ + uint32_t k = + (((uint32_t) data[0]) ) | + (((uint32_t) data[1]) << 8) | + (((uint32_t) data[2]) << 16) | + (((uint32_t) data[3]) << 24); + + k *= m; + k ^= k >> r; + k *= m; + h *= m; + h ^= k; + data += 4; + len -= 4; + } + + /* Hash any left over bytes */ + switch (len) { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + } + + /* Finalise */ + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +#endif + -- cgit v1.2.3 From ba1261ab3f03a9e40f0f1be44a1a992e258662fc Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 22 Aug 2015 11:33:23 +0100 Subject: Composition: Avoid extension block checks irrelevent to property group. --- src/select/computed.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/select/computed.c b/src/select/computed.c index 182a7e7..107c884 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -296,20 +296,24 @@ css_error css_computed_style_compose(const css_computed_style *parent, /* Iterate through the properties */ for (i = 0; i < CSS_N_PROPERTIES; i++) { - /* Skip any in extension blocks if the block does not exist */ - if (prop_dispatch[i].group == GROUP_UNCOMMON && - parent->i.uncommon == NULL && - child->i.uncommon == NULL) - continue; - - if (prop_dispatch[i].group == GROUP_PAGE && - parent->page == NULL && child->page == NULL) - continue; - - if (prop_dispatch[i].group == GROUP_AURAL && - parent->i.aural == NULL && - child->i.aural == NULL) - continue; + /* 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, *result); -- cgit v1.2.3 From 1d7d0f7616df4fb9fe6e6e5acd34e90859fcb12d Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 22 Aug 2015 13:16:52 +0100 Subject: Remove trailing tab. --- include/libcss/select.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libcss/select.h b/include/libcss/select.h index bd2fed2..74fa5d2 100644 --- a/include/libcss/select.h +++ b/include/libcss/select.h @@ -227,7 +227,7 @@ css_error css_select_font_faces(css_select_ctx *ctx, uint64_t media, lwc_string *font_family, css_select_font_faces_results **result); css_error css_select_font_faces_results_destroy( - css_select_font_faces_results *results); + css_select_font_faces_results *results); #ifdef __cplusplus } -- cgit v1.2.3 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. --- include/libcss/computed.h | 7 ++-- include/libcss/select.h | 3 ++ src/select/computed.c | 30 +++++++++++----- src/select/computed.h | 17 +++++++++ src/select/select.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++ test/select-common.c | 5 ++- 6 files changed, 140 insertions(+), 13 deletions(-) diff --git a/include/libcss/computed.h b/include/libcss/computed.h index 0009267..db3e3e4 100644 --- a/include/libcss/computed.h +++ b/include/libcss/computed.h @@ -82,13 +82,14 @@ css_error css_computed_style_destroy(css_computed_style *style); css_error css_computed_style_initialise(css_computed_style *style, struct css_select_handler *handler, void *pw); -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 struct css_hint *parent, struct css_hint *size), void *pw, - css_computed_style **result); + css_computed_style **restrict result); /****************************************************************************** * Property accessors below here * diff --git a/include/libcss/select.h b/include/libcss/select.h index 74fa5d2..3f1e14a 100644 --- a/include/libcss/select.h +++ b/include/libcss/select.h @@ -217,6 +217,9 @@ css_error css_select_ctx_count_sheets(css_select_ctx *ctx, uint32_t *count); css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index, const css_stylesheet **sheet); +css_error css_select_default_style(css_select_ctx *ctx, + css_select_handler *handler, void *pw, + css_computed_style **style); css_error css_select_style(css_select_ctx *ctx, void *node, uint64_t media, const css_stylesheet *inline_style, css_select_handler *handler, void *pw, 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, diff --git a/test/select-common.c b/test/select-common.c index c6d33c0..b4f588a 100644 --- a/test/select-common.c +++ b/test/select-common.c @@ -769,11 +769,14 @@ static void run_test_select_tree(css_select_ctx *select, &select_handler, ctx, &sr) == CSS_OK); if (node->parent != NULL) { + css_computed_style *composed; assert(css_computed_style_compose( node->parent->sr->styles[ctx->pseudo_element], sr->styles[ctx->pseudo_element], compute_font_size, NULL, - &(sr->styles[ctx->pseudo_element])) == CSS_OK); + &composed) == CSS_OK); + css_computed_style_destroy(sr->styles[ctx->pseudo_element]); + sr->styles[ctx->pseudo_element] = composed; } node->sr = sr; -- cgit v1.2.3 From cec2f7d79edcd0702fd37d0c19a0063211438f91 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 2 Nov 2015 16:12:34 +0000 Subject: Add comment. --- src/select/arena.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/select/arena.c b/src/select/arena.c index 1b0ea57..baadc9f 100644 --- a/src/select/arena.c +++ b/src/select/arena.c @@ -233,6 +233,7 @@ css_error css__arena_intern_style(struct css_computed_style **style) struct css_computed_style *s = *style; uint32_t hash, index; + /* Don't try to intern an already-interned computed style */ if (s->count != 0) { return CSS_BADPARM; } -- cgit v1.2.3 From 6dc495bb9936c8d1359fd6c1a1728962730cde08 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 2 Nov 2015 16:12:39 +0000 Subject: Remove trailing whitespace. --- src/select/computed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/select/computed.c b/src/select/computed.c index 2d3aea8..1fe6a81 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -123,7 +123,7 @@ css_error css__computed_uncommon_destroy(css_computed_uncommon *uncommon) free(uncommon->counter_reset); } - + if (uncommon->cursor != NULL) { lwc_string **s; -- cgit v1.2.3 From 03824fd772e44b4cd281dd893df07d991cac9e41 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 2 Nov 2015 22:21:53 +0000 Subject: Remove redundant API surface. --- include/libcss/computed.h | 4 ---- src/select/computed.c | 6 +++--- src/select/computed.h | 6 ++++++ src/select/select.c | 10 +++++----- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/libcss/computed.h b/include/libcss/computed.h index db3e3e4..c7e77e0 100644 --- a/include/libcss/computed.h +++ b/include/libcss/computed.h @@ -76,12 +76,8 @@ typedef struct css_computed_content_item { } data; } css_computed_content_item; -css_error css_computed_style_create(css_computed_style **result); css_error css_computed_style_destroy(css_computed_style *style); -css_error css_computed_style_initialise(css_computed_style *style, - struct css_select_handler *handler, void *pw); - css_error css_computed_style_compose( const css_computed_style *restrict parent, const css_computed_style *restrict child, diff --git a/src/select/computed.c b/src/select/computed.c index 1fe6a81..2efc8a7 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -65,7 +65,7 @@ static css_error compute_absolute_length_pair(css_computed_style *style, * CSS_NOMEM on memory exhaustion, * CSS_BADPARM on bad parameters. */ -css_error css_computed_style_create(css_computed_style **result) +css_error css__computed_style_create(css_computed_style **result) { css_computed_style *s; @@ -239,7 +239,7 @@ css_error css_computed_style_destroy(css_computed_style *style) * \param pw Client-specific private data for handler functions * \return CSS_OK on success. */ -css_error css_computed_style_initialise(css_computed_style *style, +css_error css__computed_style_initialise(css_computed_style *style, css_select_handler *handler, void *pw) { css_select_state state; @@ -300,7 +300,7 @@ css_error css_computed_style_compose( * to avoid the churn of unnecesaraly allocating and freeing * the memory to compose styles into. */ - error = css_computed_style_create(&composed); + error = css__computed_style_create(&composed); if (error != CSS_OK) { return error; } diff --git a/src/select/computed.h b/src/select/computed.h index 230711d..57981b2 100644 --- a/src/select/computed.h +++ b/src/select/computed.h @@ -342,6 +342,12 @@ static inline css_computed_style * css__computed_style_ref( return style; } +css_error css__computed_style_create(css_computed_style **result); + +css_error css__computed_style_initialise(css_computed_style *style, + struct css_select_handler *handler, void *pw); + + 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 a1ec746..f2cb6d5 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -429,11 +429,11 @@ static css_error css__select_ctx_create_default_style(css_select_ctx *ctx, css_error error; /* Need to construct the default style */ - error = css_computed_style_create(&style); + error = css__computed_style_create(&style); if (error != CSS_OK) return error; - error = css_computed_style_initialise(style, handler, pw); + error = css__computed_style_initialise(style, handler, pw); if (error != CSS_OK) { css_computed_style_destroy(style); return error; @@ -543,7 +543,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, state.results->styles[i] = NULL; /* Base element style is guaranteed to exist */ - error = css_computed_style_create( + error = css__computed_style_create( &state.results->styles[CSS_PSEUDO_ELEMENT_NONE]); if (error != CSS_OK) { free(state.results); @@ -626,7 +626,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, struct css_computed_style *computed_style = state.results->styles[CSS_PSEUDO_ELEMENT_NONE]; if (computed_style == NULL) { - error = css_computed_style_create(&computed_style); + error = css__computed_style_create(&computed_style); if (error != CSS_OK) goto cleanup; } @@ -1799,7 +1799,7 @@ css_error match_selector_chain(css_select_ctx *ctx, /* Ensure that the appropriate computed style exists */ if (state->results->styles[pseudo] == NULL) { - error = css_computed_style_create( + error = css__computed_style_create( &state->results->styles[pseudo]); if (error != CSS_OK) return error; -- cgit v1.2.3 From ddf46d2a7ef13a64ec63eb4845c982e0f713d950 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 3 Nov 2015 12:30:36 +0000 Subject: Split bloom filter get/set out into helpers. --- src/select/select.c | 241 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 93 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index f2cb6d5..c8fdb45 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -484,6 +484,143 @@ css_error css_select_default_style(css_select_ctx *ctx, return CSS_OK; } +/** + * Get a bloom filter for the parent node + * + * \param parent Parent node to get bloom filter for + * \param handler Dispatch table of handler functions + * \param pw Client-specific private data for handler functions + * \param parent_bloom Updated to parent bloom to use. + * Note: if there's no parent, the caller must free + * the returned parent bloom, since it has no node to + * own it. + * \return CSS_OK on success, appropriate error otherwise. + */ +static css_error css__get_parent_bloom(void *parent, + css_select_handler *handler, void *pw, + css_bloom **parent_bloom) +{ + css_error error; + css_bloom *bloom = NULL; + + /* Get parent node's bloom filter */ + if (parent != NULL) { + /* Get parent bloom filter */ + /* Hideous casting to avoid warnings on all platforms + * we build for. */ + error = handler->get_libcss_node_data(pw, parent, + (void **) (void *) &bloom); + if (error != CSS_OK) + return error; + } + + if (bloom == NULL) { + uint32_t i; + /* Need to create parent bloom */ + + /* TODO: + * Build & set the parent node's bloom properly. This will + * speed up the case where DOM change has caused bloom to get + * deleted. For now we fall back to a fully satruated bloom + * filter, which is slower but perfectly valid. + */ + bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); + if (bloom == NULL) { + return CSS_NOMEM; + } + if (parent != NULL) { + /* Have to make up fully saturated bloom filter */ + for (i = 0; i < CSS_BLOOM_SIZE; i++) { + bloom[i] = ~0; + } + + /* Set parent node bloom filter */ + error = handler->set_libcss_node_data(pw, + parent, bloom); + if (error != CSS_OK) { + free(bloom); + return error; + } + } else { + /* No ancestors; empty bloom filter */ + for (i = 0; i < CSS_BLOOM_SIZE; i++) { + bloom[i] = 0; + } + } + } + + *parent_bloom = bloom; + return CSS_OK; +} + +/** + * Set a node's bloom filter + * + * \param parent Node to set bloom filter for + * \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__set_node_bloom(void *node, css_select_state *state, + css_select_handler *handler, void *pw) +{ + css_error error; + css_bloom *bloom; + lwc_hash hash; + + /* Create the node's bloom */ + bloom = calloc(sizeof(css_bloom), CSS_BLOOM_SIZE); + if (bloom == NULL) { + return CSS_NOMEM; + } + + /* Add node name to bloom */ + if (lwc_string_caseless_hash_value(state->element.name, + &hash) != lwc_error_ok) { + error = CSS_NOMEM; + goto cleanup; + } + css_bloom_add_hash(bloom, hash); + + /* Add id name to bloom */ + if (state->id != NULL) { + if (lwc_string_caseless_hash_value(state->id, + &hash) != lwc_error_ok) { + error = CSS_NOMEM; + goto cleanup; + } + css_bloom_add_hash(bloom, hash); + } + + /* Add class names to bloom */ + if (state->classes != NULL) { + for (uint32_t i = 0; i < state->n_classes; i++) { + lwc_string *s = state->classes[i]; + if (lwc_string_caseless_hash_value(s, + &hash) != lwc_error_ok) { + error = CSS_NOMEM; + goto cleanup; + } + css_bloom_add_hash(bloom, hash); + } + } + + /* Merge parent bloom into node bloom */ + css_bloom_merge(state->bloom, bloom); + + /* Set node bloom filter */ + error = handler->set_libcss_node_data(pw, node, bloom); + if (error != CSS_OK) + goto cleanup; + + return CSS_OK; + +cleanup: + free(bloom); + + return error; +} + /** * Select a style for the given node @@ -515,11 +652,9 @@ css_error css_select_style(css_select_ctx *ctx, void *node, 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; - lwc_hash hash; + css_hint *hints = NULL; + void *parent = NULL; if (ctx == NULL || node == NULL || result == NULL || handler == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) @@ -550,56 +685,15 @@ css_error css_select_style(css_select_ctx *ctx, void *node, return error; } - /* Create the node's bloom */ - bloom = calloc(sizeof(css_bloom), CSS_BLOOM_SIZE); - if (bloom == NULL) { - error = CSS_NOMEM; - goto cleanup; - } - error = handler->parent_node(pw, node, &parent); if (error != CSS_OK) goto cleanup; - /* Get parent node's bloom filter */ - if (parent != NULL) { - /* Get parent bloom filter */ - /* Hideous casting to avoid warnings on all platforms - * we build for. */ - error = handler->get_libcss_node_data(pw, parent, - (void **) (void *) &state.bloom); - if (error != CSS_OK) - goto cleanup; - /* TODO: - * If state.bloom == NULL, build & set parent node's bloom, - * and use it as state.bloom. This will speed up the case - * where DOM change has caused bloom to get deleted. - * For now we fall back to a fully satruated bloom filter, - * which is slower but perfectly valid. - */ - } - - if (state.bloom == NULL) { - /* Need to create parent bloom */ - parent_bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); - if (parent_bloom == NULL) { - error = CSS_NOMEM; - goto cleanup; - } - if (parent != NULL) { - /* Have to make up fully saturated bloom filter */ - for (i = 0; i < CSS_BLOOM_SIZE; i++) { - parent_bloom[i] = ~0; - } - } else { - /* Empty bloom filter */ - for (i = 0; i < CSS_BLOOM_SIZE; i++) { - parent_bloom[i] = 0; - } - } - - state.bloom = parent_bloom; + error = css__get_parent_bloom(parent, handler, pw, &parent_bloom); + if (error != CSS_OK) { + goto cleanup; } + state.bloom = parent_bloom; /* Get node's name */ error = handler->node_name(pw, node, &state.element); @@ -750,47 +844,10 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } - /* Add node name to bloom */ - - if (lwc_string_caseless_hash_value(state.element.name, - &hash) != lwc_error_ok) { - error = CSS_NOMEM; + error = css__set_node_bloom(node, &state, handler, pw); + if (error != CSS_OK) { goto cleanup; } - css_bloom_add_hash(bloom, hash); - - /* Add id name to bloom */ - if (state.id != NULL) { - if (lwc_string_caseless_hash_value(state.id, - &hash) != lwc_error_ok) { - error = CSS_NOMEM; - goto cleanup; - } - css_bloom_add_hash(bloom, hash); - } - - /* Add class names to bloom */ - if (state.classes != NULL) { - for (i = 0; i < state.n_classes; i++) { - lwc_string *s = state.classes[i]; - if (lwc_string_caseless_hash_value(s, - &hash) != lwc_error_ok) { - error = CSS_NOMEM; - goto cleanup; - } - css_bloom_add_hash(bloom, hash); - } - } - - /* Merge parent bloom into node bloom */ - css_bloom_merge(state.bloom, bloom); - - /* Set node bloom filter */ - error = handler->set_libcss_node_data(pw, node, bloom); - if (error != CSS_OK) - goto cleanup; - - bloom = NULL; *result = state.results; error = CSS_OK; @@ -803,14 +860,12 @@ cleanup: css_select_results_destroy(state.results); } - if (parent_bloom != NULL) { + /* If there's no parent, the parent_bloom is not owned by any node, + * so we need to free it. */ + if (parent == NULL) { free(parent_bloom); } - if (bloom != NULL) { - free(bloom); - } - if (state.classes != NULL) { for (i = 0; i < state.n_classes; i++) lwc_string_unref(state.classes[i]); -- cgit v1.2.3 From f3b877ef70858a39846f2c206482703cd395d7d6 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 22 Nov 2015 12:04:43 +0000 Subject: Allow more than just bloom to be stored on nodes. We now have a css_node_data struct which is sored on nodes. It currently contians just the bloom filter. --- src/select/select.c | 129 ++++++++++++++++++++++++++++++++++------------------ src/select/select.h | 6 ++- 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index c8fdb45..30ea622 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -154,15 +154,41 @@ static void dump_chain(const css_selector *selector); #endif +static css_error css__create_node_data(struct css_node_data **node_data) +{ + struct css_node_data *nd; + + nd = calloc(sizeof(struct css_node_data), 1); + if (nd == NULL) { + return CSS_NOMEM; + } + + *node_data = nd; + + return CSS_OK; +} + +static void css__destroy_node_data(struct css_node_data *node_data) +{ + assert(node_data != NULL); + + if (node_data->bloom != NULL) { + free(node_data->bloom); + } + + free(node_data); +} + + /* Exported function documented in public select.h header. */ css_error css_libcss_node_data_handler(css_select_handler *handler, css_node_data_action action, void *pw, void *node, void *clone_node, void *libcss_node_data) { - css_bloom *bloom = libcss_node_data; - css_bloom *clone_bloom = NULL; + struct css_node_data *node_data = libcss_node_data; css_error error; - unsigned int i; + + UNUSED(clone_node); if (handler == NULL || libcss_node_data == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) { @@ -171,7 +197,7 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, switch (action) { case CSS_NODE_DELETED: - free(bloom); + css__destroy_node_data(node_data); break; case CSS_NODE_MODIFIED: @@ -180,9 +206,9 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, return CSS_BADPARM; } - free(bloom); + css__destroy_node_data(node_data); - /* Don't bother rebuilding bloom here, it can be done + /* Don't bother rebuilding node_data, it can be done * when the node is selected for. Just ensure the * client drops its reference to the libcss_node_data. */ error = handler->set_libcss_node_data(pw, node, NULL); @@ -192,25 +218,10 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, break; case CSS_NODE_CLONED: - if (node == NULL || clone_node == NULL) { - return CSS_BADPARM; - } - - clone_bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); - if (clone_bloom == NULL) { - return CSS_NOMEM; - } - - for (i = 0; i < CSS_BLOOM_SIZE; i++) { - clone_bloom[i] = bloom[i]; - } - - error = handler->set_libcss_node_data(pw, clone_node, - clone_bloom); - if (error != CSS_OK) { - free(clone_bloom); - return error; - } + /* TODO: is it worth cloning libcss data? We only store + * data on the nodes as an optimisation, which is + * unlikely to be valid for most cloning cases. + */ break; default: @@ -484,6 +495,7 @@ css_error css_select_default_style(css_select_ctx *ctx, return CSS_OK; } + /** * Get a bloom filter for the parent node * @@ -500,18 +512,25 @@ static css_error css__get_parent_bloom(void *parent, css_select_handler *handler, void *pw, css_bloom **parent_bloom) { - css_error error; + struct css_node_data *node_data = NULL; css_bloom *bloom = NULL; + css_error error; /* Get parent node's bloom filter */ if (parent != NULL) { /* Get parent bloom filter */ - /* Hideous casting to avoid warnings on all platforms - * we build for. */ + struct css_node_data *node_data; + + /* Hideous casting to avoid warnings on all platforms + * we build for. */ error = handler->get_libcss_node_data(pw, parent, - (void **) (void *) &bloom); - if (error != CSS_OK) + (void **) (void *) &node_data); + if (error != CSS_OK) { return error; + } + if (node_data != NULL) { + bloom = node_data->bloom; + } } if (bloom == NULL) { @@ -534,12 +553,21 @@ static css_error css__get_parent_bloom(void *parent, bloom[i] = ~0; } - /* Set parent node bloom filter */ - error = handler->set_libcss_node_data(pw, - parent, bloom); - if (error != CSS_OK) { - free(bloom); - return error; + if (node_data == NULL) { + error = css__create_node_data(&node_data); + if (error != CSS_OK) { + free(bloom); + return error; + } + node_data->bloom = bloom; + + /* Set parent node bloom filter */ + error = handler->set_libcss_node_data(pw, + parent, node_data); + if (error != CSS_OK) { + css__destroy_node_data(node_data); + return error; + } } } else { /* No ancestors; empty bloom filter */ @@ -554,14 +582,14 @@ static css_error css__get_parent_bloom(void *parent, } /** - * Set a node's bloom filter + * Set a node's data * - * \param parent Node to set bloom filter for + * \param parent Node to set node data for * \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__set_node_bloom(void *node, css_select_state *state, +static css_error css__set_node_data(void *node, css_select_state *state, css_select_handler *handler, void *pw) { css_error error; @@ -606,13 +634,16 @@ static css_error css__set_node_bloom(void *node, css_select_state *state, } /* Merge parent bloom into node bloom */ - css_bloom_merge(state->bloom, bloom); + css_bloom_merge(state->node_data->bloom, bloom); + state->node_data->bloom = bloom; /* Set node bloom filter */ - error = handler->set_libcss_node_data(pw, node, bloom); + error = handler->set_libcss_node_data(pw, node, state->node_data); if (error != CSS_OK) goto cleanup; + state->node_data = NULL; + return CSS_OK; cleanup: @@ -666,6 +697,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, state.media = media; state.handler = handler; state.pw = pw; + state.node_data = NULL; state.next_reject = state.reject_cache + (N_ELEMENTS(state.reject_cache) - 1); @@ -685,6 +717,11 @@ css_error css_select_style(css_select_ctx *ctx, void *node, return error; } + error = css__create_node_data(&state.node_data); + if (error != CSS_OK) { + goto cleanup; + } + error = handler->parent_node(pw, node, &parent); if (error != CSS_OK) goto cleanup; @@ -693,7 +730,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) { goto cleanup; } - state.bloom = parent_bloom; + state.node_data->bloom = parent_bloom; /* Get node's name */ error = handler->node_name(pw, node, &state.element); @@ -844,7 +881,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } - error = css__set_node_bloom(node, &state, handler, pw); + error = css__set_node_data(node, &state, handler, pw); if (error != CSS_OK) { goto cleanup; } @@ -866,6 +903,10 @@ cleanup: free(parent_bloom); } + if (state.node_data != NULL) { + css__destroy_node_data(state.node_data); + } + if (state.classes != NULL) { for (i = 0; i < state.n_classes; i++) lwc_string_unref(state.classes[i]); @@ -1639,7 +1680,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx, /* Set up general selector chain requirments */ req.media = state->media; - req.node_bloom = state->bloom; + req.node_bloom = state->node_data->bloom; req.uni = ctx->universal; /* Find hash chain that applies to current node */ diff --git a/src/select/select.h b/src/select/select.h index fad86ac..196914d 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -31,6 +31,10 @@ typedef struct prop_state { inherit : 1; /* Property is set to inherit */ } prop_state; +struct css_node_data { + css_bloom *bloom; +}; + /** * Selection state */ @@ -58,7 +62,7 @@ typedef struct css_select_state { reject_item reject_cache[128]; /* Reject cache (filled from end) */ reject_item *next_reject; /* Next free slot in reject cache */ - const css_bloom *bloom; /* Bloom filter */ + struct css_node_data *node_data; /* Data we'll store on node */ prop_state props[CSS_N_PROPERTIES][CSS_PSEUDO_ELEMENT_COUNT]; } css_select_state; -- cgit v1.2.3 From cd5aa421206501a8651baa5cb4d19a96c4374cbe Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 22 Nov 2015 17:28:52 +0000 Subject: Separate node data creation and node bloom creation. --- src/select/select.c | 55 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index 30ea622..5fef4e4 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -581,21 +581,15 @@ static css_error css__get_parent_bloom(void *parent, return CSS_OK; } -/** - * Set a node's data - * - * \param parent Node to set node data for - * \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__set_node_data(void *node, css_select_state *state, - css_select_handler *handler, void *pw) +static css_error css__create_node_bloom( + css_bloom **node_bloom, css_select_state *state) { css_error error; css_bloom *bloom; lwc_hash hash; + *node_bloom = NULL; + /* Create the node's bloom */ bloom = calloc(sizeof(css_bloom), CSS_BLOOM_SIZE); if (bloom == NULL) { @@ -635,14 +629,7 @@ static css_error css__set_node_data(void *node, css_select_state *state, /* Merge parent bloom into node bloom */ css_bloom_merge(state->node_data->bloom, bloom); - state->node_data->bloom = bloom; - - /* Set node bloom filter */ - error = handler->set_libcss_node_data(pw, node, state->node_data); - if (error != CSS_OK) - goto cleanup; - - state->node_data = NULL; + *node_bloom = bloom; return CSS_OK; @@ -652,6 +639,38 @@ cleanup: return error; } +/** + * Set a node's data + * + * \param node Node to set node data for + * \param state Selection state for node + * \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__set_node_data(void *node, css_select_state *state, + css_select_handler *handler, void *pw) +{ + css_error error; + css_bloom *bloom; + + /* Set node bloom filter */ + error = css__create_node_bloom(&bloom, state); + if (error != CSS_OK) { + return error; + } + state->node_data->bloom = bloom; + + error = handler->set_libcss_node_data(pw, node, state->node_data); + if (error != CSS_OK) { + return error; + } + + state->node_data = NULL; + + return CSS_OK; +} + /** * Select a style for the given node -- cgit v1.2.3 From d91bf786c42bd86a9d9159a6cd8e14e04ee29f39 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 8 May 2016 14:12:19 +0100 Subject: Remove option to support not storing data on DOM nodes. It was complicating lifetimes and ownership. --- test/INDEX | 3 +- test/Makefile | 2 +- test/select-common.c | 1681 ------------------------------------------------- test/select-nd.c | 14 - test/select-no-nd.c | 14 - test/select.c | 1693 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1695 insertions(+), 1712 deletions(-) delete mode 100644 test/select-common.c delete mode 100644 test/select-nd.c delete mode 100644 test/select-no-nd.c create mode 100644 test/select.c diff --git a/test/INDEX b/test/INDEX index cf1a3cb..d712157 100644 --- a/test/INDEX +++ b/test/INDEX @@ -10,8 +10,7 @@ number Conversion of numbers to fixed point number #css21 Parsing (CSS2.1 specifics) css parse-auto Automated parser tests (bytecode) parse parse2-auto Automated parser tests (om & invalid) parse2 -select-no-nd Automated selection engine tests (no node_data) select -select-nd Automated selection engine tests (with node_data) select +select Automated selection engine tests select # Regression tests diff --git a/test/Makefile b/test/Makefile index 021d829..18124ce 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,6 @@ DIR_TEST_ITEMS := csdetect:csdetect.c css21:css21.c lex:lex.c \ lex-auto:lex-auto.c number:number.c \ parse:parse.c parse-auto:parse-auto.c parse2-auto:parse2-auto.c \ - select-no-nd:select-no-nd.c select-nd:select-nd.c + select:select.c include $(NSBUILD)/Makefile.subdir diff --git a/test/select-common.c b/test/select-common.c deleted file mode 100644 index b4f588a..0000000 --- a/test/select-common.c +++ /dev/null @@ -1,1681 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "utils/utils.h" - -#include "dump_computed.h" -#include "testutils.h" - -typedef struct attribute { - lwc_string *name; - lwc_string *value; -} attribute; - -typedef struct node { - lwc_string *name; - - uint32_t n_classes; - lwc_string **classes; - - uint32_t n_attrs; - attribute *attrs; - - css_select_results *sr; - void *libcss_node_data; - - struct node *parent; - struct node *next; - struct node *prev; - struct node *children; - struct node *last_child; -} node; - -typedef struct sheet_ctx { - css_stylesheet *sheet; - css_origin origin; - uint64_t media; -} sheet_ctx; - -typedef struct line_ctx { - size_t explen; - size_t expused; - char *exp; - - bool intree; - bool insheet; - bool inerrors; - bool inexp; - - node *tree; - node *current; - uint32_t depth; - - uint32_t n_sheets; - sheet_ctx *sheets; - - uint64_t media; - uint32_t pseudo_element; - node *target; - - lwc_string *attr_class; - lwc_string *attr_id; -} line_ctx; - - - - -static bool handle_line(const char *data, size_t datalen, void *pw); -static void css__parse_tree(line_ctx *ctx, const char *data, size_t len); -static void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len); -static void css__parse_sheet(line_ctx *ctx, const char *data, size_t len); -static void css__parse_media_list(const char **data, size_t *len, uint64_t *media); -static void css__parse_pseudo_list(const char **data, size_t *len, - uint32_t *element); -static void css__parse_expected(line_ctx *ctx, const char *data, size_t len); -static void run_test(line_ctx *ctx, const char *exp, size_t explen); -static void destroy_tree(node *root); - -static css_error node_name(void *pw, void *node, - css_qname *qname); -static css_error node_classes(void *pw, void *n, - lwc_string ***classes, uint32_t *n_classes); -static css_error node_id(void *pw, void *node, - lwc_string **id); -static css_error named_ancestor_node(void *pw, void *node, - const css_qname *qname, - void **ancestor); -static css_error named_parent_node(void *pw, void *node, - const css_qname *qname, - void **parent); -static css_error named_sibling_node(void *pw, void *node, - const css_qname *qname, - void **sibling); -static css_error named_generic_sibling_node(void *pw, void *node, - const css_qname *qname, - void **sibling); -static css_error parent_node(void *pw, void *node, void **parent); -static css_error sibling_node(void *pw, void *node, void **sibling); -static css_error node_has_name(void *pw, void *node, - const css_qname *qname, - bool *match); -static css_error node_has_class(void *pw, void *node, - lwc_string *name, - bool *match); -static css_error node_has_id(void *pw, void *node, - lwc_string *name, - bool *match); -static css_error node_has_attribute(void *pw, void *node, - const css_qname *qname, - bool *match); -static css_error node_has_attribute_equal(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_has_attribute_dashmatch(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_has_attribute_includes(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_has_attribute_prefix(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_has_attribute_suffix(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_has_attribute_substring(void *pw, void *node, - const css_qname *qname, - lwc_string *value, - bool *match); -static css_error node_is_root(void *pw, void *node, bool *match); -static css_error node_count_siblings(void *pw, void *node, - bool same_name, bool after, int32_t *count); -static css_error node_is_empty(void *pw, void *node, bool *match); -static css_error node_is_link(void *pw, void *node, bool *match); -static css_error node_is_visited(void *pw, void *node, bool *match); -static css_error node_is_hover(void *pw, void *node, bool *match); -static css_error node_is_active(void *pw, void *node, bool *match); -static css_error node_is_focus(void *pw, void *node, bool *match); -static css_error node_is_enabled(void *pw, void *node, bool *match); -static css_error node_is_disabled(void *pw, void *node, bool *match); -static css_error node_is_checked(void *pw, void *node, bool *match); -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 *nhints, css_hint **hints); -static css_error ua_default_for_property(void *pw, uint32_t property, - 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, - void *libcss_node_data); -static css_error get_libcss_node_data(void *pw, void *n, - void **libcss_node_data); - -static css_select_handler select_handler = { - CSS_SELECT_HANDLER_VERSION_1, - - node_name, - node_classes, - node_id, - named_ancestor_node, - named_parent_node, - named_sibling_node, - named_generic_sibling_node, - parent_node, - sibling_node, - node_has_name, - node_has_class, - node_has_id, - node_has_attribute, - node_has_attribute_equal, - node_has_attribute_dashmatch, - node_has_attribute_includes, - node_has_attribute_prefix, - node_has_attribute_suffix, - node_has_attribute_substring, - node_is_root, - node_count_siblings, - node_is_empty, - node_is_link, - node_is_visited, - node_is_hover, - node_is_active, - node_is_focus, - node_is_enabled, - node_is_disabled, - node_is_checked, - node_is_target, - node_is_lang, - node_presentational_hint, - ua_default_for_property, - compute_font_size, - set_libcss_node_data, - get_libcss_node_data -}; - -static css_error resolve_url(void *pw, - const char *base, lwc_string *rel, lwc_string **abs) -{ - UNUSED(pw); - UNUSED(base); - - /* About as useless as possible */ - *abs = lwc_string_ref(rel); - - return CSS_OK; -} - -static bool fail_because_lwc_leaked = false; - -static void -printing_lwc_iterator(lwc_string *str, void *pw) -{ - UNUSED(pw); - - printf(" DICT: %*s\n", (int)(lwc_string_length(str)), lwc_string_data(str)); - fail_because_lwc_leaked = true; -} - -int main(int argc, char **argv) -{ - line_ctx ctx; - - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return 1; - } - - memset(&ctx, 0, sizeof(ctx)); - - - lwc_intern_string("class", SLEN("class"), &ctx.attr_class); - lwc_intern_string("id", SLEN("id"), &ctx.attr_id); - - assert(css__parse_testfile(argv[1], handle_line, &ctx) == true); - - /* and run final test */ - if (ctx.tree != NULL) - run_test(&ctx, ctx.exp, ctx.expused); - - free(ctx.exp); - - lwc_string_unref(ctx.attr_class); - lwc_string_unref(ctx.attr_id); - - lwc_iterate_strings(printing_lwc_iterator, NULL); - - assert(fail_because_lwc_leaked == false); - - printf("PASS\n"); - return 0; -} - -bool handle_line(const char *data, size_t datalen, void *pw) -{ - line_ctx *ctx = (line_ctx *) pw; - css_error error; - - if (data[0] == '#') { - if (ctx->intree) { - if (strncasecmp(data+1, "errors", 6) == 0) { - ctx->intree = false; - ctx->insheet = false; - ctx->inerrors = true; - ctx->inexp = false; - } else { - /* Assume start of stylesheet */ - css__parse_sheet(ctx, data + 1, datalen - 1); - - ctx->intree = false; - ctx->insheet = true; - ctx->inerrors = false; - ctx->inexp = false; - } - } else if (ctx->insheet) { - if (strncasecmp(data+1, "errors", 6) == 0) { - assert(css_stylesheet_data_done( - ctx->sheets[ctx->n_sheets - 1].sheet) - == CSS_OK); - - ctx->intree = false; - ctx->insheet = false; - ctx->inerrors = true; - ctx->inexp = false; - } else if (strncasecmp(data+1, "ua", 2) == 0 || - strncasecmp(data+1, "user", 4) == 0 || - strncasecmp(data+1, "author", 6) == 0) { - assert(css_stylesheet_data_done( - ctx->sheets[ctx->n_sheets - 1].sheet) - == CSS_OK); - - css__parse_sheet(ctx, data + 1, datalen - 1); - } else { - error = css_stylesheet_append_data( - ctx->sheets[ctx->n_sheets - 1].sheet, - (const uint8_t *) data, - datalen); - assert(error == CSS_OK || - error == CSS_NEEDDATA); - } - } else if (ctx->inerrors) { - ctx->intree = false; - ctx->insheet = false; - ctx->inerrors = false; - ctx->inexp = true; - } else if (ctx->inexp) { - /* This marks end of testcase, so run it */ - run_test(ctx, ctx->exp, ctx->expused); - - ctx->expused = 0; - - ctx->intree = false; - ctx->insheet = false; - ctx->inerrors = false; - ctx->inexp = false; - } else { - /* Start state */ - if (strncasecmp(data+1, "tree", 4) == 0) { - css__parse_tree(ctx, data + 5, datalen - 5); - - ctx->intree = true; - ctx->insheet = false; - ctx->inerrors = false; - ctx->inexp = false; - } - } - } else { - if (ctx->intree) { - /* Not interested in the '|' */ - css__parse_tree_data(ctx, data + 1, datalen - 1); - } else if (ctx->insheet) { - error = css_stylesheet_append_data( - ctx->sheets[ctx->n_sheets - 1].sheet, - (const uint8_t *) data, datalen); - assert(error == CSS_OK || error == CSS_NEEDDATA); - } else if (ctx->inexp) { - css__parse_expected(ctx, data, datalen); - } - } - - return true; -} - -void css__parse_tree(line_ctx *ctx, const char *data, size_t len) -{ - const char *p = data; - const char *end = data + len; - size_t left; - - /* [ ? ] ? */ - - ctx->media = CSS_MEDIA_ALL; - ctx->pseudo_element = CSS_PSEUDO_ELEMENT_NONE; - - /* Consume any leading whitespace */ - while (p < end && isspace(*p)) - p++; - - if (p < end) { - left = end - p; - - css__parse_media_list(&p, &left, &ctx->media); - - end = p + left; - } - - if (p < end) { - left = end - p; - - css__parse_pseudo_list(&p, &left, &ctx->pseudo_element); - } -} - -void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len) -{ - const char *p = data; - const char *end = data + len; - const char *name = NULL; - const char *value = NULL; - size_t namelen = 0; - size_t valuelen = 0; - uint32_t depth = 0; - bool target = false; - - /* ' '{depth+1} [ '*'? | ] - * - * ::= [^=*[:space:]]+ - * ::= [^=*[:space:]]+ '=' [^[:space:]]* - */ - - while (p < end && isspace(*p)) { - depth++; - p++; - } - depth--; - - /* Get element/attribute name */ - name = p; - while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) { - namelen++; - p++; - } - - /* Skip whitespace */ - while (p < end && isspace(*p)) - p++; - - if (p < end && *p == '=') { - /* Attribute value */ - p++; - - value = p; - - while (p < end && isspace(*p) == false) { - valuelen++; - p++; - } - } else if (p < end && *p == '*') { - /* Element is target node */ - target = true; - } - - if (value == NULL) { - /* We have an element, so create it */ - node *n = malloc(sizeof(node)); - assert(n != NULL); - - memset(n, 0, sizeof(node)); - - lwc_intern_string(name, namelen, &n->name); - - /* Insert it into tree */ - if (ctx->tree == NULL) { - ctx->tree = n; - } else { - assert(depth > 0); - assert(depth <= ctx->depth + 1); - - /* Find node to insert into */ - while (depth <= ctx->depth) { - ctx->depth--; - ctx->current = ctx->current->parent; - } - - /* Insert into current node */ - if (ctx->current->children == NULL) { - ctx->current->children = n; - ctx->current->last_child = n; - } else { - ctx->current->last_child->next = n; - n->prev = ctx->current->last_child; - - ctx->current->last_child = n; - } - n->parent = ctx->current; - } - - ctx->current = n; - ctx->depth = depth; - - /* Mark the target, if it's us */ - if (target) - ctx->target = n; - } else { - /* New attribute */ - bool amatch = false; - attribute *attr; - node *n = ctx->current; - - attribute *temp = realloc(n->attrs, - (n->n_attrs + 1) * sizeof(attribute)); - assert(temp != NULL); - - n->attrs = temp; - - attr = &n->attrs[n->n_attrs]; - - lwc_intern_string(name, namelen, &attr->name); - lwc_intern_string(value, valuelen, &attr->value); - - assert(lwc_string_caseless_isequal( - n->attrs[n->n_attrs].name, - ctx->attr_class, &amatch) == lwc_error_ok); - if (amatch == true) { - n->classes = realloc(NULL, sizeof(lwc_string **)); - assert(n->classes != NULL); - - n->classes[0] = lwc_string_ref( - n->attrs[n->n_attrs]. - value); - n->n_classes = 1; - } - - n->n_attrs++; - } -} - -void css__parse_sheet(line_ctx *ctx, const char *data, size_t len) -{ - css_stylesheet_params params; - const char *p; - const char *end = data + len; - css_origin origin = CSS_ORIGIN_AUTHOR; - uint64_t media = CSS_MEDIA_ALL; - css_stylesheet *sheet; - sheet_ctx *temp; - - /* ? */ - - /* Find end of origin */ - for (p = data; p < end; p++) { - if (isspace(*p)) - break; - } - - if (p - data == 6 && strncasecmp(data, "author", 6) == 0) - origin = CSS_ORIGIN_AUTHOR; - else if (p - data == 4 && strncasecmp(data, "user", 4) == 0) - origin = CSS_ORIGIN_USER; - else if (p - data == 2 && strncasecmp(data, "ua", 2) == 0) - origin = CSS_ORIGIN_UA; - else - assert(0 && "Unknown stylesheet origin"); - - /* Skip any whitespace */ - while (p < end && isspace(*p)) - p++; - - if (p < end) { - size_t ignored = end - p; - - css__parse_media_list(&p, &ignored, &media); - } - - params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1; - params.level = CSS_LEVEL_21; - params.charset = "UTF-8"; - params.url = "foo"; - params.title = "foo"; - params.allow_quirks = false; - params.inline_style = false; - params.resolve = resolve_url; - params.resolve_pw = NULL; - params.import = NULL; - params.import_pw = NULL; - params.color = NULL; - params.color_pw = NULL; - params.font = NULL; - params.font_pw = NULL; - - /** \todo How are we going to handle @import? */ - assert(css_stylesheet_create(¶ms, &sheet) == CSS_OK); - - /* Extend array of sheets and append new sheet to it */ - temp = realloc(ctx->sheets, - (ctx->n_sheets + 1) * sizeof(sheet_ctx)); - assert(temp != NULL); - - ctx->sheets = temp; - - ctx->sheets[ctx->n_sheets].sheet = sheet; - ctx->sheets[ctx->n_sheets].origin = origin; - ctx->sheets[ctx->n_sheets].media = media; - - ctx->n_sheets++; -} - -void css__parse_media_list(const char **data, size_t *len, uint64_t *media) -{ - const char *p = *data; - const char *end = p + *len; - uint64_t result = 0; - - /* [ ',' ]* */ - - while (p < end) { - const char *start = p; - - /* consume a medium */ - while (isspace(*p) == false && *p != ',') - p++; - - if (p - start == 10 && - strncasecmp(start, "projection", 10) == 0) - result |= CSS_MEDIA_PROJECTION; - else if (p - start == 8 && - strncasecmp(start, "handheld", 8) == 0) - result |= CSS_MEDIA_HANDHELD; - else if (p - start == 8 && - strncasecmp(start, "embossed", 8) == 0) - result |= CSS_MEDIA_EMBOSSED; - else if (p - start == 7 && - strncasecmp(start, "braille", 7) == 0) - result |= CSS_MEDIA_BRAILLE; - else if (p - start == 6 && - strncasecmp(start, "speech", 6) == 0) - result |= CSS_MEDIA_SPEECH; - else if (p - start == 6 && - strncasecmp(start, "screen", 6) == 0) - result |= CSS_MEDIA_SCREEN; - else if (p - start == 5 && - strncasecmp(start, "print", 5) == 0) - result |= CSS_MEDIA_PRINT; - else if (p - start == 5 && - strncasecmp(start, "aural", 5) == 0) - result |= CSS_MEDIA_AURAL; - else if (p - start == 3 && - strncasecmp(start, "tty", 3) == 0) - result |= CSS_MEDIA_TTY; - else if (p - start == 3 && - strncasecmp(start, "all", 3) == 0) - result |= CSS_MEDIA_ALL; - else if (p - start == 2 && - strncasecmp(start, "tv", 2) == 0) - result |= CSS_MEDIA_TV; - else - assert(0 && "Unknown media type"); - - /* Consume whitespace */ - while (p < end && isspace(*p)) - p++; - - /* Stop if we've reached the end */ - if (p == end || *p != ',') - break; - - /* Consume comma */ - p++; - - /* Consume whitespace */ - while (p < end && isspace(*p)) - p++; - } - - *media = result; - - *data = p; - *len = end - p; -} - -void css__parse_pseudo_list(const char **data, size_t *len, uint32_t *element) -{ - const char *p = *data; - const char *end = p + *len; - - /* [ ',' ]* */ - - *element = CSS_PSEUDO_ELEMENT_NONE; - - while (p < end) { - const char *start = p; - - /* consume a pseudo */ - while (isspace(*p) == false && *p != ',') - p++; - - /* Pseudo elements */ - if (p - start == 12 && - strncasecmp(start, "first-letter", 12) == 0) - *element = CSS_PSEUDO_ELEMENT_FIRST_LETTER; - else if (p - start == 10 && - strncasecmp(start, "first-line", 10) == 0) - *element = CSS_PSEUDO_ELEMENT_FIRST_LINE; - else if (p - start == 6 && - strncasecmp(start, "before", 6) == 0) - *element = CSS_PSEUDO_ELEMENT_BEFORE; - else if (p - start == 5 && - strncasecmp(start, "after", 5) == 0) - *element = CSS_PSEUDO_ELEMENT_AFTER; - else - assert(0 && "Unknown pseudo"); - - /* Consume whitespace */ - while (p < end && isspace(*p)) - p++; - - /* Stop if we've reached the end */ - if (p == end || *p != ',') - break; - - /* Consume comma */ - p++; - - /* Consume whitespace */ - while (p < end && isspace(*p)) - p++; - } - - *data = p; - *len = end - p; -} - -void css__parse_expected(line_ctx *ctx, const char *data, size_t len) -{ - while (ctx->expused + len >= ctx->explen) { - size_t required = ctx->explen == 0 ? 64 : ctx->explen * 2; - char *temp = realloc(ctx->exp, required); - if (temp == NULL) { - assert(0 && "No memory for expected output"); - } - - ctx->exp = temp; - ctx->explen = required; - } - - memcpy(ctx->exp + ctx->expused, data, len); - - ctx->expused += len; -} - -static void show_differences(size_t len, const char *exp, const char *res) -{ - const char *pos_exp, *opos_exp; - const char *pos_res, *opos_res; - - opos_exp = pos_exp = exp; - opos_res = pos_res = res; - - printf("Line differences:\n"); - while (pos_exp < exp + len && pos_res < res + len) { - if (*pos_exp == '\n' && *pos_res == '\n') { - if (pos_exp - opos_exp != pos_res - opos_res || - memcmp(opos_exp, opos_res, - pos_exp - opos_exp) != 0) { - printf("Expected:\t%.*s\n", - (int)(pos_exp - opos_exp), - opos_exp); - printf(" Result:\t%.*s\n", - (int)(pos_res - opos_res), - opos_res); - printf("\n"); - } - opos_exp = ++pos_exp; - opos_res = ++pos_res; - } else if (*pos_exp == '\n') { - pos_res++; - } else if (*pos_res == '\n') { - pos_exp++; - } else { - pos_exp++; - pos_res++; - } - } -} - - -static void run_test_select_tree(css_select_ctx *select, - node *node, line_ctx *ctx, - char *buf, size_t *buflen) -{ - css_select_results *sr; - struct node *n = NULL; - - assert(css_select_style(select, node, ctx->media, NULL, - &select_handler, ctx, &sr) == CSS_OK); - - if (node->parent != NULL) { - css_computed_style *composed; - assert(css_computed_style_compose( - node->parent->sr->styles[ctx->pseudo_element], - sr->styles[ctx->pseudo_element], - compute_font_size, NULL, - &composed) == CSS_OK); - css_computed_style_destroy(sr->styles[ctx->pseudo_element]); - sr->styles[ctx->pseudo_element] = composed; - } - - node->sr = sr; - - if (node == ctx->target) { - dump_computed_style(sr->styles[ctx->pseudo_element], - buf, buflen); - } - - for (n = node->children; n != NULL; n = n->next) { - run_test_select_tree(select, n, ctx, buf, buflen); - } -} - - -void run_test(line_ctx *ctx, const char *exp, size_t explen) -{ - css_select_ctx *select; - css_select_results *results; - uint32_t i; - char *buf; - size_t buflen; - static int testnum; - - UNUSED(exp); - - buf = malloc(8192); - if (buf == NULL) { - assert(0 && "No memory for result data"); - } - buflen = 8192; - - assert(css_select_ctx_create(&select) == CSS_OK); - - for (i = 0; i < ctx->n_sheets; i++) { - assert(css_select_ctx_append_sheet(select, - ctx->sheets[i].sheet, ctx->sheets[i].origin, - ctx->sheets[i].media) == CSS_OK); - } - - testnum++; - - run_test_select_tree(select, ctx->tree, ctx, buf, &buflen); - - results = ctx->target->sr; - assert(results->styles[ctx->pseudo_element] != NULL); - - if (8192 - buflen != explen || memcmp(buf, exp, explen) != 0) { - size_t len = 8192 - buflen < explen ? 8192 - buflen : explen; - printf("Expected (%u):\n%.*s\n", - (int) explen, (int) explen, exp); - printf("Result (%u):\n%.*s\n", (int) (8192 - buflen), - (int) (8192 - buflen), buf); - - show_differences(len, exp, buf); - assert(0 && "Result doesn't match expected"); - } - - /* Clean up */ - css_select_ctx_destroy(select); - destroy_tree(ctx->tree); - - for (i = 0; i < ctx->n_sheets; i++) { - css_stylesheet_destroy(ctx->sheets[i].sheet); - } - - ctx->tree = NULL; - ctx->current = NULL; - ctx->depth = 0; - ctx->n_sheets = 0; - free(ctx->sheets); - ctx->sheets = NULL; - ctx->target = NULL; - - free(buf); - - printf("Test %d: PASS\n", testnum); -} - -void destroy_tree(node *root) -{ - node *n, *p; - uint32_t i; - - for (n = root->children; n != NULL; n = p) { - p = n->next; - - destroy_tree(n); - } - - css_select_results_destroy(root->sr); - - for (i = 0; i < root->n_attrs; ++i) { - lwc_string_unref(root->attrs[i].name); - lwc_string_unref(root->attrs[i].value); - } - free(root->attrs); - - if (root->classes != NULL) { - for (i = 0; i < root->n_classes; ++i) { - lwc_string_unref(root->classes[i]); - } - free(root->classes); - } - - if (root->libcss_node_data != NULL) { - css_libcss_node_data_handler(&select_handler, CSS_NODE_DELETED, - NULL, root, NULL, root->libcss_node_data); - } - - lwc_string_unref(root->name); - free(root); -} - - -css_error node_name(void *pw, void *n, css_qname *qname) -{ - node *node = n; - - UNUSED(pw); - - qname->name = lwc_string_ref(node->name); - - return CSS_OK; -} - -static css_error node_classes(void *pw, void *n, - lwc_string ***classes, uint32_t *n_classes) -{ - unsigned int i; - node *node = n; - UNUSED(pw); - - *classes = node->classes; - *n_classes = node->n_classes; - - for (i = 0; i < *n_classes; i++) - (*classes)[i] = lwc_string_ref(node->classes[i]); - - return CSS_OK; - -} - -css_error node_id(void *pw, void *n, - lwc_string **id) -{ - node *node = n; - uint32_t i; - line_ctx *lc = pw; - - for (i = 0; i < node->n_attrs; i++) { - bool amatch = false; - assert(lwc_string_caseless_isequal( - node->attrs[i].name, lc->attr_id, &amatch) == - lwc_error_ok); - if (amatch == true) - break; - } - - if (i != node->n_attrs) - *id = lwc_string_ref(node->attrs[i].value); - else - *id = NULL; - - return CSS_OK; -} - -css_error named_ancestor_node(void *pw, void *n, - const css_qname *qname, - void **ancestor) -{ - node *node = n; - UNUSED(pw); - - for (node = node->parent; node != NULL; node = node->parent) { - bool match = false; - assert(lwc_string_caseless_isequal( - qname->name, node->name, - &match) == lwc_error_ok); - if (match == true) - break; - } - - *ancestor = (void *) node; - - return CSS_OK; -} - -css_error named_parent_node(void *pw, void *n, - const css_qname *qname, - void **parent) -{ - node *node = n; - UNUSED(pw); - - *parent = NULL; - if (node->parent != NULL) { - bool match = false; - assert(lwc_string_caseless_isequal( - qname->name, node->parent->name, &match) == - lwc_error_ok); - if (match == true) - *parent = (void *) node->parent; - } - - return CSS_OK; -} - -css_error named_sibling_node(void *pw, void *n, - const css_qname *qname, - void **sibling) -{ - node *node = n; - UNUSED(pw); - - *sibling = NULL; - if (node->prev != NULL) { - bool match = false; - assert(lwc_string_caseless_isequal( - qname->name, node->prev->name, &match) == - lwc_error_ok); - if (match == true) - *sibling = (void *) node->prev; - } - - return CSS_OK; -} - -css_error named_generic_sibling_node(void *pw, void *n, - const css_qname *qname, - void **sibling) -{ - node *node = n; - UNUSED(pw); - - for (node = node->prev; node != NULL; node = node->prev) { - bool match = false; - assert(lwc_string_caseless_isequal( - qname->name, node->name, - &match) == lwc_error_ok); - if (match == true) - break; - } - - *sibling = (void *) node; - - return CSS_OK; -} - -css_error parent_node(void *pw, void *n, void **parent) -{ - node *node = n; - - UNUSED(pw); - - *parent = (void *) node->parent; - - return CSS_OK; -} - -css_error sibling_node(void *pw, void *n, void **sibling) -{ - node *node = n; - - UNUSED(pw); - - *sibling = (void *) node->prev; - - return CSS_OK; -} - -css_error node_has_name(void *pw, void *n, - const css_qname *qname, - bool *match) -{ - node *node = n; - UNUSED(pw); - - if (lwc_string_length(qname->name) == 1 && - lwc_string_data(qname->name)[0] == '*') - *match = true; - else - assert(lwc_string_caseless_isequal(node->name, - qname->name, match) == lwc_error_ok); - - return CSS_OK; -} - -css_error node_has_class(void *pw, void *n, - lwc_string *name, - bool *match) -{ - node *node = n; - uint32_t i; - line_ctx *ctx = pw; - - for (i = 0; i < node->n_attrs; i++) { - bool amatch = false; - assert(lwc_string_caseless_isequal( - node->attrs[i].name, ctx->attr_class, - &amatch) == lwc_error_ok); - if (amatch == true) - break; - } - - /* Classes are case-sensitive in HTML */ - if (i != node->n_attrs && name == node->attrs[i].value) - *match = true; - else - *match = false; - - return CSS_OK; -} - -css_error node_has_id(void *pw, void *n, - lwc_string *name, - bool *match) -{ - node *node = n; - uint32_t i; - line_ctx *ctx = pw; - - for (i = 0; i < node->n_attrs; i++) { - bool amatch = false; - assert(lwc_string_caseless_isequal( - node->attrs[i].name, ctx->attr_id, &amatch) == - lwc_error_ok); - if (amatch == true) - break; - } - - /* IDs are case-sensitive in HTML */ - if (i != node->n_attrs && name == node->attrs[i].value) - *match = true; - else - *match = false; - - return CSS_OK; -} - -css_error node_has_attribute(void *pw, void *n, - const css_qname *qname, - bool *match) -{ - node *node = n; - uint32_t i; - UNUSED(pw); - - *match = false; - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - return CSS_OK; -} - -css_error node_has_attribute_equal(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, value, match) == - lwc_error_ok); - } - - return CSS_OK; -} - -css_error node_has_attribute_includes(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - size_t vlen = lwc_string_length(value); - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - const char *p; - const char *start = lwc_string_data(node->attrs[i].value); - const char *end = start + - lwc_string_length(node->attrs[i].value); - - *match = false; - - for (p = start; p < end; p++) { - if (*p == ' ') { - if ((size_t) (p - start) == vlen && - strncasecmp(start, - lwc_string_data(value), - vlen) == 0) { - *match = true; - break; - } - - start = p + 1; - } - } - } - - return CSS_OK; -} - -css_error node_has_attribute_dashmatch(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - size_t vlen = lwc_string_length(value); - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - const char *p; - const char *start = lwc_string_data(node->attrs[i].value); - const char *end = start + - lwc_string_length(node->attrs[i].value); - - *match = false; - - for (p = start; p < end; p++) { - if (*p == '-') { - if ((size_t) (p - start) == vlen && - strncasecmp(start, - lwc_string_data(value), - vlen) == 0) { - *match = true; - break; - } - - start = p + 1; - } - } - } - - return CSS_OK; -} - -css_error node_has_attribute_prefix(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - size_t len = lwc_string_length(node->attrs[i].value); - const char *data = lwc_string_data(node->attrs[i].value); - - size_t vlen = lwc_string_length(value); - const char *vdata = lwc_string_data(value); - - if (len < vlen) - *match = false; - else - *match = (strncasecmp(data, vdata, vlen) == 0); - } - - return CSS_OK; -} - -css_error node_has_attribute_suffix(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - size_t len = lwc_string_length(node->attrs[i].value); - const char *data = lwc_string_data(node->attrs[i].value); - - size_t vlen = lwc_string_length(value); - const char *vdata = lwc_string_data(value); - - size_t suffix_start = len - vlen; - - if (len < vlen) - *match = false; - else { - *match = (strncasecmp(data + suffix_start, - vdata, vlen) == 0); - } - } - - return CSS_OK; -} - -css_error node_has_attribute_substring(void *pw, void *n, - const css_qname *qname, - lwc_string *value, - bool *match) -{ - node *node = n; - uint32_t i; - UNUSED(pw); - - *match = false; - - for (i = 0; i < node->n_attrs; i++) { - assert(lwc_string_caseless_isequal( - node->attrs[i].name, qname->name, match) == - lwc_error_ok); - if (*match == true) - break; - } - - if (*match == true) { - size_t len = lwc_string_length(node->attrs[i].value); - const char *data = lwc_string_data(node->attrs[i].value); - - size_t vlen = lwc_string_length(value); - const char *vdata = lwc_string_data(value); - - const char *last_start = data + len - vlen; - - if (len < vlen) - *match = false; - else { - while (data <= last_start) { - if (strncasecmp(data, vdata, vlen) == 0) { - *match = true; - break; - } - - data++; - } - - if (data > last_start) - *match = false; - } - } - - return CSS_OK; -} - -css_error node_is_root(void *pw, void *n, bool *match) -{ - node *node = n; - UNUSED(pw); - - *match = (node->parent == NULL); - - return CSS_OK; -} - -css_error node_count_siblings(void *pw, void *n, - bool same_name, bool after, int32_t *count) -{ - int32_t cnt = 0; - bool match = false; - node *node = n; - lwc_string *name = node->name; - UNUSED(pw); - - if (after) { - while (node->next != NULL) { - if (same_name) { - assert(lwc_string_caseless_isequal( - name, node->next->name, &match) == - lwc_error_ok); - - if (match) - cnt++; - } else { - cnt++; - } - - node = node->next; - } - } else { - while (node->prev != NULL) { - if (same_name) { - assert(lwc_string_caseless_isequal( - name, node->prev->name, &match) == - lwc_error_ok); - - if (match) - cnt++; - } else { - cnt++; - } - - node = node->prev; - } - } - - *count = cnt; - - return CSS_OK; -} - -css_error node_is_empty(void *pw, void *n, bool *match) -{ - node *node = n; - UNUSED(pw); - - *match = (node->children == NULL); - - return CSS_OK; -} - -css_error node_is_link(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_visited(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_hover(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_active(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_focus(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_enabled(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_disabled(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_checked(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_target(void *pw, void *n, bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - - *match = false; - - return CSS_OK; -} - -css_error node_is_lang(void *pw, void *n, - lwc_string *lang, - bool *match) -{ - node *node = n; - - UNUSED(pw); - UNUSED(node); - UNUSED(lang); - - *match = false; - - return CSS_OK; -} - -css_error node_presentational_hint(void *pw, void *node, - uint32_t *nhints, css_hint **hints) -{ - UNUSED(pw); - UNUSED(node); - - *nhints = 0; - *hints = NULL; - - return CSS_OK; -} - -css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint) -{ - UNUSED(pw); - - if (property == CSS_PROP_COLOR) { - hint->data.color = 0xff000000; - hint->status = CSS_COLOR_COLOR; - } else if (property == CSS_PROP_FONT_FAMILY) { - hint->data.strings = NULL; - hint->status = CSS_FONT_FAMILY_SANS_SERIF; - } else if (property == CSS_PROP_QUOTES) { - /* Not exactly useful :) */ - hint->data.strings = NULL; - hint->status = CSS_QUOTES_NONE; - } else if (property == CSS_PROP_VOICE_FAMILY) { - /** \todo Fix this when we have voice-family done */ - hint->data.strings = NULL; - hint->status = 0; - } else { - return CSS_INVALID; - } - - return CSS_OK; -} - -css_error compute_font_size(void *pw, const css_hint *parent, css_hint *size) -{ - static css_hint_length sizes[] = { - { FLTTOFIX(6.75), CSS_UNIT_PT }, - { FLTTOFIX(7.50), CSS_UNIT_PT }, - { FLTTOFIX(9.75), CSS_UNIT_PT }, - { FLTTOFIX(12.0), CSS_UNIT_PT }, - { FLTTOFIX(13.5), CSS_UNIT_PT }, - { FLTTOFIX(18.0), CSS_UNIT_PT }, - { FLTTOFIX(24.0), CSS_UNIT_PT } - }; - const css_hint_length *parent_size; - - UNUSED(pw); - - /* Grab parent size, defaulting to medium if none */ - if (parent == NULL) { - parent_size = &sizes[CSS_FONT_SIZE_MEDIUM - 1]; - } else { - assert(parent->status == CSS_FONT_SIZE_DIMENSION); - assert(parent->data.length.unit != CSS_UNIT_EM); - assert(parent->data.length.unit != CSS_UNIT_EX); - parent_size = &parent->data.length; - } - - assert(size->status != CSS_FONT_SIZE_INHERIT); - - if (size->status < CSS_FONT_SIZE_LARGER) { - /* Keyword -- simple */ - size->data.length = sizes[size->status - 1]; - } else if (size->status == CSS_FONT_SIZE_LARGER) { - /** \todo Step within table, if appropriate */ - size->data.length.value = - FMUL(parent_size->value, FLTTOFIX(1.2)); - size->data.length.unit = parent_size->unit; - } else if (size->status == CSS_FONT_SIZE_SMALLER) { - /** \todo Step within table, if appropriate */ - size->data.length.value = - FMUL(parent_size->value, FLTTOFIX(1.2)); - size->data.length.unit = parent_size->unit; - } else if (size->data.length.unit == CSS_UNIT_EM || - size->data.length.unit == CSS_UNIT_EX) { - size->data.length.value = - FMUL(size->data.length.value, parent_size->value); - - if (size->data.length.unit == CSS_UNIT_EX) { - size->data.length.value = FMUL(size->data.length.value, - FLTTOFIX(0.6)); - } - - size->data.length.unit = parent_size->unit; - } else if (size->data.length.unit == CSS_UNIT_PCT) { - size->data.length.value = FDIV(FMUL(size->data.length.value, - parent_size->value), FLTTOFIX(100)); - size->data.length.unit = parent_size->unit; - } - - size->status = CSS_FONT_SIZE_DIMENSION; - - return CSS_OK; -} - -static css_error set_libcss_node_data(void *pw, void *n, - void *libcss_node_data) -{ - node *node = n; - UNUSED(pw); - - node->libcss_node_data = libcss_node_data; - - return CSS_OK; -} - - diff --git a/test/select-nd.c b/test/select-nd.c deleted file mode 100644 index 6469267..0000000 --- a/test/select-nd.c +++ /dev/null @@ -1,14 +0,0 @@ - -#include "select-common.c" - -static css_error get_libcss_node_data(void *pw, void *n, - void **libcss_node_data) -{ - node *node = n; - UNUSED(pw); - - /* Pass any node data back to libcss */ - *libcss_node_data = node->libcss_node_data; - - return CSS_OK; -} diff --git a/test/select-no-nd.c b/test/select-no-nd.c deleted file mode 100644 index 8eb3735..0000000 --- a/test/select-no-nd.c +++ /dev/null @@ -1,14 +0,0 @@ - -#include "select-common.c" - -static css_error get_libcss_node_data(void *pw, void *n, - void **libcss_node_data) -{ - UNUSED(pw); - UNUSED(n); - - /* Test case were node data is deleted, by not passing any node data */ - *libcss_node_data = NULL; - - return CSS_OK; -} diff --git a/test/select.c b/test/select.c new file mode 100644 index 0000000..4146355 --- /dev/null +++ b/test/select.c @@ -0,0 +1,1693 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "utils/utils.h" + +#include "dump_computed.h" +#include "testutils.h" + +typedef struct attribute { + lwc_string *name; + lwc_string *value; +} attribute; + +typedef struct node { + lwc_string *name; + + uint32_t n_classes; + lwc_string **classes; + + uint32_t n_attrs; + attribute *attrs; + + css_select_results *sr; + void *libcss_node_data; + + struct node *parent; + struct node *next; + struct node *prev; + struct node *children; + struct node *last_child; +} node; + +typedef struct sheet_ctx { + css_stylesheet *sheet; + css_origin origin; + uint64_t media; +} sheet_ctx; + +typedef struct line_ctx { + size_t explen; + size_t expused; + char *exp; + + bool intree; + bool insheet; + bool inerrors; + bool inexp; + + node *tree; + node *current; + uint32_t depth; + + uint32_t n_sheets; + sheet_ctx *sheets; + + uint64_t media; + uint32_t pseudo_element; + node *target; + + lwc_string *attr_class; + lwc_string *attr_id; +} line_ctx; + + + + +static bool handle_line(const char *data, size_t datalen, void *pw); +static void css__parse_tree(line_ctx *ctx, const char *data, size_t len); +static void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len); +static void css__parse_sheet(line_ctx *ctx, const char *data, size_t len); +static void css__parse_media_list(const char **data, size_t *len, uint64_t *media); +static void css__parse_pseudo_list(const char **data, size_t *len, + uint32_t *element); +static void css__parse_expected(line_ctx *ctx, const char *data, size_t len); +static void run_test(line_ctx *ctx, const char *exp, size_t explen); +static void destroy_tree(node *root); + +static css_error node_name(void *pw, void *node, + css_qname *qname); +static css_error node_classes(void *pw, void *n, + lwc_string ***classes, uint32_t *n_classes); +static css_error node_id(void *pw, void *node, + lwc_string **id); +static css_error named_ancestor_node(void *pw, void *node, + const css_qname *qname, + void **ancestor); +static css_error named_parent_node(void *pw, void *node, + const css_qname *qname, + void **parent); +static css_error named_sibling_node(void *pw, void *node, + const css_qname *qname, + void **sibling); +static css_error named_generic_sibling_node(void *pw, void *node, + const css_qname *qname, + void **sibling); +static css_error parent_node(void *pw, void *node, void **parent); +static css_error sibling_node(void *pw, void *node, void **sibling); +static css_error node_has_name(void *pw, void *node, + const css_qname *qname, + bool *match); +static css_error node_has_class(void *pw, void *node, + lwc_string *name, + bool *match); +static css_error node_has_id(void *pw, void *node, + lwc_string *name, + bool *match); +static css_error node_has_attribute(void *pw, void *node, + const css_qname *qname, + bool *match); +static css_error node_has_attribute_equal(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_has_attribute_dashmatch(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_has_attribute_includes(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_has_attribute_prefix(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_has_attribute_suffix(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_has_attribute_substring(void *pw, void *node, + const css_qname *qname, + lwc_string *value, + bool *match); +static css_error node_is_root(void *pw, void *node, bool *match); +static css_error node_count_siblings(void *pw, void *node, + bool same_name, bool after, int32_t *count); +static css_error node_is_empty(void *pw, void *node, bool *match); +static css_error node_is_link(void *pw, void *node, bool *match); +static css_error node_is_visited(void *pw, void *node, bool *match); +static css_error node_is_hover(void *pw, void *node, bool *match); +static css_error node_is_active(void *pw, void *node, bool *match); +static css_error node_is_focus(void *pw, void *node, bool *match); +static css_error node_is_enabled(void *pw, void *node, bool *match); +static css_error node_is_disabled(void *pw, void *node, bool *match); +static css_error node_is_checked(void *pw, void *node, bool *match); +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 *nhints, css_hint **hints); +static css_error ua_default_for_property(void *pw, uint32_t property, + 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, + void *libcss_node_data); +static css_error get_libcss_node_data(void *pw, void *n, + void **libcss_node_data); + +static css_select_handler select_handler = { + CSS_SELECT_HANDLER_VERSION_1, + + node_name, + node_classes, + node_id, + named_ancestor_node, + named_parent_node, + named_sibling_node, + named_generic_sibling_node, + parent_node, + sibling_node, + node_has_name, + node_has_class, + node_has_id, + node_has_attribute, + node_has_attribute_equal, + node_has_attribute_dashmatch, + node_has_attribute_includes, + node_has_attribute_prefix, + node_has_attribute_suffix, + node_has_attribute_substring, + node_is_root, + node_count_siblings, + node_is_empty, + node_is_link, + node_is_visited, + node_is_hover, + node_is_active, + node_is_focus, + node_is_enabled, + node_is_disabled, + node_is_checked, + node_is_target, + node_is_lang, + node_presentational_hint, + ua_default_for_property, + compute_font_size, + set_libcss_node_data, + get_libcss_node_data +}; + +static css_error resolve_url(void *pw, + const char *base, lwc_string *rel, lwc_string **abs) +{ + UNUSED(pw); + UNUSED(base); + + /* About as useless as possible */ + *abs = lwc_string_ref(rel); + + return CSS_OK; +} + +static bool fail_because_lwc_leaked = false; + +static void +printing_lwc_iterator(lwc_string *str, void *pw) +{ + UNUSED(pw); + + printf(" DICT: %*s\n", (int)(lwc_string_length(str)), lwc_string_data(str)); + fail_because_lwc_leaked = true; +} + +int main(int argc, char **argv) +{ + line_ctx ctx; + + if (argc != 2) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + memset(&ctx, 0, sizeof(ctx)); + + + lwc_intern_string("class", SLEN("class"), &ctx.attr_class); + lwc_intern_string("id", SLEN("id"), &ctx.attr_id); + + assert(css__parse_testfile(argv[1], handle_line, &ctx) == true); + + /* and run final test */ + if (ctx.tree != NULL) + run_test(&ctx, ctx.exp, ctx.expused); + + free(ctx.exp); + + lwc_string_unref(ctx.attr_class); + lwc_string_unref(ctx.attr_id); + + lwc_iterate_strings(printing_lwc_iterator, NULL); + + assert(fail_because_lwc_leaked == false); + + printf("PASS\n"); + return 0; +} + +bool handle_line(const char *data, size_t datalen, void *pw) +{ + line_ctx *ctx = (line_ctx *) pw; + css_error error; + + if (data[0] == '#') { + if (ctx->intree) { + if (strncasecmp(data+1, "errors", 6) == 0) { + ctx->intree = false; + ctx->insheet = false; + ctx->inerrors = true; + ctx->inexp = false; + } else { + /* Assume start of stylesheet */ + css__parse_sheet(ctx, data + 1, datalen - 1); + + ctx->intree = false; + ctx->insheet = true; + ctx->inerrors = false; + ctx->inexp = false; + } + } else if (ctx->insheet) { + if (strncasecmp(data+1, "errors", 6) == 0) { + assert(css_stylesheet_data_done( + ctx->sheets[ctx->n_sheets - 1].sheet) + == CSS_OK); + + ctx->intree = false; + ctx->insheet = false; + ctx->inerrors = true; + ctx->inexp = false; + } else if (strncasecmp(data+1, "ua", 2) == 0 || + strncasecmp(data+1, "user", 4) == 0 || + strncasecmp(data+1, "author", 6) == 0) { + assert(css_stylesheet_data_done( + ctx->sheets[ctx->n_sheets - 1].sheet) + == CSS_OK); + + css__parse_sheet(ctx, data + 1, datalen - 1); + } else { + error = css_stylesheet_append_data( + ctx->sheets[ctx->n_sheets - 1].sheet, + (const uint8_t *) data, + datalen); + assert(error == CSS_OK || + error == CSS_NEEDDATA); + } + } else if (ctx->inerrors) { + ctx->intree = false; + ctx->insheet = false; + ctx->inerrors = false; + ctx->inexp = true; + } else if (ctx->inexp) { + /* This marks end of testcase, so run it */ + run_test(ctx, ctx->exp, ctx->expused); + + ctx->expused = 0; + + ctx->intree = false; + ctx->insheet = false; + ctx->inerrors = false; + ctx->inexp = false; + } else { + /* Start state */ + if (strncasecmp(data+1, "tree", 4) == 0) { + css__parse_tree(ctx, data + 5, datalen - 5); + + ctx->intree = true; + ctx->insheet = false; + ctx->inerrors = false; + ctx->inexp = false; + } + } + } else { + if (ctx->intree) { + /* Not interested in the '|' */ + css__parse_tree_data(ctx, data + 1, datalen - 1); + } else if (ctx->insheet) { + error = css_stylesheet_append_data( + ctx->sheets[ctx->n_sheets - 1].sheet, + (const uint8_t *) data, datalen); + assert(error == CSS_OK || error == CSS_NEEDDATA); + } else if (ctx->inexp) { + css__parse_expected(ctx, data, datalen); + } + } + + return true; +} + +void css__parse_tree(line_ctx *ctx, const char *data, size_t len) +{ + const char *p = data; + const char *end = data + len; + size_t left; + + /* [ ? ] ? */ + + ctx->media = CSS_MEDIA_ALL; + ctx->pseudo_element = CSS_PSEUDO_ELEMENT_NONE; + + /* Consume any leading whitespace */ + while (p < end && isspace(*p)) + p++; + + if (p < end) { + left = end - p; + + css__parse_media_list(&p, &left, &ctx->media); + + end = p + left; + } + + if (p < end) { + left = end - p; + + css__parse_pseudo_list(&p, &left, &ctx->pseudo_element); + } +} + +void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len) +{ + const char *p = data; + const char *end = data + len; + const char *name = NULL; + const char *value = NULL; + size_t namelen = 0; + size_t valuelen = 0; + uint32_t depth = 0; + bool target = false; + + /* ' '{depth+1} [ '*'? | ] + * + * ::= [^=*[:space:]]+ + * ::= [^=*[:space:]]+ '=' [^[:space:]]* + */ + + while (p < end && isspace(*p)) { + depth++; + p++; + } + depth--; + + /* Get element/attribute name */ + name = p; + while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) { + namelen++; + p++; + } + + /* Skip whitespace */ + while (p < end && isspace(*p)) + p++; + + if (p < end && *p == '=') { + /* Attribute value */ + p++; + + value = p; + + while (p < end && isspace(*p) == false) { + valuelen++; + p++; + } + } else if (p < end && *p == '*') { + /* Element is target node */ + target = true; + } + + if (value == NULL) { + /* We have an element, so create it */ + node *n = malloc(sizeof(node)); + assert(n != NULL); + + memset(n, 0, sizeof(node)); + + lwc_intern_string(name, namelen, &n->name); + + /* Insert it into tree */ + if (ctx->tree == NULL) { + ctx->tree = n; + } else { + assert(depth > 0); + assert(depth <= ctx->depth + 1); + + /* Find node to insert into */ + while (depth <= ctx->depth) { + ctx->depth--; + ctx->current = ctx->current->parent; + } + + /* Insert into current node */ + if (ctx->current->children == NULL) { + ctx->current->children = n; + ctx->current->last_child = n; + } else { + ctx->current->last_child->next = n; + n->prev = ctx->current->last_child; + + ctx->current->last_child = n; + } + n->parent = ctx->current; + } + + ctx->current = n; + ctx->depth = depth; + + /* Mark the target, if it's us */ + if (target) + ctx->target = n; + } else { + /* New attribute */ + bool amatch = false; + attribute *attr; + node *n = ctx->current; + + attribute *temp = realloc(n->attrs, + (n->n_attrs + 1) * sizeof(attribute)); + assert(temp != NULL); + + n->attrs = temp; + + attr = &n->attrs[n->n_attrs]; + + lwc_intern_string(name, namelen, &attr->name); + lwc_intern_string(value, valuelen, &attr->value); + + assert(lwc_string_caseless_isequal( + n->attrs[n->n_attrs].name, + ctx->attr_class, &amatch) == lwc_error_ok); + if (amatch == true) { + n->classes = realloc(NULL, sizeof(lwc_string **)); + assert(n->classes != NULL); + + n->classes[0] = lwc_string_ref( + n->attrs[n->n_attrs]. + value); + n->n_classes = 1; + } + + n->n_attrs++; + } +} + +void css__parse_sheet(line_ctx *ctx, const char *data, size_t len) +{ + css_stylesheet_params params; + const char *p; + const char *end = data + len; + css_origin origin = CSS_ORIGIN_AUTHOR; + uint64_t media = CSS_MEDIA_ALL; + css_stylesheet *sheet; + sheet_ctx *temp; + + /* ? */ + + /* Find end of origin */ + for (p = data; p < end; p++) { + if (isspace(*p)) + break; + } + + if (p - data == 6 && strncasecmp(data, "author", 6) == 0) + origin = CSS_ORIGIN_AUTHOR; + else if (p - data == 4 && strncasecmp(data, "user", 4) == 0) + origin = CSS_ORIGIN_USER; + else if (p - data == 2 && strncasecmp(data, "ua", 2) == 0) + origin = CSS_ORIGIN_UA; + else + assert(0 && "Unknown stylesheet origin"); + + /* Skip any whitespace */ + while (p < end && isspace(*p)) + p++; + + if (p < end) { + size_t ignored = end - p; + + css__parse_media_list(&p, &ignored, &media); + } + + params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1; + params.level = CSS_LEVEL_21; + params.charset = "UTF-8"; + params.url = "foo"; + params.title = "foo"; + params.allow_quirks = false; + params.inline_style = false; + params.resolve = resolve_url; + params.resolve_pw = NULL; + params.import = NULL; + params.import_pw = NULL; + params.color = NULL; + params.color_pw = NULL; + params.font = NULL; + params.font_pw = NULL; + + /** \todo How are we going to handle @import? */ + assert(css_stylesheet_create(¶ms, &sheet) == CSS_OK); + + /* Extend array of sheets and append new sheet to it */ + temp = realloc(ctx->sheets, + (ctx->n_sheets + 1) * sizeof(sheet_ctx)); + assert(temp != NULL); + + ctx->sheets = temp; + + ctx->sheets[ctx->n_sheets].sheet = sheet; + ctx->sheets[ctx->n_sheets].origin = origin; + ctx->sheets[ctx->n_sheets].media = media; + + ctx->n_sheets++; +} + +void css__parse_media_list(const char **data, size_t *len, uint64_t *media) +{ + const char *p = *data; + const char *end = p + *len; + uint64_t result = 0; + + /* [ ',' ]* */ + + while (p < end) { + const char *start = p; + + /* consume a medium */ + while (isspace(*p) == false && *p != ',') + p++; + + if (p - start == 10 && + strncasecmp(start, "projection", 10) == 0) + result |= CSS_MEDIA_PROJECTION; + else if (p - start == 8 && + strncasecmp(start, "handheld", 8) == 0) + result |= CSS_MEDIA_HANDHELD; + else if (p - start == 8 && + strncasecmp(start, "embossed", 8) == 0) + result |= CSS_MEDIA_EMBOSSED; + else if (p - start == 7 && + strncasecmp(start, "braille", 7) == 0) + result |= CSS_MEDIA_BRAILLE; + else if (p - start == 6 && + strncasecmp(start, "speech", 6) == 0) + result |= CSS_MEDIA_SPEECH; + else if (p - start == 6 && + strncasecmp(start, "screen", 6) == 0) + result |= CSS_MEDIA_SCREEN; + else if (p - start == 5 && + strncasecmp(start, "print", 5) == 0) + result |= CSS_MEDIA_PRINT; + else if (p - start == 5 && + strncasecmp(start, "aural", 5) == 0) + result |= CSS_MEDIA_AURAL; + else if (p - start == 3 && + strncasecmp(start, "tty", 3) == 0) + result |= CSS_MEDIA_TTY; + else if (p - start == 3 && + strncasecmp(start, "all", 3) == 0) + result |= CSS_MEDIA_ALL; + else if (p - start == 2 && + strncasecmp(start, "tv", 2) == 0) + result |= CSS_MEDIA_TV; + else + assert(0 && "Unknown media type"); + + /* Consume whitespace */ + while (p < end && isspace(*p)) + p++; + + /* Stop if we've reached the end */ + if (p == end || *p != ',') + break; + + /* Consume comma */ + p++; + + /* Consume whitespace */ + while (p < end && isspace(*p)) + p++; + } + + *media = result; + + *data = p; + *len = end - p; +} + +void css__parse_pseudo_list(const char **data, size_t *len, uint32_t *element) +{ + const char *p = *data; + const char *end = p + *len; + + /* [ ',' ]* */ + + *element = CSS_PSEUDO_ELEMENT_NONE; + + while (p < end) { + const char *start = p; + + /* consume a pseudo */ + while (isspace(*p) == false && *p != ',') + p++; + + /* Pseudo elements */ + if (p - start == 12 && + strncasecmp(start, "first-letter", 12) == 0) + *element = CSS_PSEUDO_ELEMENT_FIRST_LETTER; + else if (p - start == 10 && + strncasecmp(start, "first-line", 10) == 0) + *element = CSS_PSEUDO_ELEMENT_FIRST_LINE; + else if (p - start == 6 && + strncasecmp(start, "before", 6) == 0) + *element = CSS_PSEUDO_ELEMENT_BEFORE; + else if (p - start == 5 && + strncasecmp(start, "after", 5) == 0) + *element = CSS_PSEUDO_ELEMENT_AFTER; + else + assert(0 && "Unknown pseudo"); + + /* Consume whitespace */ + while (p < end && isspace(*p)) + p++; + + /* Stop if we've reached the end */ + if (p == end || *p != ',') + break; + + /* Consume comma */ + p++; + + /* Consume whitespace */ + while (p < end && isspace(*p)) + p++; + } + + *data = p; + *len = end - p; +} + +void css__parse_expected(line_ctx *ctx, const char *data, size_t len) +{ + while (ctx->expused + len >= ctx->explen) { + size_t required = ctx->explen == 0 ? 64 : ctx->explen * 2; + char *temp = realloc(ctx->exp, required); + if (temp == NULL) { + assert(0 && "No memory for expected output"); + } + + ctx->exp = temp; + ctx->explen = required; + } + + memcpy(ctx->exp + ctx->expused, data, len); + + ctx->expused += len; +} + +static void show_differences(size_t len, const char *exp, const char *res) +{ + const char *pos_exp, *opos_exp; + const char *pos_res, *opos_res; + + opos_exp = pos_exp = exp; + opos_res = pos_res = res; + + printf("Line differences:\n"); + while (pos_exp < exp + len && pos_res < res + len) { + if (*pos_exp == '\n' && *pos_res == '\n') { + if (pos_exp - opos_exp != pos_res - opos_res || + memcmp(opos_exp, opos_res, + pos_exp - opos_exp) != 0) { + printf("Expected:\t%.*s\n", + (int)(pos_exp - opos_exp), + opos_exp); + printf(" Result:\t%.*s\n", + (int)(pos_res - opos_res), + opos_res); + printf("\n"); + } + opos_exp = ++pos_exp; + opos_res = ++pos_res; + } else if (*pos_exp == '\n') { + pos_res++; + } else if (*pos_res == '\n') { + pos_exp++; + } else { + pos_exp++; + pos_res++; + } + } +} + + +static void run_test_select_tree(css_select_ctx *select, + node *node, line_ctx *ctx, + char *buf, size_t *buflen) +{ + css_select_results *sr; + struct node *n = NULL; + + assert(css_select_style(select, node, ctx->media, NULL, + &select_handler, ctx, &sr) == CSS_OK); + + if (node->parent != NULL) { + css_computed_style *composed; + assert(css_computed_style_compose( + node->parent->sr->styles[ctx->pseudo_element], + sr->styles[ctx->pseudo_element], + compute_font_size, NULL, + &composed) == CSS_OK); + css_computed_style_destroy(sr->styles[ctx->pseudo_element]); + sr->styles[ctx->pseudo_element] = composed; + } + + node->sr = sr; + + if (node == ctx->target) { + dump_computed_style(sr->styles[ctx->pseudo_element], + buf, buflen); + } + + for (n = node->children; n != NULL; n = n->next) { + run_test_select_tree(select, n, ctx, buf, buflen); + } +} + + +void run_test(line_ctx *ctx, const char *exp, size_t explen) +{ + css_select_ctx *select; + css_select_results *results; + uint32_t i; + char *buf; + size_t buflen; + static int testnum; + + UNUSED(exp); + + buf = malloc(8192); + if (buf == NULL) { + assert(0 && "No memory for result data"); + } + buflen = 8192; + + assert(css_select_ctx_create(&select) == CSS_OK); + + for (i = 0; i < ctx->n_sheets; i++) { + assert(css_select_ctx_append_sheet(select, + ctx->sheets[i].sheet, ctx->sheets[i].origin, + ctx->sheets[i].media) == CSS_OK); + } + + testnum++; + + run_test_select_tree(select, ctx->tree, ctx, buf, &buflen); + + results = ctx->target->sr; + assert(results->styles[ctx->pseudo_element] != NULL); + + if (8192 - buflen != explen || memcmp(buf, exp, explen) != 0) { + size_t len = 8192 - buflen < explen ? 8192 - buflen : explen; + printf("Expected (%u):\n%.*s\n", + (int) explen, (int) explen, exp); + printf("Result (%u):\n%.*s\n", (int) (8192 - buflen), + (int) (8192 - buflen), buf); + + show_differences(len, exp, buf); + assert(0 && "Result doesn't match expected"); + } + + /* Clean up */ + css_select_ctx_destroy(select); + destroy_tree(ctx->tree); + + for (i = 0; i < ctx->n_sheets; i++) { + css_stylesheet_destroy(ctx->sheets[i].sheet); + } + + ctx->tree = NULL; + ctx->current = NULL; + ctx->depth = 0; + ctx->n_sheets = 0; + free(ctx->sheets); + ctx->sheets = NULL; + ctx->target = NULL; + + free(buf); + + printf("Test %d: PASS\n", testnum); +} + +void destroy_tree(node *root) +{ + node *n, *p; + uint32_t i; + + for (n = root->children; n != NULL; n = p) { + p = n->next; + + destroy_tree(n); + } + + css_select_results_destroy(root->sr); + + for (i = 0; i < root->n_attrs; ++i) { + lwc_string_unref(root->attrs[i].name); + lwc_string_unref(root->attrs[i].value); + } + free(root->attrs); + + if (root->classes != NULL) { + for (i = 0; i < root->n_classes; ++i) { + lwc_string_unref(root->classes[i]); + } + free(root->classes); + } + + if (root->libcss_node_data != NULL) { + css_libcss_node_data_handler(&select_handler, CSS_NODE_DELETED, + NULL, root, NULL, root->libcss_node_data); + } + + lwc_string_unref(root->name); + free(root); +} + + +css_error node_name(void *pw, void *n, css_qname *qname) +{ + node *node = n; + + UNUSED(pw); + + qname->name = lwc_string_ref(node->name); + + return CSS_OK; +} + +static css_error node_classes(void *pw, void *n, + lwc_string ***classes, uint32_t *n_classes) +{ + unsigned int i; + node *node = n; + UNUSED(pw); + + *classes = node->classes; + *n_classes = node->n_classes; + + for (i = 0; i < *n_classes; i++) + (*classes)[i] = lwc_string_ref(node->classes[i]); + + return CSS_OK; + +} + +css_error node_id(void *pw, void *n, + lwc_string **id) +{ + node *node = n; + uint32_t i; + line_ctx *lc = pw; + + for (i = 0; i < node->n_attrs; i++) { + bool amatch = false; + assert(lwc_string_caseless_isequal( + node->attrs[i].name, lc->attr_id, &amatch) == + lwc_error_ok); + if (amatch == true) + break; + } + + if (i != node->n_attrs) + *id = lwc_string_ref(node->attrs[i].value); + else + *id = NULL; + + return CSS_OK; +} + +css_error named_ancestor_node(void *pw, void *n, + const css_qname *qname, + void **ancestor) +{ + node *node = n; + UNUSED(pw); + + for (node = node->parent; node != NULL; node = node->parent) { + bool match = false; + assert(lwc_string_caseless_isequal( + qname->name, node->name, + &match) == lwc_error_ok); + if (match == true) + break; + } + + *ancestor = (void *) node; + + return CSS_OK; +} + +css_error named_parent_node(void *pw, void *n, + const css_qname *qname, + void **parent) +{ + node *node = n; + UNUSED(pw); + + *parent = NULL; + if (node->parent != NULL) { + bool match = false; + assert(lwc_string_caseless_isequal( + qname->name, node->parent->name, &match) == + lwc_error_ok); + if (match == true) + *parent = (void *) node->parent; + } + + return CSS_OK; +} + +css_error named_sibling_node(void *pw, void *n, + const css_qname *qname, + void **sibling) +{ + node *node = n; + UNUSED(pw); + + *sibling = NULL; + if (node->prev != NULL) { + bool match = false; + assert(lwc_string_caseless_isequal( + qname->name, node->prev->name, &match) == + lwc_error_ok); + if (match == true) + *sibling = (void *) node->prev; + } + + return CSS_OK; +} + +css_error named_generic_sibling_node(void *pw, void *n, + const css_qname *qname, + void **sibling) +{ + node *node = n; + UNUSED(pw); + + for (node = node->prev; node != NULL; node = node->prev) { + bool match = false; + assert(lwc_string_caseless_isequal( + qname->name, node->name, + &match) == lwc_error_ok); + if (match == true) + break; + } + + *sibling = (void *) node; + + return CSS_OK; +} + +css_error parent_node(void *pw, void *n, void **parent) +{ + node *node = n; + + UNUSED(pw); + + *parent = (void *) node->parent; + + return CSS_OK; +} + +css_error sibling_node(void *pw, void *n, void **sibling) +{ + node *node = n; + + UNUSED(pw); + + *sibling = (void *) node->prev; + + return CSS_OK; +} + +css_error node_has_name(void *pw, void *n, + const css_qname *qname, + bool *match) +{ + node *node = n; + UNUSED(pw); + + if (lwc_string_length(qname->name) == 1 && + lwc_string_data(qname->name)[0] == '*') + *match = true; + else + assert(lwc_string_caseless_isequal(node->name, + qname->name, match) == lwc_error_ok); + + return CSS_OK; +} + +css_error node_has_class(void *pw, void *n, + lwc_string *name, + bool *match) +{ + node *node = n; + uint32_t i; + line_ctx *ctx = pw; + + for (i = 0; i < node->n_attrs; i++) { + bool amatch = false; + assert(lwc_string_caseless_isequal( + node->attrs[i].name, ctx->attr_class, + &amatch) == lwc_error_ok); + if (amatch == true) + break; + } + + /* Classes are case-sensitive in HTML */ + if (i != node->n_attrs && name == node->attrs[i].value) + *match = true; + else + *match = false; + + return CSS_OK; +} + +css_error node_has_id(void *pw, void *n, + lwc_string *name, + bool *match) +{ + node *node = n; + uint32_t i; + line_ctx *ctx = pw; + + for (i = 0; i < node->n_attrs; i++) { + bool amatch = false; + assert(lwc_string_caseless_isequal( + node->attrs[i].name, ctx->attr_id, &amatch) == + lwc_error_ok); + if (amatch == true) + break; + } + + /* IDs are case-sensitive in HTML */ + if (i != node->n_attrs && name == node->attrs[i].value) + *match = true; + else + *match = false; + + return CSS_OK; +} + +css_error node_has_attribute(void *pw, void *n, + const css_qname *qname, + bool *match) +{ + node *node = n; + uint32_t i; + UNUSED(pw); + + *match = false; + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + return CSS_OK; +} + +css_error node_has_attribute_equal(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, value, match) == + lwc_error_ok); + } + + return CSS_OK; +} + +css_error node_has_attribute_includes(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + size_t vlen = lwc_string_length(value); + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + const char *p; + const char *start = lwc_string_data(node->attrs[i].value); + const char *end = start + + lwc_string_length(node->attrs[i].value); + + *match = false; + + for (p = start; p < end; p++) { + if (*p == ' ') { + if ((size_t) (p - start) == vlen && + strncasecmp(start, + lwc_string_data(value), + vlen) == 0) { + *match = true; + break; + } + + start = p + 1; + } + } + } + + return CSS_OK; +} + +css_error node_has_attribute_dashmatch(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + size_t vlen = lwc_string_length(value); + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + const char *p; + const char *start = lwc_string_data(node->attrs[i].value); + const char *end = start + + lwc_string_length(node->attrs[i].value); + + *match = false; + + for (p = start; p < end; p++) { + if (*p == '-') { + if ((size_t) (p - start) == vlen && + strncasecmp(start, + lwc_string_data(value), + vlen) == 0) { + *match = true; + break; + } + + start = p + 1; + } + } + } + + return CSS_OK; +} + +css_error node_has_attribute_prefix(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + size_t len = lwc_string_length(node->attrs[i].value); + const char *data = lwc_string_data(node->attrs[i].value); + + size_t vlen = lwc_string_length(value); + const char *vdata = lwc_string_data(value); + + if (len < vlen) + *match = false; + else + *match = (strncasecmp(data, vdata, vlen) == 0); + } + + return CSS_OK; +} + +css_error node_has_attribute_suffix(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + size_t len = lwc_string_length(node->attrs[i].value); + const char *data = lwc_string_data(node->attrs[i].value); + + size_t vlen = lwc_string_length(value); + const char *vdata = lwc_string_data(value); + + size_t suffix_start = len - vlen; + + if (len < vlen) + *match = false; + else { + *match = (strncasecmp(data + suffix_start, + vdata, vlen) == 0); + } + } + + return CSS_OK; +} + +css_error node_has_attribute_substring(void *pw, void *n, + const css_qname *qname, + lwc_string *value, + bool *match) +{ + node *node = n; + uint32_t i; + UNUSED(pw); + + *match = false; + + for (i = 0; i < node->n_attrs; i++) { + assert(lwc_string_caseless_isequal( + node->attrs[i].name, qname->name, match) == + lwc_error_ok); + if (*match == true) + break; + } + + if (*match == true) { + size_t len = lwc_string_length(node->attrs[i].value); + const char *data = lwc_string_data(node->attrs[i].value); + + size_t vlen = lwc_string_length(value); + const char *vdata = lwc_string_data(value); + + const char *last_start = data + len - vlen; + + if (len < vlen) + *match = false; + else { + while (data <= last_start) { + if (strncasecmp(data, vdata, vlen) == 0) { + *match = true; + break; + } + + data++; + } + + if (data > last_start) + *match = false; + } + } + + return CSS_OK; +} + +css_error node_is_root(void *pw, void *n, bool *match) +{ + node *node = n; + UNUSED(pw); + + *match = (node->parent == NULL); + + return CSS_OK; +} + +css_error node_count_siblings(void *pw, void *n, + bool same_name, bool after, int32_t *count) +{ + int32_t cnt = 0; + bool match = false; + node *node = n; + lwc_string *name = node->name; + UNUSED(pw); + + if (after) { + while (node->next != NULL) { + if (same_name) { + assert(lwc_string_caseless_isequal( + name, node->next->name, &match) == + lwc_error_ok); + + if (match) + cnt++; + } else { + cnt++; + } + + node = node->next; + } + } else { + while (node->prev != NULL) { + if (same_name) { + assert(lwc_string_caseless_isequal( + name, node->prev->name, &match) == + lwc_error_ok); + + if (match) + cnt++; + } else { + cnt++; + } + + node = node->prev; + } + } + + *count = cnt; + + return CSS_OK; +} + +css_error node_is_empty(void *pw, void *n, bool *match) +{ + node *node = n; + UNUSED(pw); + + *match = (node->children == NULL); + + return CSS_OK; +} + +css_error node_is_link(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_visited(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_hover(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_active(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_focus(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_enabled(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_disabled(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_checked(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_target(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_lang(void *pw, void *n, + lwc_string *lang, + bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + UNUSED(lang); + + *match = false; + + return CSS_OK; +} + +css_error node_presentational_hint(void *pw, void *node, + uint32_t *nhints, css_hint **hints) +{ + UNUSED(pw); + UNUSED(node); + + *nhints = 0; + *hints = NULL; + + return CSS_OK; +} + +css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint) +{ + UNUSED(pw); + + if (property == CSS_PROP_COLOR) { + hint->data.color = 0xff000000; + hint->status = CSS_COLOR_COLOR; + } else if (property == CSS_PROP_FONT_FAMILY) { + hint->data.strings = NULL; + hint->status = CSS_FONT_FAMILY_SANS_SERIF; + } else if (property == CSS_PROP_QUOTES) { + /* Not exactly useful :) */ + hint->data.strings = NULL; + hint->status = CSS_QUOTES_NONE; + } else if (property == CSS_PROP_VOICE_FAMILY) { + /** \todo Fix this when we have voice-family done */ + hint->data.strings = NULL; + hint->status = 0; + } else { + return CSS_INVALID; + } + + return CSS_OK; +} + +css_error compute_font_size(void *pw, const css_hint *parent, css_hint *size) +{ + static css_hint_length sizes[] = { + { FLTTOFIX(6.75), CSS_UNIT_PT }, + { FLTTOFIX(7.50), CSS_UNIT_PT }, + { FLTTOFIX(9.75), CSS_UNIT_PT }, + { FLTTOFIX(12.0), CSS_UNIT_PT }, + { FLTTOFIX(13.5), CSS_UNIT_PT }, + { FLTTOFIX(18.0), CSS_UNIT_PT }, + { FLTTOFIX(24.0), CSS_UNIT_PT } + }; + const css_hint_length *parent_size; + + UNUSED(pw); + + /* Grab parent size, defaulting to medium if none */ + if (parent == NULL) { + parent_size = &sizes[CSS_FONT_SIZE_MEDIUM - 1]; + } else { + assert(parent->status == CSS_FONT_SIZE_DIMENSION); + assert(parent->data.length.unit != CSS_UNIT_EM); + assert(parent->data.length.unit != CSS_UNIT_EX); + parent_size = &parent->data.length; + } + + assert(size->status != CSS_FONT_SIZE_INHERIT); + + if (size->status < CSS_FONT_SIZE_LARGER) { + /* Keyword -- simple */ + size->data.length = sizes[size->status - 1]; + } else if (size->status == CSS_FONT_SIZE_LARGER) { + /** \todo Step within table, if appropriate */ + size->data.length.value = + FMUL(parent_size->value, FLTTOFIX(1.2)); + size->data.length.unit = parent_size->unit; + } else if (size->status == CSS_FONT_SIZE_SMALLER) { + /** \todo Step within table, if appropriate */ + size->data.length.value = + FMUL(parent_size->value, FLTTOFIX(1.2)); + size->data.length.unit = parent_size->unit; + } else if (size->data.length.unit == CSS_UNIT_EM || + size->data.length.unit == CSS_UNIT_EX) { + size->data.length.value = + FMUL(size->data.length.value, parent_size->value); + + if (size->data.length.unit == CSS_UNIT_EX) { + size->data.length.value = FMUL(size->data.length.value, + FLTTOFIX(0.6)); + } + + size->data.length.unit = parent_size->unit; + } else if (size->data.length.unit == CSS_UNIT_PCT) { + size->data.length.value = FDIV(FMUL(size->data.length.value, + parent_size->value), FLTTOFIX(100)); + size->data.length.unit = parent_size->unit; + } + + size->status = CSS_FONT_SIZE_DIMENSION; + + return CSS_OK; +} + +static css_error set_libcss_node_data(void *pw, void *n, + void *libcss_node_data) +{ + node *node = n; + UNUSED(pw); + + node->libcss_node_data = libcss_node_data; + + return CSS_OK; +} + +static css_error get_libcss_node_data(void *pw, void *n, + void **libcss_node_data) +{ + node *node = n; + UNUSED(pw); + + /* Pass any node data back to libcss */ + *libcss_node_data = node->libcss_node_data; + + return CSS_OK; +} + + -- cgit v1.2.3 From da2c006495db400134c3e788e398cbcba1dba1d0 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 22 Nov 2015 20:18:08 +0000 Subject: Make node data contain list of partial node styles. --- src/select/computed.h | 4 ++++ src/select/select.c | 26 ++++++++++++++++++++++++-- src/select/select.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/select/computed.h b/src/select/computed.h index 57981b2..f77bda2 100644 --- a/src/select/computed.h +++ b/src/select/computed.h @@ -338,6 +338,10 @@ static inline css_computed_style * css__computed_style_ref( if (style == NULL) return NULL; + if (style->i.uncommon != NULL) { + style->i.uncommon->count++; + } + style->count++; return style; } diff --git a/src/select/select.c b/src/select/select.c index 5fef4e4..ec01d32 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -170,12 +170,21 @@ static css_error css__create_node_data(struct css_node_data **node_data) static void css__destroy_node_data(struct css_node_data *node_data) { + int i; + assert(node_data != NULL); if (node_data->bloom != NULL) { free(node_data->bloom); } + for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) { + if (node_data->partial.styles[i] != NULL) { + css_computed_style_destroy( + node_data->partial.styles[i]); + } + } + free(node_data); } @@ -651,18 +660,31 @@ cleanup: static css_error css__set_node_data(void *node, css_select_state *state, css_select_handler *handler, void *pw) { + int i; css_error error; css_bloom *bloom; + css_select_results *results; + + struct css_node_data *node_data = state->node_data; /* Set node bloom filter */ error = css__create_node_bloom(&bloom, state); if (error != CSS_OK) { return error; } - state->node_data->bloom = bloom; + node_data->bloom = bloom; - error = handler->set_libcss_node_data(pw, node, state->node_data); + /* Set selection results */ + results = state->results; + for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) { + node_data->partial.styles[i] = + css__computed_style_ref(results->styles[i]); + } + + error = handler->set_libcss_node_data(pw, node, node_data); if (error != CSS_OK) { + css__destroy_node_data(node_data); + state->node_data = NULL; return error; } diff --git a/src/select/select.h b/src/select/select.h index 196914d..254b095 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -32,6 +32,7 @@ typedef struct prop_state { } prop_state; struct css_node_data { + css_select_results partial; css_bloom *bloom; }; -- cgit v1.2.3 From f198d30c40c9358e964aa273d9ff9779bffaa6ad Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 25 Sep 2016 21:23:05 +0100 Subject: Selection: Split out selection state {initi|fin}alisation. --- src/select/select.c | 244 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 95 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index ec01d32..aad90bd 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -546,18 +546,19 @@ static css_error css__get_parent_bloom(void *parent, uint32_t i; /* Need to create parent bloom */ - /* TODO: - * Build & set the parent node's bloom properly. This will - * speed up the case where DOM change has caused bloom to get - * deleted. For now we fall back to a fully satruated bloom - * filter, which is slower but perfectly valid. - */ - bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); - if (bloom == NULL) { - return CSS_NOMEM; - } if (parent != NULL) { - /* Have to make up fully saturated bloom filter */ + /* TODO: + * Build & set the parent node's bloom properly. + * This will speed up the case where DOM change + * has caused bloom to get deleted. For now we + * fall back to a fully satruated bloom filter, + * which is slower but perfectly valid. + */ + bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); + if (bloom == NULL) { + return CSS_NOMEM; + } + for (i = 0; i < CSS_BLOOM_SIZE; i++) { bloom[i] = ~0; } @@ -580,9 +581,17 @@ static css_error css__get_parent_bloom(void *parent, } } else { /* No ancestors; empty bloom filter */ - for (i = 0; i < CSS_BLOOM_SIZE; i++) { - bloom[i] = 0; - } + /* The parent bloom is owned by the parent node's + * node data. However, for the root node, there is + * no parent node to own the bloom filter. + * As such, we just use a pointer to static storage + * so calling code doesn't need to worry about + * whether the returned parent bloom is owned + * by something or not. + * Note, parent bloom is only read from, and not + * written to. */ + static css_bloom empty_bloom[CSS_BLOOM_SIZE]; + bloom = empty_bloom; } } @@ -694,6 +703,123 @@ static css_error css__set_node_data(void *node, css_select_state *state, } +/** + * Finalise a selection state, releasing any resources it owns + * + * \param[in] state The selection state to finalise. + */ +static void css_select__finalise_selection_state( + css_select_state *state) +{ + if (state->results != NULL) { + css_select_results_destroy(state->results); + } + + if (state->node_data != NULL) { + css__destroy_node_data(state->node_data); + } + + if (state->classes != NULL) { + for (uint32_t i = 0; i < state->n_classes; i++) { + lwc_string_unref(state->classes[i]); + } + } + + if (state->id != NULL) { + lwc_string_unref(state->id); + } + + if (state->element.ns != NULL) { + lwc_string_unref(state->element.ns); + } + + if (state->element.name != NULL){ + lwc_string_unref(state->element.name); + } +} + + +/** + * Initialise a selection state. + * + * \param[in] state The selection state to initialise + * \param[in] node The node we are selecting for. + * \param[in] parent The node's parent node, or NULL. + * \param[in] media The media type we're selecting for. + * \param[in] handler The client selection callback table. + * \param[in] pw The client private data, passsed out to callbacks. + * \return CSS_OK or appropriate error otherwise. + */ +static css_error css_select__initialise_selection_state( + css_select_state *state, + void *node, + void *parent, + uint64_t media, + css_select_handler *handler, + void *pw) +{ + css_error error; + + /* Set up the selection state */ + memset(state, 0, sizeof(*state)); + state->node = node; + state->media = media; + state->handler = handler; + state->pw = pw; + state->next_reject = state->reject_cache + + (N_ELEMENTS(state->reject_cache) - 1); + + /* Allocate the result set */ + state->results = calloc(1, sizeof(css_select_results)); + if (state->results == NULL) { + return CSS_NOMEM; + } + + /* Base element style is guaranteed to exist */ + error = css__computed_style_create( + &state->results->styles[CSS_PSEUDO_ELEMENT_NONE]); + if (error != CSS_OK) { + goto failed; + } + + error = css__create_node_data(&state->node_data); + if (error != CSS_OK) { + goto failed; + } + + error = css__get_parent_bloom(parent, handler, pw, + &state->node_data->bloom); + if (error != CSS_OK) { + goto failed; + } + + /* Get node's name */ + error = handler->node_name(pw, node, &state->element); + if (error != CSS_OK){ + goto failed; + } + + /* Get node's ID, if any */ + error = handler->node_id(pw, node, &state->id); + if (error != CSS_OK){ + goto failed; + } + + /* Get node's classes, if any */ + error = handler->node_classes(pw, node, + &state->classes, &state->n_classes); + if (error != CSS_OK){ + goto failed; + } + + return CSS_OK; + +failed: + css_select__finalise_selection_state(state); + return error; +} + + /** * Select a style for the given node * @@ -724,7 +850,6 @@ css_error css_select_style(css_select_ctx *ctx, void *node, uint32_t i, j, nhints; css_error error; css_select_state state; - css_bloom *parent_bloom = NULL; css_hint *hints = NULL; void *parent = NULL; @@ -732,62 +857,14 @@ css_error css_select_style(css_select_ctx *ctx, void *node, handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) return CSS_BADPARM; - /* Set up the selection state */ - memset(&state, 0, sizeof(css_select_state)); - state.node = node; - state.media = media; - state.handler = handler; - state.pw = pw; - state.node_data = NULL; - state.next_reject = state.reject_cache + - (N_ELEMENTS(state.reject_cache) - 1); - - /* Allocate the result set */ - state.results = malloc(sizeof(css_select_results)); - if (state.results == NULL) - return CSS_NOMEM; - - for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) - state.results->styles[i] = NULL; - - /* Base element style is guaranteed to exist */ - error = css__computed_style_create( - &state.results->styles[CSS_PSEUDO_ELEMENT_NONE]); - if (error != CSS_OK) { - free(state.results); - return error; - } - - error = css__create_node_data(&state.node_data); - if (error != CSS_OK) { - goto cleanup; - } - error = handler->parent_node(pw, node, &parent); if (error != CSS_OK) - goto cleanup; - - error = css__get_parent_bloom(parent, handler, pw, &parent_bloom); - if (error != CSS_OK) { - goto cleanup; - } - state.node_data->bloom = parent_bloom; - - /* Get node's name */ - error = handler->node_name(pw, node, &state.element); - if (error != CSS_OK) - goto cleanup; - - /* Get node's ID, if any */ - error = handler->node_id(pw, node, &state.id); - if (error != CSS_OK) - goto cleanup; + return error; - /* Get node's classes, if any */ - error = handler->node_classes(pw, node, - &state.classes, &state.n_classes); + error = css_select__initialise_selection_state( + &state, node, parent, media, handler, pw); if (error != CSS_OK) - goto cleanup; + return error; /* Apply presentational hints */ error = handler->node_presentational_hint(pw, node, &nhints, &hints); @@ -927,38 +1004,15 @@ css_error css_select_style(css_select_ctx *ctx, void *node, goto cleanup; } + /* Steal the results from the selection state, so they don't get + * freed when the selection state is finalised */ *result = state.results; + state.results = NULL; + error = CSS_OK; cleanup: - /* Only clean up the results if there's an error. - * If there is no error, we're going to pass ownership of - * the results to the client */ - if (error != CSS_OK && state.results != NULL) { - css_select_results_destroy(state.results); - } - - /* If there's no parent, the parent_bloom is not owned by any node, - * so we need to free it. */ - if (parent == NULL) { - free(parent_bloom); - } - - if (state.node_data != NULL) { - css__destroy_node_data(state.node_data); - } - - if (state.classes != NULL) { - for (i = 0; i < state.n_classes; i++) - lwc_string_unref(state.classes[i]); - } - - if (state.id != NULL) - lwc_string_unref(state.id); - - if (state.element.ns != NULL) - lwc_string_unref(state.element.ns); - lwc_string_unref(state.element.name); + css_select__finalise_selection_state(&state); return error; } -- cgit v1.2.3 From 7cb09396a547709ad55a195af825fc8bb74607fd Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 15 Dec 2015 20:12:52 +0000 Subject: Optimisation: Bypass selection by sharing previous sibling's style. --- src/select/select.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/select/select.h | 7 ++ 2 files changed, 310 insertions(+), 15 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index aad90bd..692486d 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -703,6 +703,225 @@ static css_error css__set_node_data(void *node, css_select_state *state, } +/** The releationship of a share candidate node to the selection node. */ +enum share_candidate_type { + CANDIDATE_SIBLING, + CANDIDATE_COUSIN, +}; + + +/** + * Get node_data for candidate node if we can reuse its style. + * + * \param[in] state The selection state for current node. + * \param[in] share_candidate_node The node to test id and classes of. + * \param[in] type The candidate's relation to selection node. + * \param[out] sharable_node_data Returns node_data or NULL. + * \return CSS_OK on success, appropriate error otherwise. + */ +static css_error css_select_style__get_sharable_node_data_for_candidate( + css_select_state *state, + void *share_candidate_node, + enum share_candidate_type type, + struct css_node_data **sharable_node_data) +{ + css_error error; + lwc_string *share_candidate_id; + uint32_t share_candidate_n_classes; + lwc_string **share_candidate_classes; + struct css_node_data *node_data; + + UNUSED(type); + + *sharable_node_data = NULL; + + /* We get the candidate node data first, as if it has none, we can't + * share its data anyway. + * Hideous casting to avoid warnings on all platforms we build for. */ + error = state->handler->get_libcss_node_data(state->pw, + share_candidate_node, (void **) (void *) &node_data); + if (error != CSS_OK || node_data == NULL) { + return error; + } + + /* If one node has hints and other doesn't then can't share */ + if ((node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) != + (state->node_data->flags & CSS_NODE_FLAGS_HAS_HINTS)) { + return CSS_OK; + } + + /* If the node was affected by attribute or pseudo class rules, + * it's not a candidate for sharing */ + if (node_data->flags & ( + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS | + CSS_NODE_FLAGS_TAINT_ATTRIBUTE | + CSS_NODE_FLAGS_TAINT_SIBLING)) { + return CSS_OK; + } + + /* Check candidate ID doesn't prevent sharing */ + error = state->handler->node_id(state->pw, + share_candidate_node, + &share_candidate_id); + if (error != CSS_OK) { + return error; + + } else if (share_candidate_id != NULL) { + lwc_string_unref(share_candidate_id); + return CSS_OK; + } + + /* Check candidate classes don't prevent sharing */ + error = state->handler->node_classes(state->pw, + share_candidate_node, + &share_candidate_classes, + &share_candidate_n_classes); + if (error != CSS_OK) { + return error; + } + + if (state->n_classes != share_candidate_n_classes) { + goto cleanup; + } + + /* TODO: no need to care about the order, but it's simpler to + * have an ordered match, and authors are more likely to be + * consistent than not. */ + for (uint32_t i = 0; i < share_candidate_n_classes; i++) { + bool match; + if (lwc_string_caseless_isequal( + state->classes[i], + share_candidate_classes[i], + &match) == lwc_error_ok && + match == false) { + goto cleanup; + } + } + + if (node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) { + /* TODO: check hints match. For now, just prevent sharing */ + goto cleanup; + } + + *sharable_node_data = node_data; + +cleanup: + if (share_candidate_classes != NULL) { + for (uint32_t i = 0; i < share_candidate_n_classes; i++) { + lwc_string_unref(share_candidate_classes[i]); + } + } + + return CSS_OK; +} + + +/** + * Get previous named cousin node. + * + * \param[in] state The selection state for current node. + * \param[in] node The node to get the cousin of. + * \param[out] cousin_out Returns a cousin node or NULL. + * \return CSS_OK on success or appropriate error otherwise. + */ +static css_error css_select_style__get_named_cousin( + css_select_state *state, void *node, + void **cousin_out) +{ + /* TODO: + * + * Consider cousin nodes; Go to parent's previous sibling's last child. + * The parent and the parent's sibling must be "similar". + */ + UNUSED(state); + UNUSED(node); + + *cousin_out = NULL; + + return CSS_OK; +} + + +/** + * Get node_data for any node that we can reuse the style for. + * + * This is an optimisation to needing to perform selection for a node, + * by sharing the style for a previous node. + * + * \param[in] node Node we're selecting for. + * \param[in] state The current selection state. + * \param[out] sharable_node_data Returns node_data or NULL. + * \return CSS_OK on success or appropriate error otherwise. + */ +static css_error css_select_style__get_sharable_node_data( + void *node, css_select_state *state, + struct css_node_data **sharable_node_data) +{ + css_error error; + enum share_candidate_type type = CANDIDATE_SIBLING; + + *sharable_node_data = NULL; + + /* TODO: move this test to caller? */ + if (state->id != NULL) { + /* If the node has an ID can't share another node's style. */ + /* TODO: Consider whether this ID exists in the ID hash tables. + * (If not, the ID cannot affect the node's style.) + * + * Call css__selector_hash_find_by_id, for each sheet, + * and if we get a non-NULL "matched" then return. + * + * Check overhead is worth cost. */ + return CSS_OK; + } + + while (true) { + void *share_candidate_node; + + /* Get previous sibling with same element name */ + error = state->handler->named_generic_sibling_node(state->pw, + node, &state->element, &share_candidate_node); + if (error != CSS_OK) { + return error; + } else { + if (share_candidate_node == NULL) { + error = css_select_style__get_named_cousin( + state, node, + &share_candidate_node); + if (error != CSS_OK) { + return error; + } else { + if (share_candidate_node == NULL) { + break; + } + } + type = CANDIDATE_COUSIN; + } + } + + /* Check whether we can share the candidate node's + * style. We already know the element names match, + * check that candidate node's ID and class won't + * prevent sharing. */ + error = css_select_style__get_sharable_node_data_for_candidate( + state, share_candidate_node, + type, sharable_node_data); + if (error != CSS_OK) { + return error; + } else { + if (sharable_node_data == NULL) { + /* Can't share with this; look for another */ + continue; + } else { + break; + } + } + } + + return CSS_OK; +} + + /** * Finalise a selection state, releasing any resources it owns * @@ -775,13 +994,6 @@ static css_error css_select__initialise_selection_state( return CSS_NOMEM; } - /* Base element style is guaranteed to exist */ - error = css__computed_style_create( - &state->results->styles[CSS_PSEUDO_ELEMENT_NONE]); - if (error != CSS_OK) { - goto failed; - } - error = css__create_node_data(&state->node_data); if (error != CSS_OK) { goto failed; @@ -852,6 +1064,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, css_select_state state; css_hint *hints = NULL; void *parent = NULL; + struct css_node_data *share; if (ctx == NULL || node == NULL || result == NULL || handler == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) @@ -866,20 +1079,41 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) return error; - /* Apply presentational hints */ + /* Fetch presentational hints */ error = handler->node_presentational_hint(pw, node, &nhints, &hints); if (error != CSS_OK) goto cleanup; + if (nhints > 0) { + state.node_data->flags |= CSS_NODE_FLAGS_HAS_HINTS; + } + + /* Check if we can share another node's style */ + error = css_select_style__get_sharable_node_data(node, &state, &share); + if (error != CSS_OK) { + goto cleanup; + } else if (share != NULL) { + css_computed_style **styles = share->partial.styles; + for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) { + state.results->styles[i] = + css__computed_style_ref(styles[i]); + } + goto complete; + } + + /* Not sharing; need to select. + * Base element style is guaranteed to exist + */ + error = css__computed_style_create( + &state.results->styles[CSS_PSEUDO_ELEMENT_NONE]); + if (error != CSS_OK) { + goto cleanup; + } + + /* Apply any hints */ 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) - goto cleanup; - } - state.results->styles[CSS_PSEUDO_ELEMENT_NONE] = computed_style; state.computed = computed_style; for (i = 0; i < nhints; i++) { @@ -999,6 +1233,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } +complete: error = css__set_node_data(node, &state, handler, pw); if (error != CSS_OK) { goto cleanup; @@ -2033,6 +2268,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, n, &selector->data.qname, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_GENERIC_SIBLING: error = state->handler->named_generic_sibling_node( @@ -2040,6 +2279,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } case CSS_COMBINATOR_NONE: break; } @@ -2128,6 +2371,10 @@ css_error match_universal_combinator(css_select_ctx *ctx, css_combinator type, error = state->handler->sibling_node(state->pw, n, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_NONE: break; @@ -2395,8 +2642,17 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else if (detail->qname.name == ctx->checked) { error = state->handler->node_is_checked(state->pw, node, match); - } else + } else { *match = false; + } + /* If the node in question is the node we're selecting for + * then its style has been tainted by pseudo class specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; + } break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; @@ -2415,36 +2671,68 @@ css_error match_detail(css_select_ctx *ctx, void *node, case CSS_SELECTOR_ATTRIBUTE: error = state->handler->node_has_attribute(state->pw, node, &detail->qname, match); + /* If the node in question is the node we're selecting for + * then its style has been tainted by attribute specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_EQUAL: error = state->handler->node_has_attribute_equal(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_DASHMATCH: error = state->handler->node_has_attribute_dashmatch(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_INCLUDES: error = state->handler->node_has_attribute_includes(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_PREFIX: error = state->handler->node_has_attribute_prefix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUFFIX: error = state->handler->node_has_attribute_suffix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUBSTRING: error = state->handler->node_has_attribute_substring(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; } diff --git a/src/select/select.h b/src/select/select.h index 254b095..96f4546 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -34,6 +34,13 @@ typedef struct prop_state { struct css_node_data { css_select_results partial; css_bloom *bloom; + enum { + CSS_NODE_FLAGS_NONE = 0, + CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 1), + CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 2), + CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 3), + } flags; }; /** -- cgit v1.2.3 From e64ebec323ae044f1977a2933696163ebeeb6c22 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 16 Oct 2016 18:40:24 +0100 Subject: Documentation: Function param comment fix. --- src/select/select.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/select/select.c b/src/select/select.c index 692486d..f6b1b12 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -1037,7 +1037,6 @@ failed: * * \param ctx Selection context to use * \param node Node to select style for - * \param bloom Node's bloom filter filled with ancestor tag,id,class * \param media Currently active media types * \param inline_style Corresponding inline style for node, or NULL * \param handler Dispatch table of handler functions -- cgit v1.2.3 From 7a80bc8f0c44c7bab5abcaf87059b7bb3d710499 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 17 Oct 2016 09:20:30 +0100 Subject: Debug for recording which nodes fail to share style and why. --- src/select/select.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/select/select.c b/src/select/select.c index f6b1b12..068257f 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -28,6 +28,9 @@ /* Define this to enable verbose messages when matching selector chains */ #undef DEBUG_CHAIN_MATCHING +/* Define this to enable verbose messages when attempting to share styles */ +#undef DEBUG_STYLE_SHARING + /** * Container for stylesheet selection info */ @@ -741,12 +744,20 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( error = state->handler->get_libcss_node_data(state->pw, share_candidate_node, (void **) (void *) &node_data); if (error != CSS_OK || node_data == NULL) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: no candidate node data\n", + lwc_string_data(state->element.name)); +#endif return error; } /* If one node has hints and other doesn't then can't share */ if ((node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) != (state->node_data->flags & CSS_NODE_FLAGS_HAS_HINTS)) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: have hints mismatch\n", + lwc_string_data(state->element.name)); +#endif return CSS_OK; } @@ -756,6 +767,19 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS | CSS_NODE_FLAGS_TAINT_ATTRIBUTE | CSS_NODE_FLAGS_TAINT_SIBLING)) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: candidate flags: %s%s%s\n", + lwc_string_data(state->element.name), + (node_data->flags & + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS) ? + "PSEUDOCLASS" : "", + (node_data->flags & + CSS_NODE_FLAGS_TAINT_ATTRIBUTE) ? + " ATTRIBUTE" : "", + (node_data->flags & + CSS_NODE_FLAGS_TAINT_SIBLING) ? + " SIBLING" : ""); +#endif return CSS_OK; } @@ -768,6 +792,10 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( } else if (share_candidate_id != NULL) { lwc_string_unref(share_candidate_id); +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: candidate id\n", + lwc_string_data(state->element.name)); +#endif return CSS_OK; } @@ -781,6 +809,10 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( } if (state->n_classes != share_candidate_n_classes) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: class count mismatch\n", + lwc_string_data(state->element.name)); +#endif goto cleanup; } @@ -794,12 +826,20 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( share_candidate_classes[i], &match) == lwc_error_ok && match == false) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: class mismatch\n", + lwc_string_data(state->element.name)); +#endif goto cleanup; } } if (node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) { /* TODO: check hints match. For now, just prevent sharing */ +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: hints\n", + lwc_string_data(state->element.name)); +#endif goto cleanup; } @@ -872,6 +912,9 @@ static css_error css_select_style__get_sharable_node_data( * and if we get a non-NULL "matched" then return. * * Check overhead is worth cost. */ +#ifdef DEBUG_STYLE_SHARING +printf(" \t%s\tno share: node id (%s)\n", lwc_string_data(state->element.name), lwc_string_data(state->id)); +#endif return CSS_OK; } @@ -1096,8 +1139,15 @@ css_error css_select_style(css_select_ctx *ctx, void *node, state.results->styles[i] = css__computed_style_ref(styles[i]); } +#ifdef DEBUG_STYLE_SHARING + printf("style:\t%s\tSHARED!\n", + lwc_string_data(state.element.name)); +#endif goto complete; } +#ifdef DEBUG_STYLE_SHARING + printf("style:\t%s\tSELECTED\n", lwc_string_data(state.element.name)); +#endif /* Not sharing; need to select. * Base element style is guaranteed to exist -- cgit v1.2.3 From ffe1de36ded35058f082a3185615b55ca0668996 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 22 Oct 2016 12:06:12 +0100 Subject: Selection: Abstract common node flags setting code into helper. --- src/select/select.c | 66 ++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index 068257f..4b9497c 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -2361,6 +2361,18 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, return CSS_OK; } +static inline void add_node_flags(const void *node, + const css_select_state *state, css_node_flags flags) +{ + /* If the node in question is the node we're selecting for then its + * style has been tainted by particular rules that affect whether the + * node's style can be shared. We don't care whether the rule matched + * or not, just that such a rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= flags; + } +} + css_error match_universal_combinator(css_select_ctx *ctx, css_combinator type, const css_selector *selector, css_select_state *state, void *node, bool may_optimise, bool *rejected_by_cache, @@ -2420,10 +2432,8 @@ css_error match_universal_combinator(css_select_ctx *ctx, css_combinator type, error = state->handler->sibling_node(state->pw, n, &n); if (error != CSS_OK) return error; - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_SIBLING; - } + add_node_flags(node, state, + CSS_NODE_FLAGS_TAINT_SIBLING); break; case CSS_COMBINATOR_NONE: break; @@ -2694,14 +2704,7 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else { *match = false; } - /* If the node in question is the node we're selecting for - * then its style has been tainted by pseudo class specific - * rules. We don't care whether the rule matched or not, - * just that such rule has been considered. */ - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS); break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; @@ -2720,68 +2723,43 @@ css_error match_detail(css_select_ctx *ctx, void *node, case CSS_SELECTOR_ATTRIBUTE: error = state->handler->node_has_attribute(state->pw, node, &detail->qname, match); - /* If the node in question is the node we're selecting for - * then its style has been tainted by attribute specific - * rules. We don't care whether the rule matched or not, - * just that such rule has been considered. */ - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_EQUAL: error = state->handler->node_has_attribute_equal(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_DASHMATCH: error = state->handler->node_has_attribute_dashmatch(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_INCLUDES: error = state->handler->node_has_attribute_includes(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_PREFIX: error = state->handler->node_has_attribute_prefix(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_SUFFIX: error = state->handler->node_has_attribute_suffix(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; case CSS_SELECTOR_ATTRIBUTE_SUBSTRING: error = state->handler->node_has_attribute_substring(state->pw, node, &detail->qname, detail->value.string, match); - if (node == state->node) { - state->node_data->flags |= - CSS_NODE_FLAGS_TAINT_ATTRIBUTE; - } + add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_ATTRIBUTE); break; } -- cgit v1.2.3 From ce28a1a8cb638ec2563f375277ee4950f5eb4bde Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 23 Oct 2016 15:57:43 +0100 Subject: Enable sharing where pseudo common pseudo classes are the same. --- src/select/select.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/select/select.h | 28 ++++++++++++++++++------- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index 4b9497c..1719b7f 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -30,6 +30,7 @@ /* Define this to enable verbose messages when attempting to share styles */ #undef DEBUG_STYLE_SHARING +#define DEBUG_STYLE_SHARING /** * Container for stylesheet selection info @@ -761,6 +762,19 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( return CSS_OK; } + /* If the node and candidate node had different pseudo classes, we + * can't share. */ + if ((node_data->flags & CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK) != + (state->node_data->flags & + CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK)) { +#ifdef DEBUG_STYLE_SHARING + printf(" \t%s\tno share: different pseudo classes\n", + lwc_string_data(state->element.name)); +#endif + return CSS_OK; + + } + /* If the node was affected by attribute or pseudo class rules, * it's not a candidate for sharing */ if (node_data->flags & ( @@ -1021,6 +1035,7 @@ static css_error css_select__initialise_selection_state( void *pw) { css_error error; + bool match; /* Set up the selection state */ memset(state, 0, sizeof(*state)); @@ -1067,6 +1082,42 @@ static css_error css_select__initialise_selection_state( goto failed; } + /* Node pseudo classes */ + error = handler->node_is_link(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_LINK; + } + + error = handler->node_is_visited(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED; + } + + error = handler->node_is_hover(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER; + } + + error = handler->node_is_active(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE; + } + + error = handler->node_is_focus(pw, node, &match); + if (error != CSS_OK){ + goto failed; + } else if (match) { + state->node_data->flags |= CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS; + } + return CSS_OK; failed: @@ -2534,6 +2585,7 @@ css_error match_detail(css_select_ctx *ctx, void *node, { bool is_root = false; css_error error = CSS_OK; + css_node_flags flags = CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; switch (detail->type) { case CSS_SELECTOR_ELEMENT: @@ -2674,18 +2726,23 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else if (detail->qname.name == ctx->link) { error = state->handler->node_is_link(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->visited) { error = state->handler->node_is_visited(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->hover) { error = state->handler->node_is_hover(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->active) { error = state->handler->node_is_active(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->focus) { error = state->handler->node_is_focus(state->pw, node, match); + flags = CSS_NODE_FLAGS_NONE; } else if (detail->qname.name == ctx->target) { error = state->handler->node_is_target(state->pw, node, match); @@ -2704,7 +2761,7 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else { *match = false; } - add_node_flags(node, state, CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS); + add_node_flags(node, state, flags); break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; diff --git a/src/select/select.h b/src/select/select.h index 96f4546..1d9a813 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -31,16 +31,30 @@ typedef struct prop_state { inherit : 1; /* Property is set to inherit */ } prop_state; + +typedef enum css_node_flags { + CSS_NODE_FLAGS_NONE = 0, + CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE = (1 << 1), + CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS = (1 << 2), + CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER = (1 << 3), + CSS_NODE_FLAGS_PSEUDO_CLASS_LINK = (1 << 4), + CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED = (1 << 5), + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 6), + CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 7), + CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 8), + CSS_NODE_FLAGS__PSEUDO_CLASSES_MASK = + (CSS_NODE_FLAGS_PSEUDO_CLASS_ACTIVE | + CSS_NODE_FLAGS_PSEUDO_CLASS_FOCUS | + CSS_NODE_FLAGS_PSEUDO_CLASS_HOVER | + CSS_NODE_FLAGS_PSEUDO_CLASS_LINK | + CSS_NODE_FLAGS_PSEUDO_CLASS_VISITED), +} css_node_flags; + struct css_node_data { css_select_results partial; css_bloom *bloom; - enum { - CSS_NODE_FLAGS_NONE = 0, - CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), - CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 1), - CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 2), - CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 3), - } flags; + css_node_flags flags; }; /** -- cgit v1.2.3 From 216d0931dd56af5043218ccdf3dd99d5c6216979 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 19 Nov 2016 14:50:42 +0000 Subject: Selection: Turn off style sharing debug output. --- src/select/select.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/select/select.c b/src/select/select.c index 1719b7f..e46134c 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -30,7 +30,6 @@ /* Define this to enable verbose messages when attempting to share styles */ #undef DEBUG_STYLE_SHARING -#define DEBUG_STYLE_SHARING /** * Container for stylesheet selection info -- cgit v1.2.3