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.
This commit is contained in:
Michael Drake 2018-01-03 16:59:58 +00:00
parent d1c656b55f
commit 5776d3448c
5 changed files with 137 additions and 38 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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;