From 6be6fa1b2197ffe6e511c5eff9abe14d883f8478 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 3 Jan 2018 23:58:18 +0000 Subject: CSS utils: Handle new units in length conversion routines. This causes a ripple effect of all the callsites needing information they didn't have. --- render/box.c | 41 ++-- render/box.h | 6 +- render/box_normalise.c | 3 - render/box_textarea.c | 11 +- render/font.c | 8 +- render/font.h | 11 +- render/form.c | 3 +- render/html.c | 15 +- render/html_interaction.c | 12 +- render/html_internal.h | 4 + render/html_object.c | 6 +- render/html_redraw.c | 41 ++-- render/layout.c | 562 +++++++++++++++++++++++++++++----------------- render/search.c | 5 +- render/table.c | 319 ++++++++++++++++---------- render/table.h | 8 +- render/textplain.c | 2 +- 17 files changed, 667 insertions(+), 390 deletions(-) (limited to 'render') diff --git a/render/box.c b/render/box.c index 8b9c89ee6..c97e8982b 100644 --- a/render/box.c +++ b/render/box.c @@ -342,20 +342,27 @@ void box_bounds(struct box *box, struct rect *r) /** * Determine if a point lies within a box. * - * \param box box to consider - * \param x coordinate relative to box - * \param y coordinate relative to box - * \param physically if function returning true, physically is set true if - * point is within the box's physical dimensions and false - * if the point is not within the box's physical dimensions - * but is in the area defined by the box's descendants. - * if function returning false, physically is undefined. + * \param[in] len_ctx CSS length conversion context to use. + * \param[in] box Box to consider + * \param[in] x Coordinate relative to box + * \param[in] y Coordinate relative to box + * \param[out] physically If function returning true, physically is set true + * iff point is within the box's physical dimensions and + * false if the point is not within the box's physical + * dimensions but is in the area defined by the box's + * descendants. If function returns false, physically + * is undefined. * \return true if the point is within the box or a descendant box * * This is a helper function for box_at_point(). */ -static bool box_contains_point(struct box *box, int x, int y, bool *physically) +static bool box_contains_point( + const nscss_len_ctx *len_ctx, + const struct box *box, + int x, + int y, + bool *physically) { css_computed_clip_rect css_rect; @@ -382,25 +389,25 @@ static bool box_contains_point(struct box *box, int x, int y, bool *physically) /* Adjust rect to css clip region */ if (css_rect.left_auto == false) { - r.x0 += FIXTOINT(nscss_len2px( + r.x0 += FIXTOINT(nscss_len2px(len_ctx, css_rect.left, css_rect.lunit, box->style)); } if (css_rect.top_auto == false) { - r.y0 += FIXTOINT(nscss_len2px( + r.y0 += FIXTOINT(nscss_len2px(len_ctx, css_rect.top, css_rect.tunit, box->style)); } if (css_rect.right_auto == false) { r.x1 = box->border[LEFT].width + - FIXTOINT(nscss_len2px( + FIXTOINT(nscss_len2px(len_ctx, css_rect.right, css_rect.runit, box->style)); } if (css_rect.bottom_auto == false) { r.y1 = box->border[TOP].width + - FIXTOINT(nscss_len2px( + FIXTOINT(nscss_len2px(len_ctx, css_rect.bottom, css_rect.bunit, box->style)); @@ -659,6 +666,7 @@ skip_children: /** * Find the boxes at a point. * + * \param len_ctx CSS length conversion context for document. * \param box box to search children of * \param x point to find, in global document coordinates * \param y point to find, in global document coordinates @@ -674,13 +682,14 @@ skip_children: * struct box *box = top_of_document_to_search; * int box_x = 0, box_y = 0; * - * while ((box = box_at_point(box, x, y, &box_x, &box_y))) { + * while ((box = box_at_point(len_ctx, box, x, y, &box_x, &box_y))) { * // process box * } * \endcode */ -struct box *box_at_point(struct box *box, const int x, const int y, +struct box *box_at_point(const nscss_len_ctx *len_ctx, + struct box *box, const int x, const int y, int *box_x, int *box_y) { bool skip_children; @@ -690,7 +699,7 @@ struct box *box_at_point(struct box *box, const int x, const int y, skip_children = false; while ((box = box_next_xy(box, box_x, box_y, skip_children))) { - if (box_contains_point(box, x - *box_x, y - *box_y, + if (box_contains_point(len_ctx, box, x - *box_x, y - *box_y, &physically)) { *box_x -= scrollbar_get_offset(box->scroll_x); *box_y -= scrollbar_get_offset(box->scroll_y); diff --git a/render/box.h b/render/box.h index 8208a6fd3..1af0a8b73 100644 --- a/render/box.h +++ b/render/box.h @@ -91,6 +91,8 @@ #include #include +#include "content/handlers/css/utils.h" + struct content; struct box; struct browser_window; @@ -328,7 +330,9 @@ void box_free(struct box *box); void box_free_box(struct box *box); void box_bounds(struct box *box, struct rect *r); void box_coords(struct box *box, int *x, int *y); -struct box *box_at_point(struct box *box, const int x, const int y, +struct box *box_at_point( + const nscss_len_ctx *len_ctx, + struct box *box, const int x, const int y, int *box_x, int *box_y); struct box *box_pick_text_box(struct html_content *html, int x, int y, int dir, int *dx, int *dy); diff --git a/render/box_normalise.c b/render/box_normalise.c index 9c0875b4e..8da245754 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -422,9 +422,6 @@ bool box_normalise_table( free(col_info.spans); - if (table_calculate_column_types(table) == false) - return false; - #ifdef BOX_NORMALISE_DEBUG NSLOG(netsurf, INFO, "table %p done", table); #endif diff --git a/render/box_textarea.c b/render/box_textarea.c index 3b1e7750c..a60984235 100644 --- a/render/box_textarea.c +++ b/render/box_textarea.c @@ -239,7 +239,14 @@ bool box_textarea_create_textarea(html_content *html, dom_exception err; textarea_setup ta_setup; textarea_flags ta_flags; - plot_font_style_t fstyle; + plot_font_style_t fstyle = { + .family = PLOT_FONT_FAMILY_SANS_SERIF, + .size = 10 * FONT_SIZE_SCALE, + .weight = 400, + .flags = FONTF_NONE, + .background = 0, + .foreground = 0, + }; bool read_only = false; bool disabled = false; struct form_control *gadget = box->gadget; @@ -307,8 +314,6 @@ bool box_textarea_create_textarea(html_content *html, gadget->data.text.data.gadget = gadget; - font_plot_style_from_css(gadget->box->style, &fstyle); - /* Reset to correct values by layout */ ta_setup.width = 200; ta_setup.height = 20; diff --git a/render/font.c b/render/font.c index 94ef877c7..a769b476f 100644 --- a/render/font.c +++ b/render/font.c @@ -131,8 +131,10 @@ static plot_font_flags_t plot_font_flags(enum css_font_style_e style, } -/* exported function documented in render/font_internal.h */ -void font_plot_style_from_css(const css_computed_style *css, +/* exported function documented in render/font.h */ +void font_plot_style_from_css( + const nscss_len_ctx *len_ctx, + const css_computed_style *css, plot_font_style_t *fstyle) { lwc_string **families; @@ -144,7 +146,7 @@ void font_plot_style_from_css(const css_computed_style *css, css_computed_font_family(css, &families)); css_computed_font_size(css, &length, &unit); - fstyle->size = FIXTOINT(FMUL(nscss_len2pt(length, unit), + fstyle->size = FIXTOINT(FMUL(nscss_len2pt(len_ctx, length, unit), INTTOFIX(FONT_SIZE_SCALE))); /* Clamp font size to configured minimum */ diff --git a/render/font.h b/render/font.h index fba368a97..52f5a62c2 100644 --- a/render/font.h +++ b/render/font.h @@ -32,10 +32,13 @@ struct plot_font_style; /** * Populate a font style using data from a computed CSS style * - * \param css Computed style to consider - * \param fstyle Font style to populate + * \param len_ctx Length conversion context + * \param css Computed style to consider + * \param fstyle Font style to populate */ -void font_plot_style_from_css(const css_computed_style *css, - struct plot_font_style *fstyle); +void font_plot_style_from_css( + const nscss_len_ctx *len_ctx, + const css_computed_style *css, + struct plot_font_style *fstyle); #endif diff --git a/render/form.c b/render/form.c index 904272d3a..432002564 100644 --- a/render/form.c +++ b/render/form.c @@ -1133,6 +1133,7 @@ bool form_open_select_menu(void *client_data, plot_font_style_t fstyle; int total_height; struct form_select_menu *menu; + html_content *html = (html_content *)c; /* if the menu is opened for the first time */ @@ -1153,7 +1154,7 @@ bool form_open_select_menu(void *client_data, box->border[LEFT].width + box->padding[RIGHT] + box->padding[LEFT]; - font_plot_style_from_css(control->box->style, + font_plot_style_from_css(&html->len_ctx, control->box->style, &fstyle); menu->f_size = fstyle.size; diff --git a/render/html.c b/render/html.c index 3cfc5e236..b7d7aa313 100644 --- a/render/html.c +++ b/render/html.c @@ -1398,6 +1398,10 @@ static void html_reformat(struct content *c, int width, int height) htmlc->reflowing = true; + htmlc->len_ctx.vw = width; + htmlc->len_ctx.vh = height; + htmlc->len_ctx.root_style = htmlc->layout->style; + layout_document(htmlc, width, height); layout = htmlc->layout; @@ -1647,7 +1651,7 @@ html_open(struct content *c, html->drag_owner.no_owner = true; /* text selection */ - selection_init(&html->sel, html->layout); + selection_init(&html->sel, html->layout, &html->len_ctx); html->selection_type = HTML_SELECTION_NONE; html->selection_owner.none = true; @@ -1768,7 +1772,8 @@ html_get_contextual_content(struct content *c, int x, int y, struct box *next; int box_x = 0, box_y = 0; - while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { + while ((next = box_at_point(&html->len_ctx, box, x, y, + &box_x, &box_y)) != NULL) { box = next; /* hidden boxes are ignored */ @@ -1845,7 +1850,8 @@ html_scroll_at_point(struct content *c, int x, int y, int scrx, int scry) /* TODO: invert order; visit deepest box first */ - while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { + while ((next = box_at_point(&html->len_ctx, box, x, y, + &box_x, &box_y)) != NULL) { box = next; if (box->style && css_computed_visibility(box->style) == @@ -1987,7 +1993,8 @@ static bool html_drop_file_at_point(struct content *c, int x, int y, char *file) int box_x = 0, box_y = 0; /* Scan box tree for boxes that can handle drop */ - while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { + while ((next = box_at_point(&html->len_ctx, box, x, y, + &box_x, &box_y)) != NULL) { box = next; if (box->style && css_computed_visibility(box->style) == diff --git a/render/html_interaction.c b/render/html_interaction.c index 30adaa080..2d14ed2ae 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -208,7 +208,7 @@ static size_t html_selection_drag_end(struct html_content *html, if (box) { plot_font_style_t fstyle; - font_plot_style_from_css(box->style, &fstyle); + font_plot_style_from_css(&html->len_ctx, box->style, &fstyle); guit->layout->position(&fstyle, box->text, box->length, dx, &idx, &pixel_offset); @@ -415,7 +415,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, size_t idx; plot_font_style_t fstyle; - font_plot_style_from_css(box->style, &fstyle); + font_plot_style_from_css(&html->len_ctx, + box->style, &fstyle); guit->layout->position(&fstyle, box->text, box->length, @@ -649,7 +650,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, text_box = box; text_box_x = box_x; } - } while ((box = box_at_point(box, x, y, &box_x, &box_y)) != NULL); + } while ((box = box_at_point(&html->len_ctx, box, x, y, + &box_x, &box_y)) != NULL); /* use of box_x, box_y, or content below this point is probably a * mistake; they will refer to the last box returned by box_at_point */ @@ -910,8 +912,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, int pixel_offset; size_t idx; - font_plot_style_from_css(text_box->style, - &fstyle); + font_plot_style_from_css(&html->len_ctx, + text_box->style, &fstyle); guit->layout->position(&fstyle, text_box->text, diff --git a/render/html_internal.h b/render/html_internal.h index 2f84cf869..66ecb2b36 100644 --- a/render/html_internal.h +++ b/render/html_internal.h @@ -26,6 +26,7 @@ #include +#include "content/handlers/css/utils.h" #include "content/content_protected.h" #include "desktop/selection.h" #include "render/html.h" @@ -94,6 +95,9 @@ typedef struct html_content { /** Base target */ char *base_target; + /** CSS length conversion context for document. */ + nscss_len_ctx len_ctx; + /** Content has been aborted in the LOADING state */ bool aborted; diff --git a/render/html_object.c b/render/html_object.c index e98bdba0b..fb9e7b090 100644 --- a/render/html_object.c +++ b/render/html_object.c @@ -227,7 +227,8 @@ html_object_callback(hlcache_handle *object, if (hunit == CSS_UNIT_PCT) { l = (width - w) * hpos / INTTOFIX(100); } else { - l = FIXTOINT(nscss_len2px(hpos, hunit, + l = FIXTOINT(nscss_len2px(&c->len_ctx, + hpos, hunit, box->style)); } @@ -235,7 +236,8 @@ html_object_callback(hlcache_handle *object, if (vunit == CSS_UNIT_PCT) { t = (height - h) * vpos / INTTOFIX(100); } else { - t = FIXTOINT(nscss_len2px(vpos, vunit, + t = FIXTOINT(nscss_len2px(&c->len_ctx, + vpos, vunit, box->style)); } diff --git a/render/html_redraw.c b/render/html_redraw.c index 2f8730634..9a97e5ec5 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -521,12 +521,14 @@ static bool html_redraw_radio(int x, int y, int width, int height, * \param box box of input * \param scale scale for redraw * \param background_colour current background colour + * \param len_ctx Length conversion context * \param ctx current redraw context * \return true if successful, false otherwise */ static bool html_redraw_file(int x, int y, int width, int height, struct box *box, float scale, colour background_colour, + const nscss_len_ctx *len_ctx, const struct redraw_context *ctx) { int text_width; @@ -535,7 +537,7 @@ static bool html_redraw_file(int x, int y, int width, int height, plot_font_style_t fstyle; nserror res; - font_plot_style_from_css(box->style, &fstyle); + font_plot_style_from_css(len_ctx, box->style, &fstyle); fstyle.background = background_colour; if (box->gadget->value) { @@ -578,13 +580,16 @@ static bool html_redraw_file(int x, int y, int width, int height, * \param clip current clip rectangle * \param background_colour current background colour * \param background box containing background details (usually \a box) - * \param ctx current redraw context + * \param len_ctx Length conversion context + * \param ctx current redraw context * \return true if successful, false otherwise */ static bool html_redraw_background(int x, int y, struct box *box, float scale, const struct rect *clip, colour *background_colour, - struct box *background, const struct redraw_context *ctx) + struct box *background, + const nscss_len_ctx *len_ctx, + const struct redraw_context *ctx) { bool repeat_x = false; bool repeat_y = false; @@ -660,7 +665,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale, content_get_width(background->background)) * scale * FIXTOFLT(hpos) / 100.; } else { - x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit, + x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit, background->style)) * scale); } @@ -669,7 +674,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale, content_get_height(background->background)) * scale * FIXTOFLT(vpos) / 100.; } else { - y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, + y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit, background->style)) * scale); } } @@ -802,13 +807,15 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale, * \param first true if this is the first rectangle associated with the inline * \param last true if this is the last rectangle associated with the inline * \param background_colour updated to current background colour if plotted - * \param ctx current redraw context + * \param len_ctx Length conversion context + * \param ctx current redraw context * \return true if successful, false otherwise */ static bool html_redraw_inline_background(int x, int y, struct box *box, float scale, const struct rect *clip, struct rect b, bool first, bool last, colour *background_colour, + const nscss_len_ctx *len_ctx, const struct redraw_context *ctx) { struct rect r = *clip; @@ -869,7 +876,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box, plot_content = false; } } else { - x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit, + x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit, box->style)) * scale); } @@ -878,7 +885,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box, content_get_height(box->background) * scale) * FIXTOFLT(vpos) / 100.; } else { - y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, + y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit, box->style)) * scale); } } @@ -1120,7 +1127,7 @@ static bool html_redraw_text_box(const html_content *html, struct box *box, bool excluded = (box->object != NULL); plot_font_style_t fstyle; - font_plot_style_from_css(box->style, &fstyle); + font_plot_style_from_css(&html->len_ctx, box->style, &fstyle); fstyle.background = current_background_color; if (!text_redraw(box->text, box->length, box->byte_offset, @@ -1382,21 +1389,25 @@ bool html_redraw_box(const html_content *html, struct box *box, /* We have an absolutly positioned box with a clip rect */ if (css_rect.left_auto == false) r.x0 = x - border_left + FIXTOINT(nscss_len2px( + &html->len_ctx, css_rect.left, css_rect.lunit, box->style)); if (css_rect.top_auto == false) r.y0 = y - border_top + FIXTOINT(nscss_len2px( + &html->len_ctx, css_rect.top, css_rect.tunit, box->style)); if (css_rect.right_auto == false) r.x1 = x - border_left + FIXTOINT(nscss_len2px( + &html->len_ctx, css_rect.right, css_rect.runit, box->style)); if (css_rect.bottom_auto == false) r.y1 = y - border_top + FIXTOINT(nscss_len2px( + &html->len_ctx, css_rect.bottom, css_rect.bunit, box->style)); @@ -1486,7 +1497,8 @@ bool html_redraw_box(const html_content *html, struct box *box, if ((p.x0 < p.x1) && (p.y0 < p.y1)) { /* plot background */ if (!html_redraw_background(x, y, box, scale, &p, - ¤t_background_color, bg_box, ctx)) + ¤t_background_color, bg_box, + &html->len_ctx, ctx)) return false; /* restore previous graphics window */ if (ctx->plot->clip(ctx, &r) != NSERROR_OK) @@ -1565,7 +1577,8 @@ bool html_redraw_box(const html_content *html, struct box *box, if (!html_redraw_inline_background( x, y, box, scale, &p, b, first, false, - ¤t_background_color, ctx)) + ¤t_background_color, + &html->len_ctx, ctx)) return false; /* restore previous graphics window */ if (ctx->plot->clip(ctx, &r) != NSERROR_OK) @@ -1597,7 +1610,8 @@ bool html_redraw_box(const html_content *html, struct box *box, /* plot background and borders for last rectangle of * the inline */ if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b, - first, true, ¤t_background_color, ctx)) + first, true, ¤t_background_color, + &html->len_ctx, ctx)) return false; /* restore previous graphics window */ if (ctx->plot->clip(ctx, &r) != NSERROR_OK) @@ -1768,7 +1782,6 @@ bool html_redraw_box(const html_content *html, struct box *box, obj, sizeof(obj) - 1) != NSERROR_OK) return false; } - } else if (box->iframe) { /* Offset is passed to browser window redraw unscaled */ @@ -1789,7 +1802,7 @@ bool html_redraw_box(const html_content *html, struct box *box, } else if (box->gadget && box->gadget->type == GADGET_FILE) { if (!html_redraw_file(x + padding_left, y + padding_top, width, height, box, scale, - current_background_color, ctx)) + current_background_color, &html->len_ctx, ctx)) return false; } else if (box->gadget && diff --git a/render/layout.c b/render/layout.c index 83dbc536d..15eb1e846 100644 --- a/render/layout.c +++ b/render/layout.c @@ -69,8 +69,14 @@ #define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100))) /* forward declaration to break cycles */ -static bool layout_block_context(struct box *block, int viewport_height, html_content *content); -static void layout_minmax_block(struct box *block, const struct gui_layout_table *font_func); +static bool layout_block_context( + struct box *block, + int viewport_height, + html_content *content); +static void layout_minmax_block( + struct box *block, + const struct gui_layout_table *font_func, + const html_content *content); /** @@ -179,7 +185,9 @@ layout_get_object_dimensions(struct box *box, * \param width width of containing block * \return length of indent */ -static int layout_text_indent(const css_computed_style *style, int width) +static int layout_text_indent( + const nscss_len_ctx *len_ctx, + const css_computed_style *style, int width) { css_fixed value = 0; css_unit unit = CSS_UNIT_PX; @@ -189,7 +197,7 @@ static int layout_text_indent(const css_computed_style *style, int width) if (unit == CSS_UNIT_PCT) { return FPCT_OF_INT_TOINT(value, width); } else { - return FIXTOINT(nscss_len2px(value, unit, style)); + return FIXTOINT(nscss_len2px(len_ctx, value, unit, style)); } } @@ -197,6 +205,7 @@ static int layout_text_indent(const css_computed_style *style, int width) /** * Determine width of margin, borders, and padding on one side of a box. * + * \param len_ctx CSS length conversion context for document * \param style style to measure * \param side side of box to measure * \param margin whether margin width is required @@ -206,7 +215,8 @@ static int layout_text_indent(const css_computed_style *style, int width) * \param frac increased by sum of fractional margin and padding */ static void -calculate_mbp_width(const css_computed_style *style, +calculate_mbp_width(const nscss_len_ctx *len_ctx, + const css_computed_style *style, unsigned int side, bool margin, bool border, @@ -217,19 +227,19 @@ calculate_mbp_width(const css_computed_style *style, typedef uint8_t (*len_func)(const css_computed_style *style, css_fixed *length, css_unit *unit); - static len_func margin_funcs[4] = { + static const len_func margin_funcs[4] = { css_computed_margin_top, css_computed_margin_right, css_computed_margin_bottom, css_computed_margin_left }; - static len_func padding_funcs[4] = { + static const len_func padding_funcs[4] = { css_computed_padding_top, css_computed_padding_right, css_computed_padding_bottom, css_computed_padding_left }; - static struct { + static const struct { len_func width; uint8_t (*style)(const css_computed_style *style); } border_funcs[4] = { @@ -257,8 +267,8 @@ calculate_mbp_width(const css_computed_style *style, if (unit == CSS_UNIT_PCT) { *frac += FIXTOINT(FDIV(value, F_100)); } else { - *fixed += FIXTOINT(nscss_len2px(value, unit, - style)); + *fixed += FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } } @@ -269,7 +279,8 @@ calculate_mbp_width(const css_computed_style *style, CSS_BORDER_STYLE_NONE) { border_funcs[side].width(style, &value, &unit); - *fixed += FIXTOINT(nscss_len2px(value, unit, style)); + *fixed += FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } @@ -279,7 +290,8 @@ calculate_mbp_width(const css_computed_style *style, if (unit == CSS_UNIT_PCT) { *frac += FIXTOINT(FDIV(value, F_100)); } else { - *fixed += FIXTOINT(nscss_len2px(value, unit, style)); + *fixed += FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } } @@ -290,19 +302,20 @@ calculate_mbp_width(const css_computed_style *style, * * \param table box of type TABLE * \param font_func Font functions - * \param content The HTML content being layed out. + * \param content The HTML content we are laying out. * \post table->min_width and table->max_width filled in, * 0 <= table->min_width <= table->max_width */ -static void -layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) +static void layout_minmax_table(struct box *table, + const struct gui_layout_table *font_func, + const html_content *content) { unsigned int i, j; int border_spacing_h = 0; int table_min = 0, table_max = 0; int extra_fixed = 0; float extra_frac = 0; - struct column *col = table->col; + struct column *col; struct box *row_group, *row, *cell; enum css_width_e wtype; css_fixed value = 0; @@ -312,6 +325,13 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) if (table->max_width != UNKNOWN_MAX_WIDTH) return; + if (table_calculate_column_types(&content->len_ctx, table) == false) { + NSLOG(netsurf, WARNING, + "Could not establish table column types."); + return; + } + col = table->col; + /* start with 0 except for fixed-width columns */ for (i = 0; i != table->columns; i++) { if (col[i].type == COLUMN_WIDTH_FIXED) @@ -328,7 +348,8 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) css_computed_border_spacing(table->style, &h, &hu, &v, &vu); - border_spacing_h = FIXTOINT(nscss_len2px(h, hu, table->style)); + border_spacing_h = FIXTOINT(nscss_len2px(&content->len_ctx, + h, hu, table->style)); } /* 1st pass: consider cells with colspan 1 only */ @@ -344,7 +365,7 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) if (cell->columns != 1) continue; - layout_minmax_block(cell, font_func); + layout_minmax_block(cell, font_func, content); i = cell->start_column; if (col[i].positioned) @@ -367,7 +388,7 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) if (cell->columns == 1) continue; - layout_minmax_block(cell, font_func); + layout_minmax_block(cell, font_func, content); i = cell->start_column; /* find min width so far of spanned columns, and count @@ -433,7 +454,8 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) /* fixed width takes priority, unless it is too narrow */ wtype = css_computed_width(table->style, &value, &unit); if (wtype == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) { - int width = FIXTOINT(nscss_len2px(value, unit, table->style)); + int width = FIXTOINT(nscss_len2px(&content->len_ctx, + value, unit, table->style)); if (table_min < width) table_min = width; if (table_max < width) @@ -441,9 +463,11 @@ layout_minmax_table(struct box *table, const struct gui_layout_table *font_func) } /* add margins, border, padding to min, max widths */ - calculate_mbp_width(table->style, LEFT, true, true, true, + calculate_mbp_width(&content->len_ctx, + table->style, LEFT, true, true, true, &extra_fixed, &extra_frac); - calculate_mbp_width(table->style, RIGHT, true, true, true, + calculate_mbp_width(&content->len_ctx, + table->style, RIGHT, true, true, true, &extra_fixed, &extra_frac); if (extra_fixed < 0) extra_fixed = 0; @@ -478,7 +502,8 @@ layout_minmax_line(struct box *first, int *line_max, bool first_line, bool *line_has_height, - const struct gui_layout_table *font_func) + const struct gui_layout_table *font_func, + const html_content *content) { int min = 0, max = 0, width, height, fixed; float frac; @@ -524,9 +549,11 @@ layout_minmax_line(struct box *first, if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT) { assert(b->children); if (b->children->type == BOX_BLOCK) - layout_minmax_block(b->children, font_func); + layout_minmax_block(b->children, font_func, + content); else - layout_minmax_table(b->children, font_func); + layout_minmax_table(b->children, font_func, + content); b->min_width = b->children->min_width; b->max_width = b->children->max_width; if (min < b->min_width) @@ -536,7 +563,7 @@ layout_minmax_line(struct box *first, } if (b->type == BOX_INLINE_BLOCK) { - layout_minmax_block(b, font_func); + layout_minmax_block(b, font_func, content); if (min < b->min_width) min = b->min_width; max += b->max_width; @@ -547,16 +574,18 @@ layout_minmax_line(struct box *first, } assert(b->style); - font_plot_style_from_css(b->style, &fstyle); + font_plot_style_from_css(&content->len_ctx, b->style, &fstyle); if (b->type == BOX_INLINE && !b->object && !(b->flags & REPLACE_DIM) && !(b->flags & IFRAME)) { fixed = frac = 0; - calculate_mbp_width(b->style, LEFT, true, true, true, + calculate_mbp_width(&content->len_ctx, + b->style, LEFT, true, true, true, &fixed, &frac); if (!b->inline_end) - calculate_mbp_width(b->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->style, RIGHT, true, true, true, &fixed, &frac); if (0 < fixed) @@ -565,7 +594,8 @@ layout_minmax_line(struct box *first, /* \todo update min width, consider fractional extra */ } else if (b->type == BOX_INLINE_END) { fixed = frac = 0; - calculate_mbp_width(b->inline_end->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->inline_end->style, RIGHT, true, true, true, &fixed, &frac); if (0 < fixed) @@ -686,15 +716,17 @@ layout_minmax_line(struct box *first, width = AUTO; } else { - width = FIXTOINT(nscss_len2px(value, unit, - b->style)); + width = FIXTOINT(nscss_len2px(&content->len_ctx, + value, unit, b->style)); if (bs == CSS_BOX_SIZING_BORDER_BOX) { fixed = frac = 0; - calculate_mbp_width(block->style, LEFT, + calculate_mbp_width(&content->len_ctx, + block->style, LEFT, false, true, true, &fixed, &frac); - calculate_mbp_width(block->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + block->style, RIGHT, false, true, true, &fixed, &frac); if (width < fixed) { @@ -711,7 +743,8 @@ layout_minmax_line(struct box *first, /* height */ htype = css_computed_height(b->style, &value, &unit); if (htype == CSS_HEIGHT_SET) { - height = FIXTOINT(nscss_len2px(value, unit, b->style)); + height = FIXTOINT(nscss_len2px(&content->len_ctx, + value, unit, b->style)); } else { height = AUTO; } @@ -727,17 +760,21 @@ layout_minmax_line(struct box *first, fixed = frac = 0; if (bs == CSS_BOX_SIZING_BORDER_BOX) { - calculate_mbp_width(b->style, LEFT, + calculate_mbp_width(&content->len_ctx, + b->style, LEFT, true, false, false, &fixed, &frac); - calculate_mbp_width(b->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->style, RIGHT, true, false, false, &fixed, &frac); } else { - calculate_mbp_width(b->style, LEFT, + calculate_mbp_width(&content->len_ctx, + b->style, LEFT, true, true, true, &fixed, &frac); - calculate_mbp_width(b->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->style, RIGHT, true, true, true, &fixed, &frac); } @@ -750,17 +787,21 @@ layout_minmax_line(struct box *first, fixed = frac = 0; if (bs == CSS_BOX_SIZING_BORDER_BOX) { - calculate_mbp_width(b->style, LEFT, + calculate_mbp_width(&content->len_ctx, + b->style, LEFT, true, false, false, &fixed, &frac); - calculate_mbp_width(b->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->style, RIGHT, true, false, false, &fixed, &frac); } else { - calculate_mbp_width(b->style, LEFT, + calculate_mbp_width(&content->len_ctx, + b->style, LEFT, true, true, true, &fixed, &frac); - calculate_mbp_width(b->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + b->style, RIGHT, true, true, true, &fixed, &frac); } @@ -771,8 +812,10 @@ layout_minmax_line(struct box *first, } else { /* form control with no object */ if (width == AUTO) - width = FIXTOINT(nscss_len2px(INTTOFIX(1), - CSS_UNIT_EM, b->style)); + width = FIXTOINT(nscss_len2px( + &content->len_ctx, + INTTOFIX(1), CSS_UNIT_EM, + b->style)); } if (min < width) @@ -785,7 +828,7 @@ layout_minmax_line(struct box *first, if (first_line) { /* todo: handle percentage values properly */ /* todo: handle text-indent interaction with floats */ - int text_indent = layout_text_indent( + int text_indent = layout_text_indent(&content->len_ctx, first->parent->parent->style, 100); min = (min + text_indent < 0) ? 0 : min + text_indent; max = (max + text_indent < 0) ? 0 : max + text_indent; @@ -815,7 +858,8 @@ layout_minmax_line(struct box *first, static void layout_minmax_inline_container(struct box *inline_container, bool *has_height, - const struct gui_layout_table *font_func) + const struct gui_layout_table *font_func, + const html_content *content) { struct box *child; int line_min = 0, line_max = 0; @@ -833,7 +877,8 @@ layout_minmax_inline_container(struct box *inline_container, for (child = inline_container->children; child; ) { child = layout_minmax_line(child, &line_min, &line_max, - first_line, &line_has_height, font_func); + first_line, &line_has_height, font_func, + content); if (min < line_min) min = line_min; if (max < line_max) @@ -856,11 +901,14 @@ layout_minmax_inline_container(struct box *inline_container, * * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL * \param font_func font functions + * \param content The HTML content being layed out. * \post block->min_width and block->max_width filled in, * 0 <= block->min_width <= block->max_width */ -static void -layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) +static void layout_minmax_block( + struct box *block, + const struct gui_layout_table *font_func, + const html_content *content) { struct box *child; int min = 0, max = 0; @@ -913,7 +961,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) css_fixed size = INTTOFIX(10); css_unit unit = CSS_UNIT_EM; - min = max = FIXTOINT(nscss_len2px(size, unit, block->style)); + min = max = FIXTOINT(nscss_len2px(&content->len_ctx, + size, unit, block->style)); block->flags |= HAS_HEIGHT; } @@ -926,7 +975,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) /* form checkbox or radio button * if width is AUTO, set it to 1em */ - min = max = FIXTOINT(nscss_len2px(size, unit, block->style)); + min = max = FIXTOINT(nscss_len2px(&content->len_ctx, + size, unit, block->style)); block->flags |= HAS_HEIGHT; } @@ -934,7 +984,7 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) if (block->object) { if (content_get_type(block->object) == CONTENT_HTML) { layout_minmax_block(html_get_box_tree(block->object), - font_func); + font_func, content); min = html_get_box_tree(block->object)->min_width; max = html_get_box_tree(block->object)->max_width; } else { @@ -951,7 +1001,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) for (child = block->children; child; child = child->next) { switch (child->type) { case BOX_BLOCK: - layout_minmax_block(child, font_func); + layout_minmax_block(child, font_func, + content); if (child->flags & HAS_HEIGHT) child_has_height = true; break; @@ -960,7 +1011,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) child->flags |= NEED_MIN; layout_minmax_inline_container(child, - &child_has_height, font_func); + &child_has_height, font_func, + content); if (child_has_height && child == child->parent->children) { @@ -968,7 +1020,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) } break; case BOX_TABLE: - layout_minmax_table(child, font_func); + layout_minmax_table(child, font_func, + content); /* todo: fix for zero height tables */ child_has_height = true; child->flags |= MAKE_HEIGHT; @@ -1006,14 +1059,17 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) /* fixed width takes priority */ if (block->type != BOX_TABLE_CELL && wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT) { - min = max = FIXTOINT(nscss_len2px(width, wunit, block->style)); + min = max = FIXTOINT(nscss_len2px(&content->len_ctx, + width, wunit, block->style)); if (bs == CSS_BOX_SIZING_BORDER_BOX) { int border_box_fixed = 0; float border_box_frac = 0; - calculate_mbp_width(block->style, LEFT, + calculate_mbp_width(&content->len_ctx, + block->style, LEFT, false, true, true, &border_box_fixed, &border_box_frac); - calculate_mbp_width(block->style, RIGHT, + calculate_mbp_width(&content->len_ctx, + block->style, RIGHT, false, true, true, &border_box_fixed, &border_box_frac); if (min < border_box_fixed) { @@ -1033,14 +1089,18 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) * and paddings are wrong. */ if (bs == CSS_BOX_SIZING_BORDER_BOX && wtype == CSS_WIDTH_SET) { /* Border and padding included in width, so just get margin */ - calculate_mbp_width(block->style, LEFT, true, false, false, + calculate_mbp_width(&content->len_ctx, + block->style, LEFT, true, false, false, &extra_fixed, &extra_frac); - calculate_mbp_width(block->style, RIGHT, true, false, false, + calculate_mbp_width(&content->len_ctx, + block->style, RIGHT, true, false, false, &extra_fixed, &extra_frac); } else { - calculate_mbp_width(block->style, LEFT, true, true, true, + calculate_mbp_width(&content->len_ctx, + block->style, LEFT, true, true, true, &extra_fixed, &extra_frac); - calculate_mbp_width(block->style, RIGHT, true, true, true, + calculate_mbp_width(&content->len_ctx, + block->style, RIGHT, true, true, true, &extra_fixed, &extra_frac); } if (extra_fixed < 0) @@ -1070,6 +1130,7 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) * * This turns the specified dimension into a content-box dimension. * + * \param len_ctx Length conversion context * \param box gadget to adjust dimensions of * \param available_width width of containing block * \param setwidth set true if the dimension to be tweaked is a width, @@ -1079,6 +1140,7 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func) * gadget properties. */ static void layout_handle_box_sizing( + const nscss_len_ctx *len_ctx, struct box *box, int available_width, bool setwidth, @@ -1095,9 +1157,11 @@ static void layout_handle_box_sizing( int fixed = 0; float frac = 0; - calculate_mbp_width(box->style, setwidth ? LEFT : TOP, + calculate_mbp_width(len_ctx, box->style, + setwidth ? LEFT : TOP, false, true, true, &fixed, &frac); - calculate_mbp_width(box->style, setwidth ? RIGHT : BOTTOM, + calculate_mbp_width(len_ctx, box->style, + setwidth ? RIGHT : BOTTOM, false, true, true, &fixed, &frac); orig -= frac * available_width + fixed; *dimension = orig > 0 ? orig : 0; @@ -1108,6 +1172,7 @@ static void layout_handle_box_sizing( /** * Calculate width, height, and thickness of margins, paddings, and borders. * + * \param len_ctx Length conversion context * \param available_width width of containing block * \param viewport_height height of viewport in pixels or -ve if unknown * \param box current box @@ -1124,7 +1189,8 @@ static void layout_handle_box_sizing( * \param border filled with border widths, may be NULL */ static void -layout_find_dimensions(int available_width, +layout_find_dimensions(const nscss_len_ctx *len_ctx, + int available_width, int viewport_height, struct box *box, const css_computed_style *style, @@ -1153,15 +1219,15 @@ layout_find_dimensions(int available_width, *width = FPCT_OF_INT_TOINT( value, available_width); } else { - *width = FIXTOINT(nscss_len2px(value, unit, - style)); + *width = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { *width = AUTO; } if (*width != AUTO) { - layout_handle_box_sizing(box, available_width, + layout_handle_box_sizing(len_ctx, box, available_width, true, width); } } @@ -1241,15 +1307,15 @@ layout_find_dimensions(int available_width, *height = AUTO; } } else { - *height = FIXTOINT(nscss_len2px(value, unit, - style)); + *height = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { *height = AUTO; } if (*height != AUTO) { - layout_handle_box_sizing(box, available_width, + layout_handle_box_sizing(len_ctx, box, available_width, false, height); } } @@ -1266,8 +1332,8 @@ layout_find_dimensions(int available_width, *max_width = FPCT_OF_INT_TOINT(value, available_width); } else { - *max_width = FIXTOINT(nscss_len2px(value, unit, - style)); + *max_width = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { /* Inadmissible */ @@ -1275,7 +1341,7 @@ layout_find_dimensions(int available_width, } if (*max_width != -1) { - layout_handle_box_sizing(box, available_width, + layout_handle_box_sizing(len_ctx, box, available_width, true, max_width); } } @@ -1292,8 +1358,8 @@ layout_find_dimensions(int available_width, *min_width = FPCT_OF_INT_TOINT(value, available_width); } else { - *min_width = FIXTOINT(nscss_len2px(value, unit, - style)); + *min_width = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { /* Inadmissible */ @@ -1301,7 +1367,7 @@ layout_find_dimensions(int available_width, } if (*min_width != 0) { - layout_handle_box_sizing(box, available_width, + layout_handle_box_sizing(len_ctx, box, available_width, true, min_width); } } @@ -1318,8 +1384,8 @@ layout_find_dimensions(int available_width, /* TODO: handle percentage */ *max_height = -1; } else { - *max_height = FIXTOINT(nscss_len2px(value, unit, - style)); + *max_height = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { /* Inadmissible */ @@ -1339,8 +1405,8 @@ layout_find_dimensions(int available_width, /* TODO: handle percentage */ *min_height = 0; } else { - *min_height = FIXTOINT(nscss_len2px(value, unit, - style)); + *min_height = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } else { /* Inadmissible */ @@ -1378,8 +1444,9 @@ layout_find_dimensions(int available_width, margin[i] = FPCT_OF_INT_TOINT(value, available_width); } else { - margin[i] = FIXTOINT(nscss_len2px(value, - unit, style)); + margin[i] = FIXTOINT(nscss_len2px( + len_ctx, + value, unit, style)); } } else { margin[i] = AUTO; @@ -1411,8 +1478,8 @@ layout_find_dimensions(int available_width, padding[i] = FPCT_OF_INT_TOINT(value, available_width); } else { - padding[i] = FIXTOINT(nscss_len2px(value, unit, - style)); + padding[i] = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); } } @@ -1459,8 +1526,8 @@ layout_find_dimensions(int available_width, /* spec unclear: following Mozilla */ border[i].width = 0; else - border[i].width = FIXTOINT(nscss_len2px(value, - unit, style)); + border[i].width = FIXTOINT(nscss_len2px(len_ctx, + value, unit, style)); /* Special case for border-collapse: make all borders * on table/table-row-group/table-row zero width. */ @@ -1478,6 +1545,7 @@ layout_find_dimensions(int available_width, /** * Find next block that current margin collapses to. * + * \param len_ctx Length conversion context * \param box box to start tree-order search from (top margin is included) * \param block box responsible for current block fromatting context * \param viewport_height height of viewport in px @@ -1486,7 +1554,8 @@ layout_find_dimensions(int available_width, * \return next box that current margin collapses to, or NULL if none. */ static struct box* -layout_next_margin_block(struct box *box, +layout_next_margin_block(const nscss_len_ctx *len_ctx, + struct box *box, struct box *block, int viewport_height, int *max_pos_margin, @@ -1505,7 +1574,8 @@ layout_next_margin_block(struct box *box, /* Get margins */ if (box->style) { - layout_find_dimensions(box->parent->width, + layout_find_dimensions(len_ctx, + box->parent->width, viewport_height, box, box->style, NULL, NULL, NULL, NULL, @@ -1579,7 +1649,8 @@ layout_next_margin_block(struct box *box, /* Get margins */ if (box->style) { - layout_find_dimensions(box->parent->width, + layout_find_dimensions(len_ctx, + box->parent->width, viewport_height, box, box->style, NULL, NULL, NULL, NULL, @@ -1815,6 +1886,7 @@ layout_solve_width(struct box *box, * Compute dimensions of box, margins, paddings, and borders for a block-level * element. * + * \param len_ctx Length conversion context * \param available_width Max width available in pixels * \param viewport_height Height of viewport in pixels or -ve if unknown * \param lm min left margin required to avoid floats in px. @@ -1827,7 +1899,8 @@ layout_solve_width(struct box *box, * See CSS 2.1 10.3.3, 10.3.4, 10.6.2, and 10.6.3. */ static void -layout_block_find_dimensions(int available_width, +layout_block_find_dimensions(const nscss_len_ctx *len_ctx, + int available_width, int viewport_height, int lm, int rm, @@ -1840,8 +1913,8 @@ layout_block_find_dimensions(int available_width, struct box_border *border = box->border; const css_computed_style *style = box->style; - layout_find_dimensions(available_width, viewport_height, box, style, - &width, &height, &max_width, &min_width, + layout_find_dimensions(len_ctx, available_width, viewport_height, box, + style, &width, &height, &max_width, &min_width, &max_height, &min_height, margin, padding, border); if (box->object && !(box->flags & REPLACE_DIM) && @@ -1994,8 +2067,9 @@ static bool layout_table(struct box *table, int available_width, memcpy(col, table->col, sizeof(col[0]) * columns); /* find margins, paddings, and borders for table and cells */ - layout_find_dimensions(available_width, -1, table, style, 0, 0, 0, 0, - 0, 0, table->margin, table->padding, table->border); + layout_find_dimensions(&content->len_ctx, available_width, -1, table, + style, 0, 0, 0, 0, 0, 0, table->margin, table->padding, + table->border); for (row_group = table->children; row_group; row_group = row_group->next) { for (row = row_group->children; row; row = row->next) { @@ -2004,9 +2078,11 @@ static bool layout_table(struct box *table, int available_width, enum css_overflow_e overflow_y; assert(c->style); - table_used_border_for_cell(c); - layout_find_dimensions(available_width, -1, - c, c->style, 0, 0, 0, 0, 0, 0, + table_used_border_for_cell( + &content->len_ctx, c); + layout_find_dimensions(&content->len_ctx, + available_width, -1, c, + c->style, 0, 0, 0, 0, 0, 0, 0, c->padding, c->border); overflow_x = css_computed_overflow_x(c->style); @@ -2034,8 +2110,10 @@ static bool layout_table(struct box *table, int available_width, css_computed_border_spacing(style, &h, &hu, &v, &vu); - border_spacing_h = FIXTOINT(nscss_len2px(h, hu, style)); - border_spacing_v = FIXTOINT(nscss_len2px(v, vu, style)); + border_spacing_h = FIXTOINT(nscss_len2px(&content->len_ctx, + h, hu, style)); + border_spacing_v = FIXTOINT(nscss_len2px(&content->len_ctx, + v, vu, style)); } /* find specified table width, or available width if auto-width */ @@ -2045,7 +2123,8 @@ static bool layout_table(struct box *table, int available_width, table_width = FPCT_OF_INT_TOINT(value, available_width); } else { table_width = - FIXTOINT(nscss_len2px(value, unit, style)); + FIXTOINT(nscss_len2px(&content->len_ctx, + value, unit, style)); } /* specified width includes border */ @@ -2123,7 +2202,8 @@ static bool layout_table(struct box *table, int available_width, } else { /* This is the minimum height for the table * (see 17.5.3) */ - min_height = FIXTOINT(nscss_len2px(value, unit, style)); + min_height = FIXTOINT(nscss_len2px(&content->len_ctx, + value, unit, style)); } } @@ -2313,8 +2393,9 @@ static bool layout_table(struct box *table, int available_width, htype = css_computed_height(row->style, &value, &unit); if (htype == CSS_HEIGHT_SET && unit != CSS_UNIT_PCT) { - row_height = FIXTOINT(nscss_len2px(value, unit, - row->style)); + row_height = FIXTOINT(nscss_len2px( + &content->len_ctx, + value, unit, row->style)); } for (c = row->children; c; c = c->next) { assert(c->style); @@ -2351,8 +2432,9 @@ static bool layout_table(struct box *table, int available_width, /* some sites use height="1" or similar * to attempt to make cells as small as * possible, so treat it as a minimum */ - int h = FIXTOINT(nscss_len2px(value, - unit, c->style)); + int h = FIXTOINT(nscss_len2px( + &content->len_ctx, + value, unit, c->style)); if (c->height < h) c->height = h; } @@ -2496,12 +2578,16 @@ static bool layout_table(struct box *table, int available_width, /** * Manimpulate box height according to CSS min-height and max-height properties * + * \param len_ctx CSS length conversion context for document. * \param box block to modify with any min-height or max-height * \param container containing block for absolutely positioned elements, or * NULL for non absolutely positioned elements. * \return whether the height has been changed */ -static bool layout_apply_minmax_height(struct box *box, struct box *container) +static bool layout_apply_minmax_height( + const nscss_len_ctx *len_ctx, + struct box *box, + struct box *container) { int h; struct box *containing_block = NULL; @@ -2560,8 +2646,8 @@ static bool layout_apply_minmax_height(struct box *box, struct box *container) } } } else { - h = FIXTOINT(nscss_len2px(value, unit, - box->style)); + h = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); if (h < box->height) { box->height = h; updated = true; @@ -2590,8 +2676,8 @@ static bool layout_apply_minmax_height(struct box *box, struct box *container) } } } else { - h = FIXTOINT(nscss_len2px(value, unit, - box->style)); + h = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); if (h > box->height) { box->height = h; updated = true; @@ -2759,6 +2845,7 @@ layout_text_box_split(html_content *content, * Compute dimensions of box, margins, paddings, and borders for a floating * element using shrink-to-fit. Also used for inline-blocks. * + * \param len_ctx CSS length conversion context for document. * \param available_width Max width available in pixels * \param style Box's style * \param box Box for which to find dimensions @@ -2766,9 +2853,11 @@ layout_text_box_split(html_content *content, * height are updated. */ static void -layout_float_find_dimensions(int available_width, - const css_computed_style *style, - struct box *box) +layout_float_find_dimensions( + const nscss_len_ctx *len_ctx, + int available_width, + const css_computed_style *style, + struct box *box) { int width, height, max_width, min_width, max_height, min_height; int *margin = box->margin; @@ -2785,9 +2874,9 @@ layout_float_find_dimensions(int available_width, overflow_y == CSS_OVERFLOW_AUTO) ? SCROLLBAR_WIDTH : 0; - layout_find_dimensions(available_width, -1, box, style, &width, &height, - &max_width, &min_width, &max_height, &min_height, - margin, padding, border); + layout_find_dimensions(len_ctx, available_width, -1, box, style, + &width, &height, &max_width, &min_width, + &max_height, &min_height, margin, padding, border); if (margin[LEFT] == AUTO) margin[LEFT] = 0; @@ -2821,26 +2910,26 @@ layout_float_find_dimensions(int available_width, box->gadget->type == GADGET_FILE) { if (width == AUTO) { size = INTTOFIX(10); - width = FIXTOINT(nscss_len2px(size, unit, - box->style)); + width = FIXTOINT(nscss_len2px(len_ctx, + size, unit, box->style)); } if (box->gadget->type == GADGET_FILE && height == AUTO) { size = FLTTOFIX(1.5); - height = FIXTOINT(nscss_len2px(size, unit, - box->style)); + height = FIXTOINT(nscss_len2px(len_ctx, + size, unit, box->style)); } } if (box->gadget->type == GADGET_TEXTAREA) { if (width == AUTO) { size = INTTOFIX(10); - width = FIXTOINT(nscss_len2px(size, unit, - box->style)); + width = FIXTOINT(nscss_len2px(len_ctx, + size, unit, box->style)); } if (height == AUTO) { size = INTTOFIX(4); - height = FIXTOINT(nscss_len2px(size, unit, - box->style)); + height = FIXTOINT(nscss_len2px(len_ctx, + size, unit, box->style)); } } } else if (width == AUTO) { @@ -2861,10 +2950,10 @@ layout_float_find_dimensions(int available_width, * mbp as was used in layout_minmax_block() */ int fixed = 0; float frac = 0; - calculate_mbp_width(box->style, LEFT, true, true, true, - &fixed, &frac); - calculate_mbp_width(box->style, RIGHT, true, true, true, - &fixed, &frac); + calculate_mbp_width(len_ctx, box->style, LEFT, + true, true, true, &fixed, &frac); + calculate_mbp_width(len_ctx, box->style, RIGHT, + true, true, true, &fixed, &frac); if (fixed < 0) fixed = 0; @@ -2902,7 +2991,7 @@ static bool layout_float(struct box *b, int width, html_content *content) { assert(b->type == BOX_TABLE || b->type == BOX_BLOCK || b->type == BOX_INLINE_BLOCK); - layout_float_find_dimensions(width, b->style, b); + layout_float_find_dimensions(&content->len_ctx, width, b->style, b); if (b->type == BOX_TABLE) { if (!layout_table(b, width, content)) return false; @@ -2974,7 +3063,9 @@ place_float_below(struct box *c, int width, int cx, int y, struct box *cont) /** * Calculate line height from a style. */ -static int line_height(const css_computed_style *style) +static int line_height( + const nscss_len_ctx *len_ctx, + const css_computed_style *style) { enum css_line_height_e lhtype; css_fixed lhvalue = 0; @@ -2992,14 +3083,16 @@ static int line_height(const css_computed_style *style) if (lhtype == CSS_LINE_HEIGHT_NUMBER || lhunit == CSS_UNIT_PCT) { - line_height = nscss_len2px(lhvalue, CSS_UNIT_EM, style); + line_height = nscss_len2px(len_ctx, + lhvalue, CSS_UNIT_EM, style); if (lhtype != CSS_LINE_HEIGHT_NUMBER) line_height = FDIV(line_height, F_100); } else { assert(lhunit != CSS_UNIT_PCT); - line_height = nscss_len2px(lhvalue, lhunit, style); + line_height = nscss_len2px(len_ctx, + lhvalue, lhunit, style); } return FIXTOINT(line_height); @@ -3071,7 +3164,8 @@ layout_line(struct box *first, x1 -= cx; if (indent) - x0 += layout_text_indent(first->parent->parent->style, *width); + x0 += layout_text_indent(&content->len_ctx, + first->parent->parent->style, *width); if (x1 < x0) x1 = x0; @@ -3080,8 +3174,8 @@ layout_line(struct box *first, * this is the line-height if there are text children and also in the * case of an initially empty text input */ if (has_text_children || first->parent->parent->gadget) - used_height = height = - line_height(first->parent->parent->style); + used_height = height = line_height(&content->len_ctx, + first->parent->parent->style); else /* inline containers with no text are usually for layout and * look better with no minimum line-height */ @@ -3120,7 +3214,7 @@ layout_line(struct box *first, continue; assert(b->style != NULL); - font_plot_style_from_css(b->style, &fstyle); + font_plot_style_from_css(&content->len_ctx, b->style, &fstyle); x += space_after; @@ -3144,9 +3238,9 @@ layout_line(struct box *first, if (b->type == BOX_INLINE) { /* calculate borders, margins, and padding */ - layout_find_dimensions(*width, -1, b, b->style, 0, 0, - 0, 0, 0, 0, b->margin, b->padding, - b->border); + layout_find_dimensions(&content->len_ctx, + *width, -1, b, b->style, 0, 0, 0, 0, + 0, 0, b->margin, b->padding, b->border); for (i = 0; i != 4; i++) if (b->margin[i] == AUTO) b->margin[i] = 0; @@ -3179,7 +3273,8 @@ layout_line(struct box *first, if (!b->object && !(b->flags & IFRAME) && !b->gadget && !(b->flags & REPLACE_DIM)) { /* inline non-replaced, 10.3.1 and 10.6.1 */ - b->height = line_height(b->style ? b->style : + b->height = line_height(&content->len_ctx, + b->style ? b->style : b->parent->parent->style); if (height < b->height) height = b->height; @@ -3249,9 +3344,12 @@ layout_line(struct box *first, /* inline replaced, 10.3.2 and 10.6.2 */ assert(b->style); - layout_find_dimensions(*width, -1, b, b->style, - &b->width, &b->height, &max_width, &min_width, - &max_height, &min_height, NULL, NULL, NULL); + layout_find_dimensions(&content->len_ctx, + *width, -1, b, b->style, + &b->width, &b->height, + &max_width, &min_width, + &max_height, &min_height, + NULL, NULL, NULL); if (b->object && !(b->flags & REPLACE_DIM)) { layout_get_object_dimensions(b, &b->width, &b->height, @@ -3269,10 +3367,12 @@ layout_line(struct box *first, } else { /* form control with no object */ if (b->width == AUTO) - b->width = FIXTOINT(nscss_len2px(INTTOFIX(1), + b->width = FIXTOINT(nscss_len2px( + &content->len_ctx, INTTOFIX(1), CSS_UNIT_EM, b->style)); if (b->height == AUTO) - b->height = FIXTOINT(nscss_len2px(INTTOFIX(1), + b->height = FIXTOINT(nscss_len2px( + &content->len_ctx, INTTOFIX(1), CSS_UNIT_EM, b->style)); } @@ -3306,7 +3406,8 @@ layout_line(struct box *first, x1 -= cx; if (indent) - x0 += layout_text_indent(first->parent->parent->style, *width); + x0 += layout_text_indent(&content->len_ctx, + first->parent->parent->style, *width); if (x1 < x0) x1 = x0; @@ -3363,8 +3464,9 @@ layout_line(struct box *first, space_after = 0; else if (b->text || b->type == BOX_INLINE_END) { if (b->space == UNKNOWN_WIDTH) { - font_plot_style_from_css(b->style, - &fstyle); + font_plot_style_from_css( + &content->len_ctx, + b->style, &fstyle); /** \todo handle errors */ font_func->width(&fstyle, " ", 1, &b->space); @@ -3517,7 +3619,8 @@ layout_line(struct box *first, !(split_box->flags & IFRAME) && !split_box->gadget && split_box->text) { - font_plot_style_from_css(split_box->style, &fstyle); + font_plot_style_from_css(&content->len_ctx, + split_box->style, &fstyle); /** \todo handle errors */ font_func->split(&fstyle, split_box->text, @@ -3879,7 +3982,8 @@ layout_block_context(struct box *block, gadget_unit = CSS_UNIT_EM; gadget_size = INTTOFIX(1); if (block->height == AUTO) - block->height = FIXTOINT(nscss_len2px(gadget_size, + block->height = FIXTOINT(nscss_len2px( + &content->len_ctx, gadget_size, gadget_unit, block->style)); } @@ -3943,7 +4047,8 @@ layout_block_context(struct box *block, /* If we don't know which box the current margin collapses * through to, find out. Update the pos/neg margin values. */ if (margin_collapse == NULL) { - margin_collapse = layout_next_margin_block(box, block, + margin_collapse = layout_next_margin_block( + &content->len_ctx, box, block, viewport_height, &max_pos_margin, &max_neg_margin); /* We have a margin that has not yet been applied. */ @@ -3994,7 +4099,8 @@ layout_block_context(struct box *block, box->parent->padding[RIGHT] - x1; } - layout_block_find_dimensions(box->parent->width, + layout_block_find_dimensions(&content->len_ctx, + box->parent->width, viewport_height, lm, rm, box); if (box->type == BOX_BLOCK && !(box->flags & IFRAME)) { layout_block_add_scrollbar(box, RIGHT); @@ -4234,8 +4340,9 @@ layout_block_context(struct box *block, if (box->style && css_computed_position(box->style) != CSS_POSITION_ABSOLUTE && - layout_apply_minmax_height(box, - NULL)) { + layout_apply_minmax_height( + &content->len_ctx, + box, NULL)) { /* Height altered */ /* Set current cy */ cy += box->height - @@ -4291,19 +4398,23 @@ layout_block_context(struct box *block, if (block->style && css_computed_position(block->style) != CSS_POSITION_ABSOLUTE) { /* Block is in normal flow */ - layout_apply_minmax_height(block, NULL); + layout_apply_minmax_height(&content->len_ctx, block, NULL); } if (block->gadget && (block->gadget->type == GADGET_TEXTAREA || block->gadget->type == GADGET_PASSWORD || block->gadget->type == GADGET_TEXTBOX)) { + plot_font_style_t fstyle; int ta_width = block->padding[LEFT] + block->width + block->padding[RIGHT]; int ta_height = block->padding[TOP] + block->height + block->padding[BOTTOM]; + font_plot_style_from_css(&content->len_ctx, + block->style, &fstyle); + fstyle.background = NS_TRANSPARENT; textarea_set_layout(block->gadget->data.text.ta, - ta_width, ta_height, + &fstyle, ta_width, ta_height, block->padding[TOP], block->padding[RIGHT], block->padding[BOTTOM], block->padding[LEFT]); } @@ -4317,7 +4428,8 @@ layout_block_context(struct box *block, */ static void layout_lists(struct box *box, - const struct gui_layout_table *font_func) + const struct gui_layout_table *font_func, + const nscss_len_ctx *len_ctx) { struct box *child; struct box *marker; @@ -4332,12 +4444,13 @@ layout_lists(struct box *box, marker->x = -marker->width; marker->height = content_get_height(marker->object); - marker->y = (line_height(marker->style) - + marker->y = (line_height(len_ctx, + marker->style) - marker->height) / 2; } else if (marker->text) { if (marker->width == UNKNOWN_WIDTH) { - font_plot_style_from_css(marker->style, - &fstyle); + font_plot_style_from_css(len_ctx, + marker->style, &fstyle); font_func->width(&fstyle, marker->text, marker->length, @@ -4346,7 +4459,8 @@ layout_lists(struct box *box, } marker->x = -marker->width; marker->y = 0; - marker->height = line_height(marker->style); + marker->height = line_height(len_ctx, + marker->style); } else { marker->x = 0; marker->y = 0; @@ -4356,7 +4470,7 @@ layout_lists(struct box *box, /* Gap between marker and content */ marker->x -= 4; } - layout_lists(child, font_func); + layout_lists(child, font_func, len_ctx); } } @@ -4365,6 +4479,7 @@ layout_lists(struct box *box, * Compute box offsets for a relatively or absolutely positioned box with * respect to a box. * + * \param len_ctx Length conversion context * \param box box to compute offsets for * \param containing_block box to compute percentages with respect to * \param top updated to top offset, or AUTO @@ -4375,7 +4490,8 @@ layout_lists(struct box *box, * See CSS 2.1 9.3.2. containing_block must have width and height. */ static void -layout_compute_offsets(struct box *box, +layout_compute_offsets(const nscss_len_ctx *len_ctx, + struct box *box, struct box *containing_block, int *top, int *right, @@ -4397,7 +4513,8 @@ layout_compute_offsets(struct box *box, *left = FPCT_OF_INT_TOINT(value, containing_block->width); } else { - *left = FIXTOINT(nscss_len2px(value, unit, box->style)); + *left = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); } } else { *left = AUTO; @@ -4410,8 +4527,8 @@ layout_compute_offsets(struct box *box, *right = FPCT_OF_INT_TOINT(value, containing_block->width); } else { - *right = FIXTOINT(nscss_len2px(value, unit, - box->style)); + *right = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); } } else { *right = AUTO; @@ -4424,7 +4541,8 @@ layout_compute_offsets(struct box *box, *top = FPCT_OF_INT_TOINT(value, containing_block->height); } else { - *top = FIXTOINT(nscss_len2px(value, unit, box->style)); + *top = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); } } else { *top = AUTO; @@ -4437,8 +4555,8 @@ layout_compute_offsets(struct box *box, *bottom = FPCT_OF_INT_TOINT(value, containing_block->height); } else { - *bottom = FIXTOINT(nscss_len2px(value, unit, - box->style)); + *bottom = FIXTOINT(nscss_len2px(len_ctx, + value, unit, box->style)); } } else { *bottom = AUTO; @@ -4494,16 +4612,17 @@ layout_absolute(struct box *box, /** \todo inline containers */ } - layout_compute_offsets(box, containing_block, + layout_compute_offsets(&content->len_ctx, box, containing_block, &top, &right, &bottom, &left); /* Pass containing block into layout_find_dimensions via the float * containing block box member. This is unused for absolutely positioned * boxes because a box can't be floated and absolutely positioned. */ box->float_container = containing_block; - layout_find_dimensions(available_width, -1, box, box->style, - &width, &height, &max_width, &min_width, - 0, 0, margin, padding, border); + layout_find_dimensions(&content->len_ctx, available_width, -1, + box, box->style, &width, &height, + &max_width, &min_width, 0, 0, + margin, padding, border); box->float_container = NULL; /* 10.3.7 */ @@ -4818,7 +4937,7 @@ layout_absolute(struct box *box, /** \todo Inline ancestors */ } box->height = height; - layout_apply_minmax_height(box, containing_block); + layout_apply_minmax_height(&content->len_ctx, box, containing_block); return true; } @@ -4895,11 +5014,16 @@ layout_position_absolute(struct box *box, /** * Compute a box's relative offset as per CSS 2.1 9.4.3 * + * \param len_ctx Length conversion context * \param box Box to compute relative offsets for. * \param x Receives relative offset in x. * \param y Receives relative offset in y. */ -static void layout_compute_relative_offset(struct box *box, int *x, int *y) +static void layout_compute_relative_offset( + const nscss_len_ctx *len_ctx, + struct box *box, + int *x, + int *y) { int left, right, top, bottom; struct box *containing_block; @@ -4916,7 +5040,7 @@ static void layout_compute_relative_offset(struct box *box, int *x, int *y) containing_block = box->parent; } - layout_compute_offsets(box, containing_block, + layout_compute_offsets(len_ctx, box, containing_block, &top, &right, &bottom, &left); if (left == AUTO && right == AUTO) @@ -4964,6 +5088,7 @@ static void layout_compute_relative_offset(struct box *box, int *x, int *y) /** * Adjust positions of relatively positioned boxes. * + * \param len_ctx Length conversion context * \param root box to adjust the position of * \param fp box which forms the block formatting context for children of * "root" which are floats @@ -4975,7 +5100,12 @@ static void layout_compute_relative_offset(struct box *box, int *x, int *y) * box, "fp", for float children of "root" */ static void -layout_position_relative(struct box *root, struct box *fp, int fx, int fy) +layout_position_relative( + const nscss_len_ctx *len_ctx, + struct box *root, + struct box *fp, + int fx, + int fy) { struct box *box; /* for children of "root" */ struct box *fn; /* for block formatting context box for children of @@ -4999,7 +5129,8 @@ layout_position_relative(struct box *root, struct box *fp, int fx, int fy) /* If relatively positioned, get offsets */ if (box->style && css_computed_position(box->style) == CSS_POSITION_RELATIVE) - layout_compute_relative_offset(box, &x, &y); + layout_compute_relative_offset( + len_ctx, box, &x, &y); else x = y = 0; @@ -5035,7 +5166,7 @@ layout_position_relative(struct box *root, struct box *fp, int fx, int fy) } /* recurse first */ - layout_position_relative(box, fn, fnx, fny); + layout_position_relative(len_ctx, box, fn, fnx, fny); /* Ignore things we're not interested in. */ if (!box->style || (box->style && @@ -5064,6 +5195,7 @@ layout_position_relative(struct box *root, struct box *fp, int fx, int fy) /** * Find a box's bounding box relative to itself, i.e. the box's border edge box * + * \param len_ctx Length conversion context * \param box box find bounding box of * \param desc_x0 updated to left of box's bbox * \param desc_y0 updated to top of box's bbox @@ -5071,9 +5203,11 @@ layout_position_relative(struct box *root, struct box *fp, int fx, int fy) * \param desc_y1 updated to bottom of box's bbox */ static void -layout_get_box_bbox(struct box *box, - int *desc_x0, int *desc_y0, - int *desc_x1, int *desc_y1) +layout_get_box_bbox( + const nscss_len_ctx *len_ctx, + struct box *box, + int *desc_x0, int *desc_y0, + int *desc_x1, int *desc_y1) { *desc_x0 = -box->border[LEFT].width; *desc_y0 = -box->border[TOP].width; @@ -5093,7 +5227,8 @@ layout_get_box_bbox(struct box *box, int text_height; css_computed_font_size(box->style, &font_size, &font_unit); - text_height = nscss_len2px(font_size, font_unit, box->style); + text_height = nscss_len2px(len_ctx, font_size, font_unit, + box->style); text_height = FIXTOINT(text_height * 3 / 4); *desc_y0 = (*desc_y0 < -text_height) ? *desc_y0 : -text_height; } @@ -5103,16 +5238,19 @@ layout_get_box_bbox(struct box *box, /** * Apply changes to box descendant_[xy][01] values due to given child. * - * \param box box to update - * \param child a box, which may affect box's descendant bbox - * \param off_x offset to apply to child->x coord to treat as child of box - * \param off_y offset to apply to child->y coord to treat as child of box + * \param len_ctx Length conversion context + * \param box box to update + * \param child a box, which may affect box's descendant bbox + * \param off_x offset to apply to child->x coord to treat as child of box + * \param off_y offset to apply to child->y coord to treat as child of box */ static void -layout_update_descendant_bbox(struct box *box, - struct box *child, - int off_x, - int off_y) +layout_update_descendant_bbox( + const nscss_len_ctx *len_ctx, + struct box *box, + struct box *child, + int off_x, + int off_y) { int child_desc_x0, child_desc_y0, child_desc_x1, child_desc_y1; @@ -5132,7 +5270,8 @@ layout_update_descendant_bbox(struct box *box, } /* Get child's border edge */ - layout_get_box_bbox(child, &child_desc_x0, &child_desc_y0, + layout_get_box_bbox(len_ctx, child, + &child_desc_x0, &child_desc_y0, &child_desc_x1, &child_desc_y1); if (overflow_x == CSS_OVERFLOW_VISIBLE && @@ -5169,9 +5308,12 @@ layout_update_descendant_bbox(struct box *box, * Recursively calculate the descendant_[xy][01] values for a laid-out box tree * and inform iframe browser windows of their size and position. * - * \param box tree of boxes to update + * \param len_ctx Length conversion context + * \param box tree of boxes to update */ -static void layout_calculate_descendant_bboxes(struct box *box) +static void layout_calculate_descendant_bboxes( + const nscss_len_ctx *len_ctx, + struct box *box) { struct box *child; @@ -5180,7 +5322,8 @@ static void layout_calculate_descendant_bboxes(struct box *box) /* assert((box->width >= 0) && (box->height >= 0)); */ /* Initialise box's descendant box to border edge box */ - layout_get_box_bbox(box, &box->descendant_x0, &box->descendant_y0, + layout_get_box_bbox(len_ctx, box, + &box->descendant_x0, &box->descendant_y0, &box->descendant_x1, &box->descendant_y1); /* Extend it to contain HTML contents if box is replaced */ @@ -5213,7 +5356,7 @@ static void layout_calculate_descendant_bboxes(struct box *box) child->type == BOX_FLOAT_RIGHT) continue; - layout_update_descendant_bbox(box, child, + layout_update_descendant_bbox(len_ctx, box, child, box->x, box->y); if (child == box->inline_end) @@ -5231,7 +5374,7 @@ static void layout_calculate_descendant_bboxes(struct box *box) child->type == BOX_FLOAT_RIGHT) continue; - layout_calculate_descendant_bboxes(child); + layout_calculate_descendant_bboxes(len_ctx, child); if (box->style && css_computed_overflow_x(box->style) == CSS_OVERFLOW_HIDDEN && @@ -5239,23 +5382,23 @@ static void layout_calculate_descendant_bboxes(struct box *box) CSS_OVERFLOW_HIDDEN) continue; - layout_update_descendant_bbox(box, child, 0, 0); + layout_update_descendant_bbox(len_ctx, box, child, 0, 0); } for (child = box->float_children; child; child = child->next_float) { assert(child->type == BOX_FLOAT_LEFT || child->type == BOX_FLOAT_RIGHT); - layout_calculate_descendant_bboxes(child); + layout_calculate_descendant_bboxes(len_ctx, child); - layout_update_descendant_bbox(box, child, 0, 0); + layout_update_descendant_bbox(len_ctx, box, child, 0, 0); } if (box->list_marker) { child = box->list_marker; - layout_calculate_descendant_bboxes(child); + layout_calculate_descendant_bboxes(len_ctx, child); - layout_update_descendant_bbox(box, child, 0, 0); + layout_update_descendant_bbox(len_ctx, box, child, 0, 0); } } @@ -5267,9 +5410,10 @@ bool layout_document(html_content *content, int width, int height) struct box *doc = content->layout; const struct gui_layout_table *font_func = content->font_func; - layout_minmax_block(doc, font_func); + layout_minmax_block(doc, font_func, content); - layout_block_find_dimensions(width, height, 0, 0, doc); + layout_block_find_dimensions(&content->len_ctx, + width, height, 0, 0, doc); doc->x = doc->margin[LEFT] + doc->border[LEFT].width; doc->y = doc->margin[TOP] + doc->border[TOP].width; width -= doc->margin[LEFT] + doc->border[LEFT].width + @@ -5300,11 +5444,11 @@ bool layout_document(html_content *content, int width, int height) doc->children->margin[BOTTOM]); } - layout_lists(doc, font_func); + layout_lists(doc, font_func, &content->len_ctx); layout_position_absolute(doc, doc, 0, 0, content); - layout_position_relative(doc, doc, 0, 0); + layout_position_relative(&content->len_ctx, doc, doc, 0, 0); - layout_calculate_descendant_bboxes(doc); + layout_calculate_descendant_bboxes(&content->len_ctx, doc); return ret; } diff --git a/render/search.c b/render/search.c index 8f21d8758..ca9520165 100644 --- a/render/search.c +++ b/render/search.c @@ -621,13 +621,14 @@ void search_show_all(bool all, struct search_context *context) if (!a->sel) continue; - selection_init(a->sel, html->layout); + selection_init(a->sel, html->layout, + &html->len_ctx); } else { a->sel = selection_create(context->c, false); if (!a->sel) continue; - selection_init(a->sel, NULL); + selection_init(a->sel, NULL, NULL); } selection_set_start(a->sel, a->start_idx); diff --git a/render/table.c b/render/table.c index c41b9130e..08a2e805c 100644 --- a/render/table.c +++ b/render/table.c @@ -45,31 +45,57 @@ struct border { css_unit unit; /**< border-width units */ }; -static void table_used_left_border_for_cell(struct box *cell); -static void table_used_top_border_for_cell(struct box *cell); -static void table_used_right_border_for_cell(struct box *cell); -static void table_used_bottom_border_for_cell(struct box *cell); -static bool table_border_is_more_eyecatching(const struct border *a, - box_type a_src, const struct border *b, box_type b_src); -static void table_cell_top_process_table(struct box *table, struct border *a, +static void table_used_left_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell); +static void table_used_top_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell); +static void table_used_right_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell); +static void table_used_bottom_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell); +static bool table_border_is_more_eyecatching( + const nscss_len_ctx *len_ctx, + const struct border *a, + box_type a_src, + const struct border *b, + box_type b_src); +static void table_cell_top_process_table( + const nscss_len_ctx *len_ctx, + struct box *table, + struct border *a, + box_type *a_src); +static bool table_cell_top_process_group( + const nscss_len_ctx *len_ctx, + struct box *cell, + struct box *group, + struct border *a, + box_type *a_src); +static bool table_cell_top_process_row( + const nscss_len_ctx *len_ctx, + struct box *cell, + struct box *row, + struct border *a, box_type *a_src); -static bool table_cell_top_process_group(struct box *cell, struct box *group, - struct border *a, box_type *a_src); -static bool table_cell_top_process_row(struct box *cell, struct box *row, - struct border *a, box_type *a_src); /** * Determine the column width types for a table. * - * \param table box of type BOX_TABLE + * \param len_ctx Length conversion context + * \param table box of type BOX_TABLE * \return true on success, false on memory exhaustion * * The table->col array is allocated and type and width are filled in for each * column. */ -bool table_calculate_column_types(struct box *table) +bool table_calculate_column_types( + const nscss_len_ctx *len_ctx, + struct box *table) { unsigned int i, j; struct column *col; @@ -109,7 +135,7 @@ bool table_calculate_column_types(struct box *table) css_computed_position(cell->style) != CSS_POSITION_FIXED) { col[i].positioned = false; - } + } type = css_computed_width(cell->style, &value, &unit); @@ -117,8 +143,8 @@ bool table_calculate_column_types(struct box *table) if (col[i].type != COLUMN_WIDTH_FIXED && type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) { col[i].type = COLUMN_WIDTH_FIXED; - col[i].width = FIXTOINT(nscss_len2px(value, unit, - cell->style)); + col[i].width = FIXTOINT(nscss_len2px(len_ctx, + value, unit, cell->style)); if (col[i].width < 0) col[i].width = 0; continue; @@ -181,7 +207,7 @@ bool table_calculate_column_types(struct box *table) if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT && fixed_columns + unknown_columns == cell->columns) { - int width = (FIXTOFLT(nscss_len2px(value, unit, + int width = (FIXTOFLT(nscss_len2px(len_ctx, value, unit, cell->style)) - fixed_width) / unknown_columns; if (width < 0) @@ -235,11 +261,14 @@ bool table_calculate_column_types(struct box *table) /** * Calculate used values of border-{trbl}-{style,color,width} for table cells. * - * \param cell Table cell to consider + * \param len_ctx Length conversion context + * \param cell Table cell to consider * * \post \a cell's border array is populated */ -void table_used_border_for_cell(struct box *cell) +void table_used_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell) { int side; @@ -257,7 +286,8 @@ void table_used_border_for_cell(struct box *cell) &cell->border[LEFT].c); css_computed_border_left_width(cell->style, &width, &unit); cell->border[LEFT].width = - FIXTOINT(nscss_len2px(width, unit, cell->style)); + FIXTOINT(nscss_len2px(len_ctx, + width, unit, cell->style)); /* Top border */ cell->border[TOP].style = @@ -266,7 +296,8 @@ void table_used_border_for_cell(struct box *cell) &cell->border[TOP].c); css_computed_border_top_width(cell->style, &width, &unit); cell->border[TOP].width = - FIXTOINT(nscss_len2px(width, unit, cell->style)); + FIXTOINT(nscss_len2px(len_ctx, + width, unit, cell->style)); /* Right border */ cell->border[RIGHT].style = @@ -275,7 +306,8 @@ void table_used_border_for_cell(struct box *cell) &cell->border[RIGHT].c); css_computed_border_right_width(cell->style, &width, &unit); cell->border[RIGHT].width = - FIXTOINT(nscss_len2px(width, unit, cell->style)); + FIXTOINT(nscss_len2px(len_ctx, + width, unit, cell->style)); /* Bottom border */ cell->border[BOTTOM].style = @@ -284,19 +316,20 @@ void table_used_border_for_cell(struct box *cell) &cell->border[BOTTOM].c); css_computed_border_bottom_width(cell->style, &width, &unit); cell->border[BOTTOM].width = - FIXTOINT(nscss_len2px(width, unit, cell->style)); + FIXTOINT(nscss_len2px(len_ctx, + width, unit, cell->style)); } else { /* Left border */ - table_used_left_border_for_cell(cell); + table_used_left_border_for_cell(len_ctx, cell); /* Top border */ - table_used_top_border_for_cell(cell); + table_used_top_border_for_cell(len_ctx, cell); /* Right border */ - table_used_right_border_for_cell(cell); + table_used_right_border_for_cell(len_ctx, cell); /* Bottom border */ - table_used_bottom_border_for_cell(cell); + table_used_bottom_border_for_cell(len_ctx, cell); } /* Finally, ensure that any borders configured as @@ -316,9 +349,12 @@ void table_used_border_for_cell(struct box *cell) /** * Calculate used values of border-left-{style,color,width} * - * \param cell Table cell to consider + * \param len_ctx Length conversion context + * \param cell Table cell to consider */ -void table_used_left_border_for_cell(struct box *cell) +void table_used_left_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell) { struct border a, b; box_type a_src, b_src; @@ -329,7 +365,7 @@ void table_used_left_border_for_cell(struct box *cell) a.style = css_computed_border_left_style(cell->style); a.color = css_computed_border_left_color(cell->style, &a.c); css_computed_border_left_width(cell->style, &a.width, &a.unit); - a.width = nscss_len2px(a.width, a.unit, cell->style); + a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style); a.unit = CSS_UNIT_PX; a_src = BOX_TABLE_CELL; @@ -362,11 +398,12 @@ void table_used_left_border_for_cell(struct box *cell) b.style = css_computed_border_right_style(prev->style); b.color = css_computed_border_right_color(prev->style, &b.c); css_computed_border_right_width(prev->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, prev->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, prev->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_CELL; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -384,12 +421,13 @@ void table_used_left_border_for_cell(struct box *cell) row->style, &b.c); css_computed_border_left_width( row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, + b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - - if (table_border_is_more_eyecatching(&a, a_src, - &b, b_src)) { + + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -403,11 +441,12 @@ void table_used_left_border_for_cell(struct box *cell) b.style = css_computed_border_left_style(group->style); b.color = css_computed_border_left_color(group->style, &b.c); css_computed_border_left_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -416,11 +455,12 @@ void table_used_left_border_for_cell(struct box *cell) b.style = css_computed_border_left_style(table->style); b.color = css_computed_border_left_color(table->style, &b.c); css_computed_border_left_width(table->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, table->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -429,16 +469,19 @@ void table_used_left_border_for_cell(struct box *cell) /* a now contains the used left border for the cell */ cell->border[LEFT].style = a.style; cell->border[LEFT].c = a.c; - cell->border[LEFT].width = - FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); + cell->border[LEFT].width = FIXTOINT(nscss_len2px(len_ctx, + a.width, a.unit, cell->style)); } /** * Calculate used values of border-top-{style,color,width} * - * \param cell Table cell to consider + * \param len_ctx Length conversion context + * \param cell Table cell to consider */ -void table_used_top_border_for_cell(struct box *cell) +void table_used_top_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell) { struct border a, b; box_type a_src, b_src; @@ -449,7 +492,7 @@ void table_used_top_border_for_cell(struct box *cell) a.style = css_computed_border_top_style(cell->style); css_computed_border_top_color(cell->style, &a.c); css_computed_border_top_width(cell->style, &a.width, &a.unit); - a.width = nscss_len2px(a.width, a.unit, cell->style); + a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style); a.unit = CSS_UNIT_PX; a_src = BOX_TABLE_CELL; @@ -457,18 +500,18 @@ void table_used_top_border_for_cell(struct box *cell) b.style = css_computed_border_top_style(row->style); css_computed_border_top_color(row->style, &b.c); css_computed_border_top_width(row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, &a, a_src, &b, b_src)) { a = b; a_src = b_src; } if (row->prev != NULL) { /* Consider row(s) above */ - while (table_cell_top_process_row(cell, row->prev, + while (table_cell_top_process_row(len_ctx, cell, row->prev, &a, &a_src) == false) { if (row->prev->prev == NULL) { /* Consider row group */ @@ -489,26 +532,29 @@ void table_used_top_border_for_cell(struct box *cell) b.style = css_computed_border_top_style(group->style); b.color = css_computed_border_top_color(group->style, &b.c); css_computed_border_top_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } if (group->prev == NULL) { /* Top border of table */ - table_cell_top_process_table(group->parent, &a, &a_src); + table_cell_top_process_table(len_ctx, + group->parent, &a, &a_src); } else { /* Process previous group(s) */ - while (table_cell_top_process_group(cell, group->prev, + while (table_cell_top_process_group(len_ctx, + cell, group->prev, &a, &a_src) == false) { if (group->prev->prev == NULL) { /* Top border of table */ - table_cell_top_process_table( - group->parent, + table_cell_top_process_table(len_ctx, + group->parent, &a, &a_src); break; } else { @@ -521,16 +567,19 @@ void table_used_top_border_for_cell(struct box *cell) /* a now contains the used top border for the cell */ cell->border[TOP].style = a.style; cell->border[TOP].c = a.c; - cell->border[TOP].width = - FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); + cell->border[TOP].width = FIXTOINT(nscss_len2px(len_ctx, + a.width, a.unit, cell->style)); } /** * Calculate used values of border-right-{style,color,width} * - * \param cell Table cell to consider + * \param len_ctx Length conversion context + * \param cell Table cell to consider */ -void table_used_right_border_for_cell(struct box *cell) +void table_used_right_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell) { struct border a, b; box_type a_src, b_src; @@ -541,7 +590,7 @@ void table_used_right_border_for_cell(struct box *cell) a.style = css_computed_border_right_style(cell->style); css_computed_border_right_color(cell->style, &a.c); css_computed_border_right_width(cell->style, &a.width, &a.unit); - a.width = nscss_len2px(a.width, a.unit, cell->style); + a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style); a.unit = CSS_UNIT_PX; a_src = BOX_TABLE_CELL; @@ -565,12 +614,13 @@ void table_used_right_border_for_cell(struct box *cell) row->style, &b.c); css_computed_border_right_width( row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, + b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - - if (table_border_is_more_eyecatching(&a, a_src, - &b, b_src)) { + + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -583,13 +633,14 @@ void table_used_right_border_for_cell(struct box *cell) /* Row group -- consider its right border */ b.style = css_computed_border_right_style(group->style); b.color = css_computed_border_right_color(group->style, &b.c); - css_computed_border_right_width(group->style, + css_computed_border_right_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -599,11 +650,12 @@ void table_used_right_border_for_cell(struct box *cell) b.color = css_computed_border_right_color(table->style, &b.c); css_computed_border_right_width(table->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, table->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -612,16 +664,19 @@ void table_used_right_border_for_cell(struct box *cell) /* a now contains the used right border for the cell */ cell->border[RIGHT].style = a.style; cell->border[RIGHT].c = a.c; - cell->border[RIGHT].width = - FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); + cell->border[RIGHT].width = FIXTOINT(nscss_len2px(len_ctx, + a.width, a.unit, cell->style)); } /** * Calculate used values of border-bottom-{style,color,width} * - * \param cell Table cell to consider + * \param len_ctx Length conversion context + * \param cell Table cell to consider */ -void table_used_bottom_border_for_cell(struct box *cell) +void table_used_bottom_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell) { struct border a, b; box_type a_src, b_src; @@ -632,7 +687,7 @@ void table_used_bottom_border_for_cell(struct box *cell) a.style = css_computed_border_bottom_style(cell->style); css_computed_border_bottom_color(cell->style, &a.c); css_computed_border_bottom_width(cell->style, &a.width, &a.unit); - a.width = nscss_len2px(a.width, a.unit, cell->style); + a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style); a.unit = CSS_UNIT_PX; a_src = BOX_TABLE_CELL; @@ -656,11 +711,12 @@ void table_used_bottom_border_for_cell(struct box *cell) b.style = css_computed_border_bottom_style(row->style); b.color = css_computed_border_bottom_color(row->style, &b.c); css_computed_border_bottom_width(row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -670,11 +726,12 @@ void table_used_bottom_border_for_cell(struct box *cell) b.color = css_computed_border_bottom_color(group->style, &b.c); css_computed_border_bottom_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; a_src = b_src; } @@ -684,11 +741,12 @@ void table_used_bottom_border_for_cell(struct box *cell) b.color = css_computed_border_bottom_color(table->style, &b.c); css_computed_border_bottom_width(table->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, table->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE; - if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + &a, a_src, &b, b_src)) { a = b; } } @@ -696,21 +754,26 @@ void table_used_bottom_border_for_cell(struct box *cell) /* a now contains the used bottom border for the cell */ cell->border[BOTTOM].style = a.style; cell->border[BOTTOM].c = a.c; - cell->border[BOTTOM].width = - FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); + cell->border[BOTTOM].width = FIXTOINT(nscss_len2px(len_ctx, + a.width, a.unit, cell->style)); } /** * Determine if a border style is more eyecatching than another * - * \param a Reference border style - * \param a_src Source of \a a - * \param b Candidate border style - * \param b_src Source of \a b + * \param len_ctx Length conversion context + * \param a Reference border style + * \param a_src Source of \a a + * \param b Candidate border style + * \param b_src Source of \a b * \return True if \a b is more eyecatching than \a a */ -bool table_border_is_more_eyecatching(const struct border *a, - box_type a_src, const struct border *b, box_type b_src) +bool table_border_is_more_eyecatching( + const nscss_len_ctx *len_ctx, + const struct border *a, + box_type a_src, + const struct border *b, + box_type b_src) { css_fixed awidth, bwidth; int impact = 0; @@ -731,8 +794,8 @@ bool table_border_is_more_eyecatching(const struct border *a, * if they've come from a computed style. */ assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX); assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX); - awidth = nscss_len2px(a->width, a->unit, NULL); - bwidth = nscss_len2px(b->width, b->unit, NULL); + awidth = nscss_len2px(len_ctx, a->width, a->unit, NULL); + bwidth = nscss_len2px(len_ctx, b->width, b->unit, NULL); if (awidth < bwidth) return true; @@ -811,14 +874,18 @@ bool table_border_is_more_eyecatching(const struct border *a, /** * Process a table * - * \param table Table to process - * \param a Current border style for cell - * \param a_src Source of \a a + * \param len_ctx Length conversion context + * \param table Table to process + * \param a Current border style for cell + * \param a_src Source of \a a * * \post \a a will be updated with most eyecatching style * \post \a a_src will be updated also */ -void table_cell_top_process_table(struct box *table, struct border *a, +void table_cell_top_process_table( + const nscss_len_ctx *len_ctx, + struct box *table, + struct border *a, box_type *a_src) { struct border b; @@ -828,11 +895,11 @@ void table_cell_top_process_table(struct box *table, struct border *a, b.style = css_computed_border_top_style(table->style); b.color = css_computed_border_top_color(table->style, &b.c); css_computed_border_top_width(table->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, table->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE; - if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } @@ -841,17 +908,22 @@ void table_cell_top_process_table(struct box *table, struct border *a, /** * Process a group * - * \param cell Cell being considered - * \param group Group to process - * \param a Current border style for cell - * \param a_src Source of \a a + * \param len_ctx Length conversion context + * \param cell Cell being considered + * \param group Group to process + * \param a Current border style for cell + * \param a_src Source of \a a * \return true if group has non-empty rows, false otherwise * * \post \a a will be updated with most eyecatching style * \post \a a_src will be updated also */ -bool table_cell_top_process_group(struct box *cell, struct box *group, - struct border *a, box_type *a_src) +bool table_cell_top_process_group( + const nscss_len_ctx *len_ctx, + struct box *cell, + struct box *group, + struct border *a, + box_type *a_src) { struct border b; box_type b_src; @@ -860,11 +932,11 @@ bool table_cell_top_process_group(struct box *cell, struct box *group, b.style = css_computed_border_bottom_style(group->style); b.color = css_computed_border_bottom_color(group->style, &b.c); css_computed_border_bottom_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } @@ -873,7 +945,7 @@ bool table_cell_top_process_group(struct box *cell, struct box *group, /* Process rows in group, starting with last */ struct box *row = group->last; - while (table_cell_top_process_row(cell, row, + while (table_cell_top_process_row(len_ctx, cell, row, a, a_src) == false) { if (row->prev == NULL) { return false; @@ -886,11 +958,12 @@ bool table_cell_top_process_group(struct box *cell, struct box *group, b.style = css_computed_border_top_style(group->style); b.color = css_computed_border_top_color(group->style, &b.c); css_computed_border_top_width(group->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, group->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW_GROUP; - if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } @@ -904,17 +977,22 @@ bool table_cell_top_process_group(struct box *cell, struct box *group, /** * Process a row * - * \param cell Cell being considered - * \param row Row to process - * \param a Current border style for cell - * \param a_src Source of \a a + * \param len_ctx Length conversion context + * \param cell Cell being considered + * \param row Row to process + * \param a Current border style for cell + * \param a_src Source of \a a * \return true if row has cells, false otherwise * * \post \a a will be updated with most eyecatching style * \post \a a_src will be updated also */ -bool table_cell_top_process_row(struct box *cell, struct box *row, - struct border *a, box_type *a_src) +bool table_cell_top_process_row( + const nscss_len_ctx *len_ctx, + struct box *cell, + struct box *row, + struct border *a, + box_type *a_src) { struct border b; box_type b_src; @@ -923,11 +1001,11 @@ bool table_cell_top_process_row(struct box *cell, struct box *row, b.style = css_computed_border_bottom_style(row->style); b.color = css_computed_border_bottom_color(row->style, &b.c); css_computed_border_bottom_width(row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } @@ -937,11 +1015,12 @@ bool table_cell_top_process_row(struct box *cell, struct box *row, b.style = css_computed_border_top_style(row->style); b.color = css_computed_border_top_color(row->style, &b.c); css_computed_border_top_width(row->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, row->style); + b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_ROW; - if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } @@ -975,13 +1054,13 @@ bool table_cell_top_process_row(struct box *cell, struct box *row, c->style, &b.c); css_computed_border_bottom_width(c->style, &b.width, &b.unit); - b.width = nscss_len2px(b.width, b.unit, - c->style); + b.width = nscss_len2px(len_ctx, + b.width, b.unit, c->style); b.unit = CSS_UNIT_PX; b_src = BOX_TABLE_CELL; - if (table_border_is_more_eyecatching(a, *a_src, - &b, b_src)) { + if (table_border_is_more_eyecatching(len_ctx, + a, *a_src, &b, b_src)) { *a = b; *a_src = b_src; } diff --git a/render/table.h b/render/table.h index ecd3043b5..2eeffe699 100644 --- a/render/table.h +++ b/render/table.h @@ -28,7 +28,11 @@ struct box; -bool table_calculate_column_types(struct box *table); -void table_used_border_for_cell(struct box *cell); +bool table_calculate_column_types( + const nscss_len_ctx *len_ctx, + struct box *table); +void table_used_border_for_cell( + const nscss_len_ctx *len_ctx, + struct box *cell); #endif diff --git a/render/textplain.c b/render/textplain.c index ab2d55955..0036eb5c0 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -988,7 +988,7 @@ textplain_open(struct content *c, text->bw = bw; /* text selection */ - selection_init(&text->sel, NULL); + selection_init(&text->sel, NULL, NULL); } -- cgit v1.2.3