From fdd5d5f6a27e1f072bd8ba0735c4c23c2456b8da Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Fri, 17 Jul 2009 16:01:25 +0000 Subject: Store em and percentage values for properties in the computed style. Fully compute them on access. Introduce a swathe of internal accessors that don't perform the complete computation. Port property composition to these new APIs. Reduce absolute value computation to making font sizes absolute and converting any EX units to EM. svn path=/trunk/libcss/; revision=8601 --- include/libcss/computed.h | 541 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 515 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/include/libcss/computed.h b/include/libcss/computed.h index df2f5cf..f47b086 100644 --- a/include/libcss/computed.h +++ b/include/libcss/computed.h @@ -350,6 +350,13 @@ css_error css_computed_style_compose(const css_computed_style *parent, * Property accessors below here * ******************************************************************************/ +static inline uint8_t css_computed_font_size(const css_computed_style *style, + css_fixed *length, css_unit *unit); +static inline uint8_t css_computed_line_height(const css_computed_style *style, + css_fixed *length, css_unit *unit); +static inline uint8_t css_computed_position(const css_computed_style *style); + + #define LETTER_SPACING_INDEX 0 #define LETTER_SPACING_SHIFT 2 #define LETTER_SPACING_MASK 0xfc @@ -367,6 +374,17 @@ static inline uint8_t css_computed_letter_spacing( if ((bits & 3) == CSS_LETTER_SPACING_SET) { *length = style->uncommon->letter_spacing; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, + &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 3); @@ -421,6 +439,17 @@ static inline uint8_t css_computed_outline_width( if ((bits & 7) == CSS_OUTLINE_WIDTH_WIDTH) { *length = style->uncommon->outline_width; *unit = bits >> 3; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, + &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 7); @@ -465,6 +494,24 @@ static inline uint8_t css_computed_border_spacing( *vlength = style->uncommon->border_spacing[1]; *vunit = bits1 & 0xf; + + if (*hunit == CSS_UNIT_EM || *vunit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, + &font_unit); + + if (*hunit == CSS_UNIT_EM) { + *hlength = FMUL(*hlength, font_size); + *hunit = font_unit; + } + + if (*vunit == CSS_UNIT_EM) { + *hlength = FMUL(*vunit, font_size); + *vunit = font_unit; + } + } } return bits; @@ -499,6 +546,17 @@ static inline uint8_t css_computed_word_spacing( if ((bits & 3) == CSS_WORD_SPACING_SET) { *length = style->uncommon->word_spacing; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, + &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 3); @@ -640,6 +698,40 @@ static inline uint8_t css_computed_clip( rect->left = style->uncommon->clip[3]; rect->lunit = bits1 & 0xf; + + if (rect->tunit == CSS_UNIT_EM || + rect->runit == CSS_UNIT_EM || + rect->bunit == CSS_UNIT_EM || + rect->lunit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, + &font_unit); + + if (rect->tunit == CSS_UNIT_EM) { + rect->top = FMUL(rect->top, font_size); + rect->tunit = font_unit; + } + + if (rect->runit == CSS_UNIT_EM) { + rect->right = FMUL(rect->right, + font_size); + rect->runit = font_unit; + } + + if (rect->bunit == CSS_UNIT_EM) { + rect->bottom = FMUL(rect->bottom, + font_size); + rect->bunit = font_unit; + } + + if (rect->lunit == CSS_UNIT_EM) { + rect->left = FMUL(rect->left, + font_size); + rect->lunit = font_unit; + } + } } return (bits & 0x3); @@ -696,6 +788,24 @@ static inline uint8_t css_computed_vertical_align( if ((bits & 0xf) == CSS_VERTICAL_ALIGN_SET) { *length = style->vertical_align; *unit = bits >> 4; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } else if (*unit == CSS_UNIT_PCT) { + css_fixed line_height; + css_unit lh_unit; + + css_computed_line_height(style, &line_height, &lh_unit); + + *length = FDIVI(FMUL(*length, line_height), 100); + *unit = lh_unit; + } } return (bits & 0xf); @@ -742,6 +852,16 @@ static inline uint8_t css_computed_border_top_width( if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { *length = style->border_width[0]; *unit = bits >> 3; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x7); @@ -765,6 +885,16 @@ static inline uint8_t css_computed_border_right_width( if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { *length = style->border_width[1]; *unit = bits >> 3; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x7); @@ -788,6 +918,16 @@ static inline uint8_t css_computed_border_bottom_width( if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { *length = style->border_width[2]; *unit = bits >> 3; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x7); @@ -811,6 +951,16 @@ static inline uint8_t css_computed_border_left_width( if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) { *length = style->border_width[3]; *unit = bits >> 3; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x7); @@ -902,6 +1052,15 @@ static inline uint8_t css_computed_quotes( #define TOP_INDEX 6 #define TOP_SHIFT 2 #define TOP_MASK 0xfc +#define RIGHT_INDEX 7 +#define RIGHT_SHIFT 2 +#define RIGHT_MASK 0xfc +#define BOTTOM_INDEX 8 +#define BOTTOM_SHIFT 2 +#define BOTTOM_MASK 0xfc +#define LEFT_INDEX 9 +#define LEFT_SHIFT 2 +#define LEFT_MASK 0xfc static inline uint8_t css_computed_top( const css_computed_style *style, css_fixed *length, css_unit *unit) @@ -910,21 +1069,52 @@ static inline uint8_t css_computed_top( bits &= TOP_MASK; bits >>= TOP_SHIFT; - /* 6bits: uuuutt : units | type */ - if ((bits & 0x3) == CSS_TOP_SET) { + /* Fix up, based on computed position */ + if (css_computed_position(style) == CSS_POSITION_STATIC) { + /* Static -> auto */ + bits = CSS_TOP_AUTO; + } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) { + /* Relative -> follow $9.4.3 */ + uint8_t bottom = style->bits[BOTTOM_INDEX]; + bottom &= BOTTOM_MASK; + bottom >>= BOTTOM_SHIFT; + + if ((bits & 0x3) == CSS_TOP_AUTO && + (bottom & 0x3) == CSS_BOTTOM_AUTO) { + /* Both auto => 0px */ + *length = 0; + *unit = CSS_UNIT_PX; + } else if ((bits & 0x3) == CSS_TOP_AUTO) { + /* Top is auto => -bottom */ + *length = -style->bottom; + *unit = bottom >> 2; + } else { + *length = style->top; + *unit = bits >> 2; + } + + bits = CSS_TOP_SET; + } else if ((bits & 0x3) == CSS_TOP_SET) { *length = style->top; *unit = bits >> 2; } + /* 6bits: uuuutt : units | type */ + if ((bits & 0x3) == CSS_TOP_SET) { + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } + } + return (bits & 0x3); } -#undef TOP_MASK -#undef TOP_SHIFT -#undef TOP_INDEX -#define RIGHT_INDEX 7 -#define RIGHT_SHIFT 2 -#define RIGHT_MASK 0xfc static inline uint8_t css_computed_right( const css_computed_style *style, css_fixed *length, css_unit *unit) @@ -933,21 +1123,54 @@ static inline uint8_t css_computed_right( bits &= RIGHT_MASK; bits >>= RIGHT_SHIFT; - /* 6bits: uuuutt : units | type */ - if ((bits & 0x3) == CSS_RIGHT_SET) { + /* Fix up, based on computed position */ + if (css_computed_position(style) == CSS_POSITION_STATIC) { + /* Static -> auto */ + bits = CSS_RIGHT_AUTO; + } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) { + /* Relative -> follow $9.4.3 */ + uint8_t left = style->bits[LEFT_INDEX]; + left &= LEFT_MASK; + left >>= LEFT_SHIFT; + + if ((bits & 0x3) == CSS_RIGHT_AUTO && + (left & 0x3) == CSS_LEFT_AUTO) { + /* Both auto => 0px */ + *length = 0; + *unit = CSS_UNIT_PX; + } else if ((bits & 0x3) == CSS_RIGHT_AUTO) { + /* Right is auto => -left */ + *length = -style->left; + *unit = left >> 2; + } else { + /** \todo Consider containing block's direction + * if overconstrained */ + *length = style->right; + *unit = bits >> 2; + } + + bits = CSS_RIGHT_SET; + } else if ((bits & 0x3) == CSS_RIGHT_SET) { *length = style->right; *unit = bits >> 2; } + /* 6bits: uuuutt : units | type */ + if ((bits & 0x3) == CSS_RIGHT_SET) { + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } + } + return (bits & 0x3); } -#undef RIGHT_MASK -#undef RIGHT_SHIFT -#undef RIGHT_INDEX -#define BOTTOM_INDEX 8 -#define BOTTOM_SHIFT 2 -#define BOTTOM_MASK 0xfc static inline uint8_t css_computed_bottom( const css_computed_style *style, css_fixed *length, css_unit *unit) @@ -956,21 +1179,53 @@ static inline uint8_t css_computed_bottom( bits &= BOTTOM_MASK; bits >>= BOTTOM_SHIFT; - /* 6bits: uuuutt : units | type */ - if ((bits & 0x3) == CSS_BOTTOM_SET) { + /* Fix up, based on computed position */ + if (css_computed_position(style) == CSS_POSITION_STATIC) { + /* Static -> auto */ + bits = CSS_BOTTOM_AUTO; + } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) { + /* Relative -> follow $9.4.3 */ + uint8_t top = style->bits[TOP_INDEX]; + top &= TOP_MASK; + top >>= TOP_SHIFT; + + if ((bits & 0x3) == CSS_BOTTOM_AUTO && + (top & 0x3) == CSS_TOP_AUTO) { + /* Both auto => 0px */ + *length = 0; + *unit = CSS_UNIT_PX; + } else if ((bits & 0x3) == CSS_BOTTOM_AUTO || + (top & 0x3) != CSS_TOP_AUTO) { + /* Bottom is auto or top is not auto => -top */ + *length = -style->top; + *unit = top >> 2; + } else { + *length = style->bottom; + *unit = bits >> 2; + } + + bits = CSS_BOTTOM_SET; + } else if ((bits & 0x3) == CSS_BOTTOM_SET) { *length = style->bottom; *unit = bits >> 2; } + /* 6bits: uuuutt : units | type */ + if ((bits & 0x3) == CSS_BOTTOM_SET) { + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } + } + return (bits & 0x3); } -#undef BOTTOM_MASK -#undef BOTTOM_SHIFT -#undef BOTTOM_INDEX -#define LEFT_INDEX 9 -#define LEFT_SHIFT 2 -#define LEFT_MASK 0xfc static inline uint8_t css_computed_left( const css_computed_style *style, css_fixed *length, css_unit *unit) @@ -979,17 +1234,65 @@ static inline uint8_t css_computed_left( bits &= LEFT_MASK; bits >>= LEFT_SHIFT; - /* 6bits: uuuutt : units | type */ - if ((bits & 0x3) == CSS_LEFT_SET) { + /* Fix up, based on computed position */ + if (css_computed_position(style) == CSS_POSITION_STATIC) { + /* Static -> auto */ + bits = CSS_LEFT_AUTO; + } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) { + /* Relative -> follow $9.4.3 */ + uint8_t right = style->bits[RIGHT_INDEX]; + right &= RIGHT_MASK; + right >>= RIGHT_SHIFT; + + if ((bits & 0x3) == CSS_LEFT_AUTO && + (right & 0x3) == CSS_RIGHT_AUTO) { + /* Both auto => 0px */ + *length = 0; + *unit = CSS_UNIT_PX; + } else if ((bits & 0x3) == CSS_LEFT_AUTO) { + /* Left is auto => -right */ + *length = -style->right; + *unit = right >> 2; + } else { + /** \todo Consider containing block's direction + * if overconstrained */ + *length = style->left; + *unit = bits >> 2; + } + + bits = CSS_LEFT_SET; + } else if ((bits & 0x3) == CSS_LEFT_SET) { *length = style->left; *unit = bits >> 2; } + /* 6bits: uuuutt : units | type */ + if ((bits & 0x3) == CSS_RIGHT_SET) { + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } + } + return (bits & 0x3); } #undef LEFT_MASK #undef LEFT_SHIFT #undef LEFT_INDEX +#undef BOTTOM_MASK +#undef BOTTOM_SHIFT +#undef BOTTOM_INDEX +#undef RIGHT_MASK +#undef RIGHT_SHIFT +#undef RIGHT_INDEX +#undef TOP_MASK +#undef TOP_SHIFT +#undef TOP_INDEX #define BORDER_TOP_COLOR_INDEX 6 #define BORDER_TOP_COLOR_SHIFT 0 @@ -1086,6 +1389,16 @@ static inline uint8_t css_computed_height( if ((bits & 0x3) == CSS_HEIGHT_SET) { *length = style->height; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1113,6 +1426,20 @@ static inline uint8_t css_computed_line_height( if ((bits & 0x3) == CSS_LINE_HEIGHT_DIMENSION) { *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM || *unit == CSS_UNIT_PCT) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + + if (*unit == CSS_UNIT_PCT) + *length = FDIVI(*length, 100); + + *unit = font_unit; + } } return (bits & 0x3); @@ -1176,6 +1503,16 @@ static inline uint8_t css_computed_margin_top( if ((bits & 0x3) == CSS_MARGIN_SET) { *length = style->margin[0]; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1199,6 +1536,16 @@ static inline uint8_t css_computed_margin_right( if ((bits & 0x3) == CSS_MARGIN_SET) { *length = style->margin[1]; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1222,6 +1569,16 @@ static inline uint8_t css_computed_margin_bottom( if ((bits & 0x3) == CSS_MARGIN_SET) { *length = style->margin[2]; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1245,6 +1602,16 @@ static inline uint8_t css_computed_margin_left( if ((bits & 0x3) == CSS_MARGIN_SET) { *length = style->margin[3]; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1336,6 +1703,16 @@ static inline uint8_t css_computed_max_height( if ((bits & 0x3) == CSS_MAX_HEIGHT_SET) { *length = style->max_height; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1359,6 +1736,16 @@ static inline uint8_t css_computed_max_width( if ((bits & 0x3) == CSS_MAX_WIDTH_SET) { *length = style->max_width; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1382,6 +1769,16 @@ static inline uint8_t css_computed_width( if ((bits & 0x3) == CSS_WIDTH_SET) { *length = style->width; *unit = bits >> 2; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x3); @@ -1417,6 +1814,11 @@ static inline uint8_t css_computed_float( bits &= FLOAT_MASK; bits >>= FLOAT_SHIFT; + /* Fix up as per $9.7:2 */ + if (css_computed_position(style) == CSS_POSITION_ABSOLUTE || + css_computed_position(style) == CSS_POSITION_FIXED) + return CSS_FLOAT_NONE; + /* 2bits: type */ return bits; } @@ -1456,6 +1858,16 @@ static inline uint8_t css_computed_min_height( if ((bits & 0x1) == CSS_MIN_HEIGHT_SET) { *length = style->min_height; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1479,6 +1891,16 @@ static inline uint8_t css_computed_min_width( if ((bits & 0x1) == CSS_MIN_WIDTH_SET) { *length = style->min_width; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1536,6 +1958,16 @@ static inline uint8_t css_computed_padding_top( if ((bits & 0x1) == CSS_PADDING_SET) { *length = style->padding[0]; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1559,6 +1991,16 @@ static inline uint8_t css_computed_padding_right( if ((bits & 0x1) == CSS_PADDING_SET) { *length = style->padding[1]; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1582,6 +2024,16 @@ static inline uint8_t css_computed_padding_bottom( if ((bits & 0x1) == CSS_PADDING_SET) { *length = style->padding[2]; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1605,6 +2057,16 @@ static inline uint8_t css_computed_padding_left( if ((bits & 0x1) == CSS_PADDING_SET) { *length = style->padding[3]; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1696,6 +2158,16 @@ static inline uint8_t css_computed_text_indent( if ((bits & 0x1) == CSS_TEXT_INDENT_SET) { *length = style->text_indent; *unit = bits >> 1; + + if (*unit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + *length = FMUL(*length, font_size); + *unit = font_unit; + } } return (bits & 0x1); @@ -1748,6 +2220,23 @@ static inline uint8_t css_computed_background_position( *vlength = style->background_position[1]; *vunit = bits1 & 0xf; + + if (*hunit == CSS_UNIT_EM || *vunit == CSS_UNIT_EM) { + css_fixed font_size; + css_unit font_unit; + + css_computed_font_size(style, &font_size, &font_unit); + + if (*hunit == CSS_UNIT_EM) { + *hlength = FMUL(*hlength, font_size); + *hunit = font_unit; + } + + if (*vunit == CSS_UNIT_EM) { + *hlength = FMUL(*vunit, font_size); + *vunit = font_unit; + } + } } return bits; -- cgit v1.2.3