From 5776d3448c50d58af0eac8f3960200aa1b5fc1a0 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 3 Jan 2018 16:59:58 +0000 Subject: CSS computed style composition: Update for new CSS units. Since the nscss_compute_font_size callback now needs to convert new units to absolute values, and some of these units require info from the root element's style, there are knock-on changes to ensure that the required info is available where its needed. --- content/handlers/css/select.c | 52 +++++++++++++++++++++--- content/handlers/css/select.h | 1 + render/box.h | 5 ++- render/box_construct.c | 23 ++++++++--- render/box_normalise.c | 94 +++++++++++++++++++++++++++++++------------ 5 files changed, 137 insertions(+), 38 deletions(-) diff --git a/content/handlers/css/select.c b/content/handlers/css/select.c index 328d6a711..ee79eb394 100644 --- a/content/handlers/css/select.c +++ b/content/handlers/css/select.c @@ -278,7 +278,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n, * element's style */ error = css_computed_style_compose(ctx->parent_style, styles->styles[CSS_PSEUDO_ELEMENT_NONE], - nscss_compute_font_size, NULL, + nscss_compute_font_size, ctx, &composed); if (error != CSS_OK) { css_select_results_destroy(styles); @@ -310,7 +310,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n, error = css_computed_style_compose( styles->styles[CSS_PSEUDO_ELEMENT_NONE], styles->styles[pseudo_element], - nscss_compute_font_size, NULL, + nscss_compute_font_size, ctx, &composed); if (error != CSS_OK) { /* TODO: perhaps this shouldn't be quite so @@ -349,7 +349,7 @@ css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx, /* TODO: Do we really need to compose? Initial style shouldn't * have any inherited properties. */ error = css_computed_style_compose(parent, partial, - nscss_compute_font_size, NULL, &composed); + nscss_compute_font_size, ctx, &composed); css_computed_style_destroy(partial); if (error != CSS_OK) { css_computed_style_destroy(composed); @@ -422,14 +422,37 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent, FDIV(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.unit == CSS_UNIT_EX || + size->data.length.unit == CSS_UNIT_CAP || + size->data.length.unit == CSS_UNIT_CH || + size->data.length.unit == CSS_UNIT_IC) { size->data.length.value = FMUL(size->data.length.value, parent_size.value); - if (size->data.length.unit == CSS_UNIT_EX) { + switch (size->data.length.unit) { + case CSS_UNIT_EX: /* 1ex = 0.6em in NetSurf */ size->data.length.value = FMUL(size->data.length.value, FLTTOFIX(0.6)); + break; + case CSS_UNIT_CAP: + /* Height of captals. 1cap = 0.9em in NetSurf. */ + size->data.length.value = FMUL(size->data.length.value, + FLTTOFIX(0.9)); + break; + case CSS_UNIT_CH: + /* Width of '0'. 1ch = 0.4em in NetSurf. */ + size->data.length.value = FMUL(size->data.length.value, + FLTTOFIX(0.4)); + break; + case CSS_UNIT_IC: + /* Width of U+6C43. 1ic = 1.1em in NetSurf. */ + size->data.length.value = FMUL(size->data.length.value, + FLTTOFIX(1.1)); + break; + default: + /* No scaling required for EM. */ + break; } size->data.length.unit = parent_size.unit; @@ -437,6 +460,25 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent, size->data.length.value = FDIV(FMUL(size->data.length.value, parent_size.value), INTTOFIX(100)); size->data.length.unit = parent_size.unit; + } else if (size->data.length.unit == CSS_UNIT_REM) { + nscss_select_ctx *ctx = pw; + if (parent == NULL) { + size->data.length.value = parent_size.value; + size->data.length.unit = parent_size.unit; + } else { + css_computed_font_size(ctx->root_style, + &parent_size.value, + &size->data.length.unit); + size->data.length.value = FMUL( + size->data.length.value, + parent_size.value); + } + } else if (size->data.length.unit == CSS_UNIT_RLH) { + /** TODO: Convert root element line-height to absolute value. */ + size->data.length.value = FMUL(size->data.length.value, FDIV( + INTTOFIX(nsoption_int(font_size)), + INTTOFIX(10))); + size->data.length.unit = CSS_UNIT_PT; } size->status = CSS_FONT_SIZE_DIMENSION; diff --git a/content/handlers/css/select.h b/content/handlers/css/select.h index abfb85814..9fa6d3a56 100644 --- a/content/handlers/css/select.h +++ b/content/handlers/css/select.h @@ -37,6 +37,7 @@ typedef struct nscss_select_ctx bool quirks; struct nsurl *base_url; lwc_string *universal; + const css_computed_style *root_style; const css_computed_style *parent_style; } nscss_select_ctx; diff --git a/render/box.h b/render/box.h index 2800d4026..8208a6fd3 100644 --- a/render/box.h +++ b/render/box.h @@ -356,6 +356,9 @@ bool box_hscrollbar_present(const struct box *box); nserror dom_to_box(struct dom_node *n, struct html_content *c, box_construct_complete_cb cb); -bool box_normalise_block(struct box *block, struct html_content *c); +bool box_normalise_block( + struct box *block, + const struct box *root, + struct html_content *c); #endif diff --git a/render/box_construct.c b/render/box_construct.c index 1982622f9..1aa99e2d1 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -104,7 +104,8 @@ static bool box_construct_element(struct box_construct_ctx *ctx, static void box_construct_element_after(dom_node *n, html_content *content); static bool box_construct_text(struct box_construct_ctx *ctx); static css_select_results * box_get_style(html_content *c, - const css_computed_style *parent_style, dom_node *n); + const css_computed_style *parent_style, + const css_computed_style *root_style, dom_node *n); static void box_text_transform(char *s, unsigned int len, enum css_text_transform_e tt); #define BOX_SPECIAL_PARAMS dom_node *n, html_content *content, \ @@ -429,7 +430,8 @@ void convert_xml_to_box(struct box_construct_ctx *ctx) root.children->parent = &root; /** \todo Remove box_normalise_block */ - if (box_normalise_block(&root, ctx->content) == false) { + if (box_normalise_block(&root, ctx->root_box, + ctx->content) == false) { ctx->cb(ctx->content, false); } else { ctx->content->layout = root.children; @@ -741,6 +743,7 @@ bool box_construct_element(struct box_construct_ctx *ctx, lwc_string *bgimage_uri; dom_exception err; struct box_construct_props props; + const css_computed_style *root_style = NULL; assert(ctx->n != NULL); @@ -753,7 +756,12 @@ bool box_construct_element(struct box_construct_ctx *ctx, props.containing_block->flags &= ~PRE_STRIP; } - styles = box_get_style(ctx->content, props.parent_style, ctx->n); + if (props.node_is_root == false) { + root_style = ctx->root_box->style; + } + + styles = box_get_style(ctx->content, props.parent_style, root_style, + ctx->n); if (styles == NULL) return false; @@ -1321,13 +1329,15 @@ bool box_construct_text(struct box_construct_ctx *ctx) /** * Get the style for an element. * - * \param c content of type CONTENT_HTML that is being processed + * \param c content of type CONTENT_HTML that is being processed * \param parent_style style at this point in xml tree, or NULL for root - * \param n node in xml tree + * \param root_style root node's style, or NULL for root + * \param n node in xml tree * \return the new style, or NULL on memory exhaustion */ css_select_results *box_get_style(html_content *c, - const css_computed_style *parent_style, dom_node *n) + const css_computed_style *parent_style, + const css_computed_style *root_style, dom_node *n) { dom_string *s; dom_exception err; @@ -1359,6 +1369,7 @@ css_select_results *box_get_style(html_content *c, ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL); ctx.base_url = c->base_url; ctx.universal = c->universal; + ctx.root_style = root_style; ctx.parent_style = parent_style; /* Select style for element */ diff --git a/render/box_normalise.c b/render/box_normalise.c index 9f78f75ac..9c0875b4e 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -65,24 +65,38 @@ struct columns { }; -static bool box_normalise_table(struct box *table, html_content *c); -static bool box_normalise_table_spans(struct box *table, - struct span_info *spans, html_content *c); -static bool box_normalise_table_row_group(struct box *row_group, +static bool box_normalise_table( + struct box *table, + const struct box *root, + html_content *c); +static bool box_normalise_table_spans( + struct box *table, + const struct box *root, + struct span_info *spans, + html_content *c); +static bool box_normalise_table_row_group( + struct box *row_group, + const struct box *root, struct columns *col_info, html_content *c); -static bool box_normalise_table_row(struct box *row, +static bool box_normalise_table_row( + struct box *row, + const struct box *root, struct columns *col_info, html_content *c); static bool calculate_table_row(struct columns *col_info, unsigned int col_span, unsigned int row_span, unsigned int *start_column, struct box *cell); -static bool box_normalise_inline_container(struct box *cont, html_content *c); +static bool box_normalise_inline_container( + struct box *cont, + const struct box *root, + html_content *c); /** * Ensure the box tree is correctly nested by adding and removing nodes. * * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL + * \param root root box of document * \param c content of boxes * \return true on success, false on memory exhaustion * @@ -100,7 +114,10 @@ static bool box_normalise_inline_container(struct box *cont, html_content *c); * \endcode */ -bool box_normalise_block(struct box *block, html_content *c) +bool box_normalise_block( + struct box *block, + const struct box *root, + html_content *c) { struct box *child; struct box *next_child; @@ -109,6 +126,9 @@ bool box_normalise_block(struct box *block, html_content *c) nscss_select_ctx ctx; assert(block != NULL); + assert(root != NULL); + + ctx.root_style = root->style; #ifdef BOX_NORMALISE_DEBUG NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type); @@ -128,15 +148,15 @@ bool box_normalise_block(struct box *block, html_content *c) switch (child->type) { case BOX_BLOCK: /* ok */ - if (box_normalise_block(child, c) == false) + if (box_normalise_block(child, root, c) == false) return false; break; case BOX_INLINE_CONTAINER: - if (box_normalise_inline_container(child, c) == false) + if (box_normalise_inline_container(child, root, c) == false) return false; break; case BOX_TABLE: - if (box_normalise_table(child, c) == false) + if (box_normalise_table(child, root, c) == false) return false; break; case BOX_INLINE: @@ -199,7 +219,7 @@ bool box_normalise_block(struct box *block, html_content *c) block->last = table; table->parent = block; - if (box_normalise_table(table, c) == false) + if (box_normalise_table(table, root, c) == false) return false; break; default: @@ -211,7 +231,10 @@ bool box_normalise_block(struct box *block, html_content *c) } -bool box_normalise_table(struct box *table, html_content * c) +bool box_normalise_table( + struct box *table, + const struct box *root, + html_content * c) { struct box *child; struct box *next_child; @@ -223,6 +246,8 @@ bool box_normalise_table(struct box *table, html_content * c) assert(table != NULL); assert(table->type == BOX_TABLE); + ctx.root_style = root->style; + #ifdef BOX_NORMALISE_DEBUG NSLOG(netsurf, INFO, "table %p", table); #endif @@ -243,7 +268,7 @@ bool box_normalise_table(struct box *table, html_content * c) switch (child->type) { case BOX_TABLE_ROW_GROUP: /* ok */ - if (box_normalise_table_row_group(child, + if (box_normalise_table_row_group(child, root, &col_info, c) == false) { free(col_info.spans); return false; @@ -308,7 +333,7 @@ bool box_normalise_table(struct box *table, html_content * c) table->last = row_group; row_group->parent = table; - if (box_normalise_table_row_group(row_group, + if (box_normalise_table_row_group(row_group, root, &col_info, c) == false) { free(col_info.spans); return false; @@ -390,7 +415,7 @@ bool box_normalise_table(struct box *table, html_content * c) table->rows = 1; } - if (box_normalise_table_spans(table, col_info.spans, c) == false) { + if (box_normalise_table_spans(table, root, col_info.spans, c) == false) { free(col_info.spans); return false; } @@ -413,12 +438,16 @@ bool box_normalise_table(struct box *table, html_content * c) * Additionally, generate empty cells. * * \param table Table to process + * \param root root box of document * \param spans Array of length table->columns for use in empty cell detection * \param c Content containing table * \return True on success, false on memory exhaustion. */ -bool box_normalise_table_spans(struct box *table, struct span_info *spans, +bool box_normalise_table_spans( + struct box *table, + const struct box *root, + struct span_info *spans, html_content *c) { struct box *table_row_group; @@ -429,6 +458,8 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans, unsigned int col; nscss_select_ctx ctx; + ctx.root_style = root->style; + /* Clear span data */ memset(spans, 0, table->columns * sizeof(struct span_info)); @@ -572,7 +603,9 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans, } -bool box_normalise_table_row_group(struct box *row_group, +bool box_normalise_table_row_group( + struct box *row_group, + const struct box *root, struct columns *col_info, html_content * c) { @@ -586,6 +619,8 @@ bool box_normalise_table_row_group(struct box *row_group, assert(row_group != 0); assert(row_group->type == BOX_TABLE_ROW_GROUP); + ctx.root_style = root->style; + #ifdef BOX_NORMALISE_DEBUG NSLOG(netsurf, INFO, "row_group %p", row_group); #endif @@ -597,7 +632,7 @@ bool box_normalise_table_row_group(struct box *row_group, case BOX_TABLE_ROW: /* ok */ group_row_count++; - if (box_normalise_table_row(child, col_info, + if (box_normalise_table_row(child, root, col_info, c) == false) return false; break; @@ -657,7 +692,7 @@ bool box_normalise_table_row_group(struct box *row_group, row->parent = row_group; group_row_count++; - if (box_normalise_table_row(row, col_info, + if (box_normalise_table_row(row, root, col_info, c) == false) return false; break; @@ -722,7 +757,9 @@ bool box_normalise_table_row_group(struct box *row_group, } -bool box_normalise_table_row(struct box *row, +bool box_normalise_table_row( + struct box *row, + const struct box *root, struct columns *col_info, html_content * c) { @@ -736,6 +773,8 @@ bool box_normalise_table_row(struct box *row, assert(row != NULL); assert(row->type == BOX_TABLE_ROW); + ctx.root_style = root->style; + #ifdef BOX_NORMALISE_DEBUG NSLOG(netsurf, INFO, "row %p", row); #endif @@ -746,7 +785,7 @@ bool box_normalise_table_row(struct box *row, switch (child->type) { case BOX_TABLE_CELL: /* ok */ - if (box_normalise_block(child, c) == false) + if (box_normalise_block(child, root, c) == false) return false; cell = child; break; @@ -805,7 +844,7 @@ bool box_normalise_table_row(struct box *row, row->last = cell; cell->parent = row; - if (box_normalise_block(cell, c) == false) + if (box_normalise_block(cell, root, c) == false) return false; break; case BOX_INLINE: @@ -928,7 +967,10 @@ bool calculate_table_row(struct columns *col_info, } -bool box_normalise_inline_container(struct box *cont, html_content * c) +bool box_normalise_inline_container( + struct box *cont, + const struct box *root, + html_content * c) { struct box *child; struct box *next_child; @@ -951,7 +993,7 @@ bool box_normalise_inline_container(struct box *cont, html_content * c) break; case BOX_INLINE_BLOCK: /* ok */ - if (box_normalise_block(child, c) == false) + if (box_normalise_block(child, root, c) == false) return false; break; case BOX_FLOAT_LEFT: @@ -961,12 +1003,12 @@ bool box_normalise_inline_container(struct box *cont, html_content * c) switch (child->children->type) { case BOX_BLOCK: - if (box_normalise_block(child->children, + if (box_normalise_block(child->children, root, c) == false) return false; break; case BOX_TABLE: - if (box_normalise_table(child->children, + if (box_normalise_table(child->children, root, c) == false) return false; break; -- cgit v1.2.3