netsurf: branch tlsa/libcss-units updated. release/3.7-43-g9140d88
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/9140d8815ce53a7d663ef...
...commit http://git.netsurf-browser.org/netsurf.git/commit/9140d8815ce53a7d663efb3...
...tree http://git.netsurf-browser.org/netsurf.git/tree/9140d8815ce53a7d663efb3fe...
The branch, tlsa/libcss-units has been updated
discards 1d6096002395e0db79e7fd86b6bd1e07e6853079 (commit)
via 9140d8815ce53a7d663efb3fea30a6ea5b040299 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (1d6096002395e0db79e7fd86b6bd1e07e6853079)
\
N -- N -- N (9140d8815ce53a7d663efb3fea30a6ea5b040299)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=9140d8815ce53a7d663...
commit 9140d8815ce53a7d663efb3fea30a6ea5b040299
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
CSS utils: Handle new units in length conversion routines.
This causes a ripple effect of all the callsites needing
information they didn't have.
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index 5c7cbd9..8fe157b 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90;
+
+/**
+ * Map viewport-relative length units to either vh or vw.
+ *
+ * Non-viewport-relative units are unchanged.
+ *
+ * \param[in] ctx Length conversion context.
+ * \param[in] unit Unit to map.
+ * \return the mapped unit.
+ */
+static inline css_unit css_utils__fudge_viewport_units(
+ const nscss_len_ctx *ctx,
+ css_unit unit)
+{
+ switch (unit) {
+ case CSS_UNIT_VI:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VW;
+ } else {
+ unit = CSS_UNIT_VH;
+ }
+ break;
+ case CSS_UNIT_VB:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMIN:
+ if (ctx->vh < ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMAX:
+ if (ctx->vh > ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ default: break;
+ }
+
+ return unit;
+}
+
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(css_fixed length, css_unit unit)
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit)
{
/* Length must not be relative */
- assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX);
+ assert(unit != CSS_UNIT_EM &&
+ unit != CSS_UNIT_EX &&
+ unit != CSS_UNIT_CAP &&
+ unit != CSS_UNIT_CH &&
+ unit != CSS_UNIT_IC &&
+ unit != CSS_UNIT_REM &&
+ unit != CSS_UNIT_RLH);
+
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
/* We assume the screen and any other output has the same dpi */
@@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4)));
+ /* 1in = 101.6q => 1mm = (72/101.6)pt */
+ case CSS_UNIT_Q: return FMUL(length,
+ FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length;
/* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
+ case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
+ F_72), nscss_screen_dpi);
+ case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
+ F_72), nscss_screen_dpi);
default: break;
}
return 0;
}
-
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(css_fixed length, css_unit unit,
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
const css_computed_style *style)
{
/* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit;
- assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX));
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
case CSS_UNIT_EM:
case CSS_UNIT_EX:
+ case CSS_UNIT_CAP:
+ case CSS_UNIT_CH:
+ case CSS_UNIT_IC:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
+ assert(style != NULL);
+
css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */
- font_size = nscss_len2pt(font_size, font_unit);
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- /* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
- if (unit == CSS_UNIT_EX)
+ /* Scale non-em units to em. We have fixed ratios. */
+ switch (unit) {
+ case CSS_UNIT_EX:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
+ break;
+ case CSS_UNIT_CAP:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
+ break;
+ case CSS_UNIT_CH:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
+ break;
+ case CSS_UNIT_IC:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
+ break;
+ default: break;
+ }
}
break;
case CSS_UNIT_PX:
@@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break;
+ /* 1in = 101.6q => 1q = (DPI/101.6)px */
+ case CSS_UNIT_Q:
+ px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
+ break;
/* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72);
@@ -113,6 +208,39 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break;
+ case CSS_UNIT_REM:
+ {
+ css_fixed font_size = 0;
+ css_unit font_unit = CSS_UNIT_PT;
+
+ assert(ctx->root_style != NULL);
+
+ css_computed_font_size(ctx->root_style,
+ &font_size, &font_unit);
+
+ /* Convert to points */
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
+
+ /* Clamp to configured minimum */
+ if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
+ font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
+ }
+
+ /* Convert to pixels (manually, to maximise precision)
+ * 1in = 72pt => 1pt = (DPI/72)px */
+ px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
+ break;
+ }
+ /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
+ case CSS_UNIT_RLH:
+ px_per_unit = FDIV(nscss_screen_dpi, FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10)));
+ break;
+ case CSS_UNIT_VH:
+ return TRUNCATEFIX((FDIV((length * ctx->vh), F_100) + F_0_5));
+ case CSS_UNIT_VW:
+ return TRUNCATEFIX((FDIV((length * ctx->vw), F_100) + F_0_5));
default:
px_per_unit = 0;
break;
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index 21cb497..c8f4c82 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -27,24 +27,54 @@
extern css_fixed nscss_screen_dpi;
/**
+ * Length conversion context data.
+ */
+typedef struct nscss_len_ctx {
+ /**
+ * Viewport width in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vw;
+ /**
+ * Viewport height in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vh;
+ /**
+ * Computed style for the document root element.
+ * May be NULL if unit is not rem, or rlh.
+ */
+ const css_computed_style *root_style;
+} nscss_len_ctx;
+
+/**
* Convert an absolute CSS length to points.
*
- * \param[in] length Absolute CSS length.
- * \param[in] unit Unit of the length.
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Absolute CSS length.
+ * \param[in] unit Unit of the length.
* \return length in points
*/
-css_fixed nscss_len2pt(css_fixed length, css_unit unit);
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit);
/**
* Convert a CSS length to pixels.
*
- * \param length Length to convert
- * \param unit Corresponding unit
- * \param style Computed style applying to length. May be NULL if unit is
- * neither em nor ex
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Length to convert.
+ * \param[in] unit Corresponding unit.
+ * \param[in] style Computed style applying to length.
+ * May be NULL if unit is not em, ex, cap, ch, or ic.
* \return length in pixels
*/
-css_fixed nscss_len2px(css_fixed length, css_unit unit, const css_computed_style *style);
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
+ const css_computed_style *style);
/**
diff --git a/desktop/print.c b/desktop/print.c
index 54cc545..5c0333a 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
+ nscss_len_ctx len_ctx = {
+ .vw = DEFAULT_PAGE_WIDTH,
+ .vh = DEFAULT_PAGE_HEIGHT,
+ .root_style = NULL,
+ };
switch (configuration){
case PRINT_DEFAULT:
@@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
default:
return NULL;
diff --git a/desktop/selection.c b/desktop/selection.c
index 7506af0..5cb43b8 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -70,18 +70,20 @@ struct selection_string {
typedef bool (*seln_traverse_handler)(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
- size_t whitespace_length);
+ struct box *box, const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length);
-static bool redraw_handler(const char *text, size_t length, struct box *box,
+static bool redraw_handler(const char *text, size_t length,
+ struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text,
size_t whitespace_length);
static void selection_redraw(struct selection *s, unsigned start_idx,
unsigned end_idx);
static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
unsigned *start_offset, unsigned *end_offset);
-static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker);
@@ -198,7 +200,10 @@ void selection_reinit(struct selection *s, struct box *root)
* \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root)
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx)
{
if (s->defined)
selection_clear(s, true);
@@ -207,6 +212,13 @@ void selection_init(struct selection *s, struct box *root)
s->start_idx = 0;
s->end_idx = 0;
s->drag_state = DRAG_NONE;
+ if (len_ctx != NULL) {
+ s->len_ctx = *len_ctx;
+ } else {
+ s->len_ctx.vw = 0;
+ s->len_ctx.vh = 0;
+ s->len_ctx.root_style = NULL;
+ }
selection_reinit(s, root);
}
@@ -442,6 +454,7 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* for all boxes that lie (partially) within the given range
*
* \param box box subtree
+ * \param len_ctx Length conversion context.
* \param start_idx start of range within textual representation (bytes)
* \param end_idx end of range
* \param handler handler function to call
@@ -452,7 +465,9 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* \return false iff traversal abandoned part-way through
*/
-bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+bool traverse_tree(
+ struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker)
@@ -473,9 +488,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
if (box->list_marker) {
/* do the marker box before continuing with the rest of the
* list element */
- if (!traverse_tree(box->list_marker, start_idx, end_idx,
- handler, handle, before, first,
- true))
+ if (!traverse_tree(box->list_marker, len_ctx,
+ start_idx, end_idx, handler, handle,
+ before, first, true))
return false;
}
@@ -506,7 +521,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
&end_offset)) {
if (!handler(box->text + start_offset, min(box->length,
end_offset) - start_offset,
- box, handle, whitespace_text,
+ box, len_ctx, handle, whitespace_text,
whitespace_length))
return false;
if (before) {
@@ -533,7 +548,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
* the tree */
struct box *next = child->next;
- if (!traverse_tree(child, start_idx, end_idx,
+ if (!traverse_tree(child, len_ctx, start_idx, end_idx,
handler, handle, before, first, false))
return false;
@@ -568,14 +583,16 @@ static bool selection_traverse(struct selection *s,
if (s->root) {
/* HTML */
- return traverse_tree(s->root, s->start_idx, s->end_idx,
- handler, handle, &before, &first, false);
+ return traverse_tree(s->root, &s->len_ctx,
+ s->start_idx, s->end_idx,
+ handler, handle,
+ &before, &first, false);
}
/* Text */
text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
- if (text && !handler(text, length, NULL, handle, NULL, 0))
+ if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
return false;
return true;
@@ -597,8 +614,8 @@ static bool selection_traverse(struct selection *s,
*/
bool redraw_handler(const char *text, size_t length, struct box *box,
- void *handle, const char *whitespace_text,
- size_t whitespace_length)
+ const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length)
{
if (box) {
struct rdw_info *r = (struct rdw_info*)handle;
@@ -606,7 +623,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box,
int x, y;
plot_font_style_t fstyle;
- font_plot_style_from_css(box->style, &fstyle);
+ font_plot_style_from_css(len_ctx, box->style, &fstyle);
/* \todo - it should be possible to reduce the redrawn area by
* considering the 'text', 'length' and 'space' parameters */
@@ -652,7 +669,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
rdw.inited = false;
if (s->root) {
- if (!traverse_tree(s->root, start_idx, end_idx,
+ if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
redraw_handler, &rdw,
NULL, NULL, false))
return;
@@ -739,10 +756,11 @@ static bool selection_string_append(const char *text, size_t length, bool space,
/**
* Selection traversal routine for appending text to a string
*
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param handle selection string to append to
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
* \param whitespace_text whitespace to place before text for formatting
* may be NULL
* \param whitespace_length length of whitespace_text
@@ -750,7 +768,8 @@ static bool selection_string_append(const char *text, size_t length, bool space,
*/
static bool selection_copy_handler(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
+ struct box *box, const nscss_len_ctx *len_ctx,
+ void *handle, const char *whitespace_text,
size_t whitespace_length)
{
bool add_space = false;
@@ -771,7 +790,7 @@ static bool selection_copy_handler(const char *text, size_t length,
if (box->style != NULL) {
/* Override default font style */
- font_plot_style_from_css(box->style, &style);
+ font_plot_style_from_css(len_ctx, box->style, &style);
pstyle = &style;
} else {
/* If there's no style, there must be no text */
diff --git a/desktop/selection.h b/desktop/selection.h
index e2bc3b3..2f3f6dc 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include "netsurf/mouse.h"
+#include "content/handlers/css/utils.h"
struct box;
@@ -43,6 +44,7 @@ struct selection
{
struct content *c;
struct box *root;
+ nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
@@ -60,7 +62,10 @@ struct selection *selection_create(struct content *c, bool is_html);
void selection_prepare(struct selection *s, struct content *c, bool is_html);
void selection_destroy(struct selection *s);
-void selection_init(struct selection *s, struct box *root);
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx);
void selection_reinit(struct selection *s, struct box *root);
/* struct box *selection_root(struct selection *s); */
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 149ca26..3fd4c98 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1803,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
{
int text_y_offset, text_y_offset_baseline;
+ ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
+ nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
+ INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+
text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */
@@ -1822,6 +1826,27 @@ static void textarea_setup_text_offsets(struct textarea *ta)
}
+/**
+ * Set font styles up for a textarea.
+ *
+ * \param[in] ta Textarea to update.
+ * \param[in] fstyle Font style to set in textarea.
+ * \param[in] selected_text Textarea selected text colour.
+ * \param[in] selected_bg Textarea selection background colour.
+ */
+static void textarea_set_text_style(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ colour selected_text,
+ colour selected_bg)
+{
+ ta->fstyle = *fstyle;
+
+ ta->sel_fstyle = *fstyle;
+ ta->sel_fstyle.foreground = selected_text;
+ ta->sel_fstyle.background = selected_bg;
+}
+
/* exported interface, documented in textarea.h */
struct textarea *textarea_create(const textarea_flags flags,
@@ -1861,11 +1886,10 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->border_width = setup->border_width;
ret->border_col = setup->border_col;
- ret->fstyle = setup->text;
-
- ret->sel_fstyle = setup->text;
- ret->sel_fstyle.foreground = setup->selected_text;
- ret->sel_fstyle.background = setup->selected_bg;
+ textarea_set_text_style(ret,
+ &setup->text,
+ setup->selected_text,
+ setup->selected_bg);
ret->scroll_x = 0;
ret->scroll_y = 0;
@@ -3220,8 +3244,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
/* exported interface, documented in textarea.h */
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left)
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left)
{
struct rect r = {0, 0, 0, 0};
@@ -3232,6 +3260,10 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
ta->pad_left = left;
+ textarea_set_text_style(ta, fstyle,
+ ta->sel_fstyle.foreground,
+ ta->sel_fstyle.background);
+
textarea_setup_text_offsets(ta);
if (ta->flags & TEXTAREA_MULTILINE) {
diff --git a/desktop/textarea.h b/desktop/textarea.h
index b386e50..82e0de9 100644
--- a/desktop/textarea.h
+++ b/desktop/textarea.h
@@ -329,8 +329,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height);
* \param bottom the new bottom padding of the textarea
* \param left the new left padding of the textarea
*/
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left);
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left);
/**
diff --git a/render/box.c b/render/box.c
index 8b9c89e..c97e898 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 8208a6f..1af0a8b 100644
--- a/render/box.h
+++ b/render/box.h
@@ -91,6 +91,8 @@
#include <stdio.h>
#include <libcss/libcss.h>
+#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 9c0875b..8da2457 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 3b1e775..a609842 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 94ef877..a769b47 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 fba368a..52f5a62 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 904272d..4320025 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 3cfc5e2..b7d7aa3 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 30adaa0..2d14ed2 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 2f84cf8..66ecb2b 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -26,6 +26,7 @@
#include <libcss/libcss.h>
+#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 e98bdba..fb9e7b0 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 2f87306..9a97e5e 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 83dbc53..15eb1e8 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 8f21d87..ca95201 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 c41b913..08a2e80 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 ecd3043..2eeffe6 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 ab2d559..0036eb5 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);
}
-----------------------------------------------------------------------
Summary of changes:
content/handlers/css/utils.c | 6 ++----
desktop/selection.c | 12 +++++++++++-
desktop/selection.h | 5 ++++-
render/html.c | 2 +-
render/search.c | 5 +++--
render/textplain.c | 2 +-
6 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index c0d9628..8fe157b 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -238,11 +238,9 @@ css_fixed nscss_len2px(
INTTOFIX(10)));
break;
case CSS_UNIT_VH:
- px_per_unit = FDIV((length * ctx->vh), F_100);
- break;
+ return TRUNCATEFIX((FDIV((length * ctx->vh), F_100) + F_0_5));
case CSS_UNIT_VW:
- px_per_unit = FDIV((length * ctx->vw), F_100);
- break;
+ return TRUNCATEFIX((FDIV((length * ctx->vw), F_100) + F_0_5));
default:
px_per_unit = 0;
break;
diff --git a/desktop/selection.c b/desktop/selection.c
index 9dc0b5c..5cb43b8 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -200,7 +200,10 @@ void selection_reinit(struct selection *s, struct box *root)
* \param root the root box for html document or NULL for text/plain
*/
-void selection_init(struct selection *s, struct box *root)
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx)
{
if (s->defined)
selection_clear(s, true);
@@ -209,6 +212,13 @@ void selection_init(struct selection *s, struct box *root)
s->start_idx = 0;
s->end_idx = 0;
s->drag_state = DRAG_NONE;
+ if (len_ctx != NULL) {
+ s->len_ctx = *len_ctx;
+ } else {
+ s->len_ctx.vw = 0;
+ s->len_ctx.vh = 0;
+ s->len_ctx.root_style = NULL;
+ }
selection_reinit(s, root);
}
diff --git a/desktop/selection.h b/desktop/selection.h
index 358879f..2f3f6dc 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -62,7 +62,10 @@ struct selection *selection_create(struct content *c, bool is_html);
void selection_prepare(struct selection *s, struct content *c, bool is_html);
void selection_destroy(struct selection *s);
-void selection_init(struct selection *s, struct box *root);
+void selection_init(
+ struct selection *s,
+ struct box *root,
+ const nscss_len_ctx *len_ctx);
void selection_reinit(struct selection *s, struct box *root);
/* struct box *selection_root(struct selection *s); */
diff --git a/render/html.c b/render/html.c
index 7c2c985..b7d7aa3 100644
--- a/render/html.c
+++ b/render/html.c
@@ -1651,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;
diff --git a/render/search.c b/render/search.c
index 8f21d87..ca95201 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/textplain.c b/render/textplain.c
index ab2d559..0036eb5 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);
}
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units updated. release/3.7-43-g1d60960
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/1d6096002395e0db79e7f...
...commit http://git.netsurf-browser.org/netsurf.git/commit/1d6096002395e0db79e7fd8...
...tree http://git.netsurf-browser.org/netsurf.git/tree/1d6096002395e0db79e7fd86b...
The branch, tlsa/libcss-units has been updated
discards 02ca4d934d995ffee412ace37dc7db11afb01206 (commit)
discards fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14 (commit)
via 1d6096002395e0db79e7fd86b6bd1e07e6853079 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (02ca4d934d995ffee412ace37dc7db11afb01206)
\
N -- N -- N (1d6096002395e0db79e7fd86b6bd1e07e6853079)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=1d6096002395e0db79e...
commit 1d6096002395e0db79e7fd86b6bd1e07e6853079
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
WIP: make nscss_len2p{t|x} handle new libcss units.
This causes a ripple effect of all the callsites needing
information they didn't have. It builds cleanly and seems
to work fine for a quick browse.
TODO:
I expect viewport-based units will make text selection
unhappy, since I haven't initialised the selection
context's length conversion context anywhere yet.
Also, I've not actually tested any pages using the new
units yet.
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index 5c7cbd9..c0d9628 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90;
+
+/**
+ * Map viewport-relative length units to either vh or vw.
+ *
+ * Non-viewport-relative units are unchanged.
+ *
+ * \param[in] ctx Length conversion context.
+ * \param[in] unit Unit to map.
+ * \return the mapped unit.
+ */
+static inline css_unit css_utils__fudge_viewport_units(
+ const nscss_len_ctx *ctx,
+ css_unit unit)
+{
+ switch (unit) {
+ case CSS_UNIT_VI:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VW;
+ } else {
+ unit = CSS_UNIT_VH;
+ }
+ break;
+ case CSS_UNIT_VB:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMIN:
+ if (ctx->vh < ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMAX:
+ if (ctx->vh > ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ default: break;
+ }
+
+ return unit;
+}
+
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(css_fixed length, css_unit unit)
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit)
{
/* Length must not be relative */
- assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX);
+ assert(unit != CSS_UNIT_EM &&
+ unit != CSS_UNIT_EX &&
+ unit != CSS_UNIT_CAP &&
+ unit != CSS_UNIT_CH &&
+ unit != CSS_UNIT_IC &&
+ unit != CSS_UNIT_REM &&
+ unit != CSS_UNIT_RLH);
+
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
/* We assume the screen and any other output has the same dpi */
@@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4)));
+ /* 1in = 101.6q => 1mm = (72/101.6)pt */
+ case CSS_UNIT_Q: return FMUL(length,
+ FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length;
/* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
+ case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
+ F_72), nscss_screen_dpi);
+ case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
+ F_72), nscss_screen_dpi);
default: break;
}
return 0;
}
-
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(css_fixed length, css_unit unit,
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
const css_computed_style *style)
{
/* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit;
- assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX));
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
case CSS_UNIT_EM:
case CSS_UNIT_EX:
+ case CSS_UNIT_CAP:
+ case CSS_UNIT_CH:
+ case CSS_UNIT_IC:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
+ assert(style != NULL);
+
css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */
- font_size = nscss_len2pt(font_size, font_unit);
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- /* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
- if (unit == CSS_UNIT_EX)
+ /* Scale non-em units to em. We have fixed ratios. */
+ switch (unit) {
+ case CSS_UNIT_EX:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
+ break;
+ case CSS_UNIT_CAP:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
+ break;
+ case CSS_UNIT_CH:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
+ break;
+ case CSS_UNIT_IC:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
+ break;
+ default: break;
+ }
}
break;
case CSS_UNIT_PX:
@@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break;
+ /* 1in = 101.6q => 1q = (DPI/101.6)px */
+ case CSS_UNIT_Q:
+ px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
+ break;
/* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72);
@@ -113,6 +208,41 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break;
+ case CSS_UNIT_REM:
+ {
+ css_fixed font_size = 0;
+ css_unit font_unit = CSS_UNIT_PT;
+
+ assert(ctx->root_style != NULL);
+
+ css_computed_font_size(ctx->root_style,
+ &font_size, &font_unit);
+
+ /* Convert to points */
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
+
+ /* Clamp to configured minimum */
+ if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
+ font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
+ }
+
+ /* Convert to pixels (manually, to maximise precision)
+ * 1in = 72pt => 1pt = (DPI/72)px */
+ px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
+ break;
+ }
+ /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
+ case CSS_UNIT_RLH:
+ px_per_unit = FDIV(nscss_screen_dpi, FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10)));
+ break;
+ case CSS_UNIT_VH:
+ px_per_unit = FDIV((length * ctx->vh), F_100);
+ break;
+ case CSS_UNIT_VW:
+ px_per_unit = FDIV((length * ctx->vw), F_100);
+ break;
default:
px_per_unit = 0;
break;
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index 21cb497..c8f4c82 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -27,24 +27,54 @@
extern css_fixed nscss_screen_dpi;
/**
+ * Length conversion context data.
+ */
+typedef struct nscss_len_ctx {
+ /**
+ * Viewport width in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vw;
+ /**
+ * Viewport height in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vh;
+ /**
+ * Computed style for the document root element.
+ * May be NULL if unit is not rem, or rlh.
+ */
+ const css_computed_style *root_style;
+} nscss_len_ctx;
+
+/**
* Convert an absolute CSS length to points.
*
- * \param[in] length Absolute CSS length.
- * \param[in] unit Unit of the length.
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Absolute CSS length.
+ * \param[in] unit Unit of the length.
* \return length in points
*/
-css_fixed nscss_len2pt(css_fixed length, css_unit unit);
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit);
/**
* Convert a CSS length to pixels.
*
- * \param length Length to convert
- * \param unit Corresponding unit
- * \param style Computed style applying to length. May be NULL if unit is
- * neither em nor ex
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Length to convert.
+ * \param[in] unit Corresponding unit.
+ * \param[in] style Computed style applying to length.
+ * May be NULL if unit is not em, ex, cap, ch, or ic.
* \return length in pixels
*/
-css_fixed nscss_len2px(css_fixed length, css_unit unit, const css_computed_style *style);
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
+ const css_computed_style *style);
/**
diff --git a/desktop/print.c b/desktop/print.c
index 54cc545..5c0333a 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
+ nscss_len_ctx len_ctx = {
+ .vw = DEFAULT_PAGE_WIDTH,
+ .vh = DEFAULT_PAGE_HEIGHT,
+ .root_style = NULL,
+ };
switch (configuration){
case PRINT_DEFAULT:
@@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
default:
return NULL;
diff --git a/desktop/selection.c b/desktop/selection.c
index 7506af0..9dc0b5c 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -70,18 +70,20 @@ struct selection_string {
typedef bool (*seln_traverse_handler)(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
- size_t whitespace_length);
+ struct box *box, const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length);
-static bool redraw_handler(const char *text, size_t length, struct box *box,
+static bool redraw_handler(const char *text, size_t length,
+ struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text,
size_t whitespace_length);
static void selection_redraw(struct selection *s, unsigned start_idx,
unsigned end_idx);
static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
unsigned *start_offset, unsigned *end_offset);
-static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker);
@@ -442,6 +444,7 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* for all boxes that lie (partially) within the given range
*
* \param box box subtree
+ * \param len_ctx Length conversion context.
* \param start_idx start of range within textual representation (bytes)
* \param end_idx end of range
* \param handler handler function to call
@@ -452,7 +455,9 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* \return false iff traversal abandoned part-way through
*/
-bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+bool traverse_tree(
+ struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker)
@@ -473,9 +478,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
if (box->list_marker) {
/* do the marker box before continuing with the rest of the
* list element */
- if (!traverse_tree(box->list_marker, start_idx, end_idx,
- handler, handle, before, first,
- true))
+ if (!traverse_tree(box->list_marker, len_ctx,
+ start_idx, end_idx, handler, handle,
+ before, first, true))
return false;
}
@@ -506,7 +511,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
&end_offset)) {
if (!handler(box->text + start_offset, min(box->length,
end_offset) - start_offset,
- box, handle, whitespace_text,
+ box, len_ctx, handle, whitespace_text,
whitespace_length))
return false;
if (before) {
@@ -533,7 +538,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
* the tree */
struct box *next = child->next;
- if (!traverse_tree(child, start_idx, end_idx,
+ if (!traverse_tree(child, len_ctx, start_idx, end_idx,
handler, handle, before, first, false))
return false;
@@ -568,14 +573,16 @@ static bool selection_traverse(struct selection *s,
if (s->root) {
/* HTML */
- return traverse_tree(s->root, s->start_idx, s->end_idx,
- handler, handle, &before, &first, false);
+ return traverse_tree(s->root, &s->len_ctx,
+ s->start_idx, s->end_idx,
+ handler, handle,
+ &before, &first, false);
}
/* Text */
text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
- if (text && !handler(text, length, NULL, handle, NULL, 0))
+ if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
return false;
return true;
@@ -597,8 +604,8 @@ static bool selection_traverse(struct selection *s,
*/
bool redraw_handler(const char *text, size_t length, struct box *box,
- void *handle, const char *whitespace_text,
- size_t whitespace_length)
+ const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length)
{
if (box) {
struct rdw_info *r = (struct rdw_info*)handle;
@@ -606,7 +613,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box,
int x, y;
plot_font_style_t fstyle;
- font_plot_style_from_css(box->style, &fstyle);
+ font_plot_style_from_css(len_ctx, box->style, &fstyle);
/* \todo - it should be possible to reduce the redrawn area by
* considering the 'text', 'length' and 'space' parameters */
@@ -652,7 +659,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
rdw.inited = false;
if (s->root) {
- if (!traverse_tree(s->root, start_idx, end_idx,
+ if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
redraw_handler, &rdw,
NULL, NULL, false))
return;
@@ -739,10 +746,11 @@ static bool selection_string_append(const char *text, size_t length, bool space,
/**
* Selection traversal routine for appending text to a string
*
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param handle selection string to append to
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
* \param whitespace_text whitespace to place before text for formatting
* may be NULL
* \param whitespace_length length of whitespace_text
@@ -750,7 +758,8 @@ static bool selection_string_append(const char *text, size_t length, bool space,
*/
static bool selection_copy_handler(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
+ struct box *box, const nscss_len_ctx *len_ctx,
+ void *handle, const char *whitespace_text,
size_t whitespace_length)
{
bool add_space = false;
@@ -771,7 +780,7 @@ static bool selection_copy_handler(const char *text, size_t length,
if (box->style != NULL) {
/* Override default font style */
- font_plot_style_from_css(box->style, &style);
+ font_plot_style_from_css(len_ctx, box->style, &style);
pstyle = &style;
} else {
/* If there's no style, there must be no text */
diff --git a/desktop/selection.h b/desktop/selection.h
index e2bc3b3..358879f 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include "netsurf/mouse.h"
+#include "content/handlers/css/utils.h"
struct box;
@@ -43,6 +44,7 @@ struct selection
{
struct content *c;
struct box *root;
+ nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 149ca26..3fd4c98 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1803,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
{
int text_y_offset, text_y_offset_baseline;
+ ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
+ nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
+ INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+
text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */
@@ -1822,6 +1826,27 @@ static void textarea_setup_text_offsets(struct textarea *ta)
}
+/**
+ * Set font styles up for a textarea.
+ *
+ * \param[in] ta Textarea to update.
+ * \param[in] fstyle Font style to set in textarea.
+ * \param[in] selected_text Textarea selected text colour.
+ * \param[in] selected_bg Textarea selection background colour.
+ */
+static void textarea_set_text_style(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ colour selected_text,
+ colour selected_bg)
+{
+ ta->fstyle = *fstyle;
+
+ ta->sel_fstyle = *fstyle;
+ ta->sel_fstyle.foreground = selected_text;
+ ta->sel_fstyle.background = selected_bg;
+}
+
/* exported interface, documented in textarea.h */
struct textarea *textarea_create(const textarea_flags flags,
@@ -1861,11 +1886,10 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->border_width = setup->border_width;
ret->border_col = setup->border_col;
- ret->fstyle = setup->text;
-
- ret->sel_fstyle = setup->text;
- ret->sel_fstyle.foreground = setup->selected_text;
- ret->sel_fstyle.background = setup->selected_bg;
+ textarea_set_text_style(ret,
+ &setup->text,
+ setup->selected_text,
+ setup->selected_bg);
ret->scroll_x = 0;
ret->scroll_y = 0;
@@ -3220,8 +3244,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
/* exported interface, documented in textarea.h */
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left)
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left)
{
struct rect r = {0, 0, 0, 0};
@@ -3232,6 +3260,10 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
ta->pad_left = left;
+ textarea_set_text_style(ta, fstyle,
+ ta->sel_fstyle.foreground,
+ ta->sel_fstyle.background);
+
textarea_setup_text_offsets(ta);
if (ta->flags & TEXTAREA_MULTILINE) {
diff --git a/desktop/textarea.h b/desktop/textarea.h
index b386e50..82e0de9 100644
--- a/desktop/textarea.h
+++ b/desktop/textarea.h
@@ -329,8 +329,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height);
* \param bottom the new bottom padding of the textarea
* \param left the new left padding of the textarea
*/
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left);
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left);
/**
diff --git a/render/box.c b/render/box.c
index 8b9c89e..c97e898 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 8208a6f..1af0a8b 100644
--- a/render/box.h
+++ b/render/box.h
@@ -91,6 +91,8 @@
#include <stdio.h>
#include <libcss/libcss.h>
+#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 9c0875b..8da2457 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 3b1e775..a609842 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 94ef877..a769b47 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 fba368a..52f5a62 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 904272d..4320025 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 3cfc5e2..7c2c985 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;
@@ -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 30adaa0..2d14ed2 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 2f84cf8..66ecb2b 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -26,6 +26,7 @@
#include <libcss/libcss.h>
+#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 e98bdba..fb9e7b0 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 2f87306..9a97e5e 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 83dbc53..15eb1e8 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/table.c b/render/table.c
index c41b913..08a2e80 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 ecd3043..2eeffe6 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
-----------------------------------------------------------------------
Summary of changes:
desktop/selection.c | 55 ++++++++++++++++++++++++++++--------------------
desktop/selection.h | 2 ++
desktop/textarea.c | 46 ++++++++++++++++++++++++++++++++++------
desktop/textarea.h | 8 +++++--
render/box_normalise.c | 3 ---
render/box_textarea.c | 11 +++++++---
render/html.c | 2 +-
render/layout.c | 15 +++++++++++--
8 files changed, 101 insertions(+), 41 deletions(-)
diff --git a/desktop/selection.c b/desktop/selection.c
index 7506af0..9dc0b5c 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -70,18 +70,20 @@ struct selection_string {
typedef bool (*seln_traverse_handler)(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
- size_t whitespace_length);
+ struct box *box, const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length);
-static bool redraw_handler(const char *text, size_t length, struct box *box,
+static bool redraw_handler(const char *text, size_t length,
+ struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text,
size_t whitespace_length);
static void selection_redraw(struct selection *s, unsigned start_idx,
unsigned end_idx);
static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
unsigned *start_offset, unsigned *end_offset);
-static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker);
@@ -442,6 +444,7 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* for all boxes that lie (partially) within the given range
*
* \param box box subtree
+ * \param len_ctx Length conversion context.
* \param start_idx start of range within textual representation (bytes)
* \param end_idx end of range
* \param handler handler function to call
@@ -452,7 +455,9 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* \return false iff traversal abandoned part-way through
*/
-bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
+bool traverse_tree(
+ struct box *box, const nscss_len_ctx *len_ctx,
+ unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first,
bool do_marker)
@@ -473,9 +478,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
if (box->list_marker) {
/* do the marker box before continuing with the rest of the
* list element */
- if (!traverse_tree(box->list_marker, start_idx, end_idx,
- handler, handle, before, first,
- true))
+ if (!traverse_tree(box->list_marker, len_ctx,
+ start_idx, end_idx, handler, handle,
+ before, first, true))
return false;
}
@@ -506,7 +511,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
&end_offset)) {
if (!handler(box->text + start_offset, min(box->length,
end_offset) - start_offset,
- box, handle, whitespace_text,
+ box, len_ctx, handle, whitespace_text,
whitespace_length))
return false;
if (before) {
@@ -533,7 +538,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
* the tree */
struct box *next = child->next;
- if (!traverse_tree(child, start_idx, end_idx,
+ if (!traverse_tree(child, len_ctx, start_idx, end_idx,
handler, handle, before, first, false))
return false;
@@ -568,14 +573,16 @@ static bool selection_traverse(struct selection *s,
if (s->root) {
/* HTML */
- return traverse_tree(s->root, s->start_idx, s->end_idx,
- handler, handle, &before, &first, false);
+ return traverse_tree(s->root, &s->len_ctx,
+ s->start_idx, s->end_idx,
+ handler, handle,
+ &before, &first, false);
}
/* Text */
text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
- if (text && !handler(text, length, NULL, handle, NULL, 0))
+ if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
return false;
return true;
@@ -597,8 +604,8 @@ static bool selection_traverse(struct selection *s,
*/
bool redraw_handler(const char *text, size_t length, struct box *box,
- void *handle, const char *whitespace_text,
- size_t whitespace_length)
+ const nscss_len_ctx *len_ctx, void *handle,
+ const char *whitespace_text, size_t whitespace_length)
{
if (box) {
struct rdw_info *r = (struct rdw_info*)handle;
@@ -606,7 +613,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box,
int x, y;
plot_font_style_t fstyle;
- font_plot_style_from_css(box->style, &fstyle);
+ font_plot_style_from_css(len_ctx, box->style, &fstyle);
/* \todo - it should be possible to reduce the redrawn area by
* considering the 'text', 'length' and 'space' parameters */
@@ -652,7 +659,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
rdw.inited = false;
if (s->root) {
- if (!traverse_tree(s->root, start_idx, end_idx,
+ if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
redraw_handler, &rdw,
NULL, NULL, false))
return;
@@ -739,10 +746,11 @@ static bool selection_string_append(const char *text, size_t length, bool space,
/**
* Selection traversal routine for appending text to a string
*
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param handle selection string to append to
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param len_ctx Length conversion context
+ * \param handle selection string to append to
* \param whitespace_text whitespace to place before text for formatting
* may be NULL
* \param whitespace_length length of whitespace_text
@@ -750,7 +758,8 @@ static bool selection_string_append(const char *text, size_t length, bool space,
*/
static bool selection_copy_handler(const char *text, size_t length,
- struct box *box, void *handle, const char *whitespace_text,
+ struct box *box, const nscss_len_ctx *len_ctx,
+ void *handle, const char *whitespace_text,
size_t whitespace_length)
{
bool add_space = false;
@@ -771,7 +780,7 @@ static bool selection_copy_handler(const char *text, size_t length,
if (box->style != NULL) {
/* Override default font style */
- font_plot_style_from_css(box->style, &style);
+ font_plot_style_from_css(len_ctx, box->style, &style);
pstyle = &style;
} else {
/* If there's no style, there must be no text */
diff --git a/desktop/selection.h b/desktop/selection.h
index e2bc3b3..358879f 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include "netsurf/mouse.h"
+#include "content/handlers/css/utils.h"
struct box;
@@ -43,6 +44,7 @@ struct selection
{
struct content *c;
struct box *root;
+ nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 149ca26..3fd4c98 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1803,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
{
int text_y_offset, text_y_offset_baseline;
+ ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
+ nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
+ INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+
text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */
@@ -1822,6 +1826,27 @@ static void textarea_setup_text_offsets(struct textarea *ta)
}
+/**
+ * Set font styles up for a textarea.
+ *
+ * \param[in] ta Textarea to update.
+ * \param[in] fstyle Font style to set in textarea.
+ * \param[in] selected_text Textarea selected text colour.
+ * \param[in] selected_bg Textarea selection background colour.
+ */
+static void textarea_set_text_style(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ colour selected_text,
+ colour selected_bg)
+{
+ ta->fstyle = *fstyle;
+
+ ta->sel_fstyle = *fstyle;
+ ta->sel_fstyle.foreground = selected_text;
+ ta->sel_fstyle.background = selected_bg;
+}
+
/* exported interface, documented in textarea.h */
struct textarea *textarea_create(const textarea_flags flags,
@@ -1861,11 +1886,10 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->border_width = setup->border_width;
ret->border_col = setup->border_col;
- ret->fstyle = setup->text;
-
- ret->sel_fstyle = setup->text;
- ret->sel_fstyle.foreground = setup->selected_text;
- ret->sel_fstyle.background = setup->selected_bg;
+ textarea_set_text_style(ret,
+ &setup->text,
+ setup->selected_text,
+ setup->selected_bg);
ret->scroll_x = 0;
ret->scroll_y = 0;
@@ -3220,8 +3244,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
/* exported interface, documented in textarea.h */
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left)
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left)
{
struct rect r = {0, 0, 0, 0};
@@ -3232,6 +3260,10 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
ta->pad_left = left;
+ textarea_set_text_style(ta, fstyle,
+ ta->sel_fstyle.foreground,
+ ta->sel_fstyle.background);
+
textarea_setup_text_offsets(ta);
if (ta->flags & TEXTAREA_MULTILINE) {
diff --git a/desktop/textarea.h b/desktop/textarea.h
index b386e50..82e0de9 100644
--- a/desktop/textarea.h
+++ b/desktop/textarea.h
@@ -329,8 +329,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height);
* \param bottom the new bottom padding of the textarea
* \param left the new left padding of the textarea
*/
-void textarea_set_layout(struct textarea *ta, int width, int height,
- int top, int right, int bottom, int left);
+void textarea_set_layout(
+ struct textarea *ta,
+ const plot_font_style_t *fstyle,
+ int width, int height,
+ int top, int right,
+ int bottom, int left);
/**
diff --git a/render/box_normalise.c b/render/box_normalise.c
index 9c0875b..8da2457 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 3b1e775..a609842 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/html.c b/render/html.c
index 3160e3a..7c2c985 100644
--- a/render/html.c
+++ b/render/html.c
@@ -1399,7 +1399,7 @@ static void html_reformat(struct content *c, int width, int height)
htmlc->reflowing = true;
htmlc->len_ctx.vw = width;
- htmlc->len_ctx.vh = width;
+ htmlc->len_ctx.vh = height;
htmlc->len_ctx.root_style = htmlc->layout->style;
layout_document(htmlc, width, height);
diff --git a/render/layout.c b/render/layout.c
index d301e38..15eb1e8 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -315,7 +315,7 @@ static void layout_minmax_table(struct box *table,
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;
@@ -325,6 +325,13 @@ static void layout_minmax_table(struct box *table,
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)
@@ -4398,12 +4405,16 @@ layout_block_context(struct box *block,
(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]);
}
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units updated. release/3.7-44-g02ca4d9
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/02ca4d934d995ffee412a...
...commit http://git.netsurf-browser.org/netsurf.git/commit/02ca4d934d995ffee412ace...
...tree http://git.netsurf-browser.org/netsurf.git/tree/02ca4d934d995ffee412ace37...
The branch, tlsa/libcss-units has been updated
via 02ca4d934d995ffee412ace37dc7db11afb01206 (commit)
from fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=02ca4d934d995ffee41...
commit 02ca4d934d995ffee412ace37dc7db11afb01206
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
f form.c
diff --git a/render/form.c b/render/form.c
index 904272d..4320025 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;
-----------------------------------------------------------------------
Summary of changes:
render/form.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/render/form.c b/render/form.c
index 904272d..4320025 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;
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units updated. release/3.7-43-gfe0e7e9
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/fe0e7e9e9bf288a1051ae...
...commit http://git.netsurf-browser.org/netsurf.git/commit/fe0e7e9e9bf288a1051aeb1...
...tree http://git.netsurf-browser.org/netsurf.git/tree/fe0e7e9e9bf288a1051aeb1e8...
The branch, tlsa/libcss-units has been updated
discards 71832ed639bc23eb478316b0234c13c7a75585c0 (commit)
discards d5d585cf70bbb26dd141245632ee4ae6f6e63686 (commit)
discards 239ed38759495e31685b9c99a754cf71e8829017 (commit)
via fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (71832ed639bc23eb478316b0234c13c7a75585c0)
\
N -- N -- N (fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=fe0e7e9e9bf288a1051...
commit fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
WIP: make nscss_len2p{t|x} handle new libcss units.
This causes a ripple effect of all the callsites needing information
they didn't have. Most of the layout/redraw-time stuff is done,
although some remains (table.c and html_interaction).
Main things to do are:
1. We'll need know viewport dimensions at box-construction time.
e.g. for textarea setup.
2. The whole mess that is text selection needs some kind of
solution.
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index 5c7cbd9..c0d9628 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90;
+
+/**
+ * Map viewport-relative length units to either vh or vw.
+ *
+ * Non-viewport-relative units are unchanged.
+ *
+ * \param[in] ctx Length conversion context.
+ * \param[in] unit Unit to map.
+ * \return the mapped unit.
+ */
+static inline css_unit css_utils__fudge_viewport_units(
+ const nscss_len_ctx *ctx,
+ css_unit unit)
+{
+ switch (unit) {
+ case CSS_UNIT_VI:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VW;
+ } else {
+ unit = CSS_UNIT_VH;
+ }
+ break;
+ case CSS_UNIT_VB:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMIN:
+ if (ctx->vh < ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMAX:
+ if (ctx->vh > ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ default: break;
+ }
+
+ return unit;
+}
+
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(css_fixed length, css_unit unit)
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit)
{
/* Length must not be relative */
- assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX);
+ assert(unit != CSS_UNIT_EM &&
+ unit != CSS_UNIT_EX &&
+ unit != CSS_UNIT_CAP &&
+ unit != CSS_UNIT_CH &&
+ unit != CSS_UNIT_IC &&
+ unit != CSS_UNIT_REM &&
+ unit != CSS_UNIT_RLH);
+
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
/* We assume the screen and any other output has the same dpi */
@@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4)));
+ /* 1in = 101.6q => 1mm = (72/101.6)pt */
+ case CSS_UNIT_Q: return FMUL(length,
+ FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length;
/* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
+ case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
+ F_72), nscss_screen_dpi);
+ case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
+ F_72), nscss_screen_dpi);
default: break;
}
return 0;
}
-
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(css_fixed length, css_unit unit,
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
const css_computed_style *style)
{
/* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit;
- assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX));
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
case CSS_UNIT_EM:
case CSS_UNIT_EX:
+ case CSS_UNIT_CAP:
+ case CSS_UNIT_CH:
+ case CSS_UNIT_IC:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
+ assert(style != NULL);
+
css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */
- font_size = nscss_len2pt(font_size, font_unit);
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- /* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
- if (unit == CSS_UNIT_EX)
+ /* Scale non-em units to em. We have fixed ratios. */
+ switch (unit) {
+ case CSS_UNIT_EX:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
+ break;
+ case CSS_UNIT_CAP:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
+ break;
+ case CSS_UNIT_CH:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
+ break;
+ case CSS_UNIT_IC:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
+ break;
+ default: break;
+ }
}
break;
case CSS_UNIT_PX:
@@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break;
+ /* 1in = 101.6q => 1q = (DPI/101.6)px */
+ case CSS_UNIT_Q:
+ px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
+ break;
/* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72);
@@ -113,6 +208,41 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break;
+ case CSS_UNIT_REM:
+ {
+ css_fixed font_size = 0;
+ css_unit font_unit = CSS_UNIT_PT;
+
+ assert(ctx->root_style != NULL);
+
+ css_computed_font_size(ctx->root_style,
+ &font_size, &font_unit);
+
+ /* Convert to points */
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
+
+ /* Clamp to configured minimum */
+ if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
+ font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
+ }
+
+ /* Convert to pixels (manually, to maximise precision)
+ * 1in = 72pt => 1pt = (DPI/72)px */
+ px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
+ break;
+ }
+ /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
+ case CSS_UNIT_RLH:
+ px_per_unit = FDIV(nscss_screen_dpi, FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10)));
+ break;
+ case CSS_UNIT_VH:
+ px_per_unit = FDIV((length * ctx->vh), F_100);
+ break;
+ case CSS_UNIT_VW:
+ px_per_unit = FDIV((length * ctx->vw), F_100);
+ break;
default:
px_per_unit = 0;
break;
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index 21cb497..c8f4c82 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -27,24 +27,54 @@
extern css_fixed nscss_screen_dpi;
/**
+ * Length conversion context data.
+ */
+typedef struct nscss_len_ctx {
+ /**
+ * Viewport width in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vw;
+ /**
+ * Viewport height in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vh;
+ /**
+ * Computed style for the document root element.
+ * May be NULL if unit is not rem, or rlh.
+ */
+ const css_computed_style *root_style;
+} nscss_len_ctx;
+
+/**
* Convert an absolute CSS length to points.
*
- * \param[in] length Absolute CSS length.
- * \param[in] unit Unit of the length.
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Absolute CSS length.
+ * \param[in] unit Unit of the length.
* \return length in points
*/
-css_fixed nscss_len2pt(css_fixed length, css_unit unit);
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit);
/**
* Convert a CSS length to pixels.
*
- * \param length Length to convert
- * \param unit Corresponding unit
- * \param style Computed style applying to length. May be NULL if unit is
- * neither em nor ex
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Length to convert.
+ * \param[in] unit Corresponding unit.
+ * \param[in] style Computed style applying to length.
+ * May be NULL if unit is not em, ex, cap, ch, or ic.
* \return length in pixels
*/
-css_fixed nscss_len2px(css_fixed length, css_unit unit, const css_computed_style *style);
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
+ const css_computed_style *style);
/**
diff --git a/desktop/print.c b/desktop/print.c
index 54cc545..5c0333a 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
+ nscss_len_ctx len_ctx = {
+ .vw = DEFAULT_PAGE_WIDTH,
+ .vh = DEFAULT_PAGE_HEIGHT,
+ .root_style = NULL,
+ };
switch (configuration){
case PRINT_DEFAULT:
@@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
default:
return NULL;
diff --git a/render/box.c b/render/box.c
index 8b9c89e..c97e898 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 8208a6f..1af0a8b 100644
--- a/render/box.h
+++ b/render/box.h
@@ -91,6 +91,8 @@
#include <stdio.h>
#include <libcss/libcss.h>
+#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/font.c b/render/font.c
index 94ef877..a769b47 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 fba368a..52f5a62 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/html.c b/render/html.c
index 3cfc5e2..3160e3a 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 = width;
+ htmlc->len_ctx.root_style = htmlc->layout->style;
+
layout_document(htmlc, width, height);
layout = htmlc->layout;
@@ -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 30adaa0..2d14ed2 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 2f84cf8..66ecb2b 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -26,6 +26,7 @@
#include <libcss/libcss.h>
+#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 e98bdba..fb9e7b0 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 2f87306..9a97e5e 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 83dbc53..d301e38 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,12 +302,13 @@ 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;
@@ -328,7 +341,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 +358,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 +381,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 +447,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 +456,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 +495,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 +542,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 +556,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 +567,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 +587,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 +709,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 +736,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 +753,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 +780,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 +805,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 +821,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 +851,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 +870,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 +894,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 +954,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 +968,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 +977,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 +994,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 +1004,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 +1013,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 +1052,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 +1082,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 +1123,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 +1133,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 +1150,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 +1165,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 +1182,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 +1212,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 +1300,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 +1325,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 +1334,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 +1351,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 +1360,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 +1377,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 +1398,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 +1437,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 +1471,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 +1519,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 +1538,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 +1547,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 +1567,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 +1642,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 +1879,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 +1892,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 +1906,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 +2060,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 +2071,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 +2103,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 +2116,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 +2195,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 +2386,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 +2425,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 +2571,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 +2639,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 +2669,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 +2838,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 +2846,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 +2867,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 +2903,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 +2943,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 +2984,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 +3056,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 +3076,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 +3157,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 +3167,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 +3207,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 +3231,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 +3266,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 +3337,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 +3360,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 +3399,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 +3457,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 +3612,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 +3975,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 +4040,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 +4092,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 +4333,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,7 +4391,7 @@ 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 &&
@@ -4317,7 +4417,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 +4433,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 +4448,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 +4459,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 +4468,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 +4479,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 +4502,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 +4516,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 +4530,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 +4544,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 +4601,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 +4926,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 +5003,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 +5029,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 +5077,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 +5089,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 +5118,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 +5155,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 +5184,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 +5192,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 +5216,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 +5227,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 +5259,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 +5297,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 +5311,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 +5345,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 +5363,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 +5371,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 +5399,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 +5433,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/table.c b/render/table.c
index c41b913..08a2e80 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 ecd3043..2eeffe6 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
-----------------------------------------------------------------------
Summary of changes:
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units updated. release/3.7-45-g71832ed
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/71832ed639bc23eb47831...
...commit http://git.netsurf-browser.org/netsurf.git/commit/71832ed639bc23eb478316b...
...tree http://git.netsurf-browser.org/netsurf.git/tree/71832ed639bc23eb478316b02...
The branch, tlsa/libcss-units has been updated
via 71832ed639bc23eb478316b0234c13c7a75585c0 (commit)
from d5d585cf70bbb26dd141245632ee4ae6f6e63686 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=71832ed639bc23eb478...
commit 71832ed639bc23eb478316b0234c13c7a75585c0
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
f html interaction and html object
diff --git a/render/html_interaction.c b/render/html_interaction.c
index a302b90..2d14ed2 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,
@@ -911,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_object.c b/render/html_object.c
index e98bdba..fb9e7b0 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));
}
-----------------------------------------------------------------------
Summary of changes:
render/html_interaction.c | 9 +++++----
render/html_object.c | 6 ++++--
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/render/html_interaction.c b/render/html_interaction.c
index a302b90..2d14ed2 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,
@@ -911,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_object.c b/render/html_object.c
index e98bdba..fb9e7b0 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));
}
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units updated. release/3.7-44-gd5d585c
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/d5d585cf70bbb26dd1412...
...commit http://git.netsurf-browser.org/netsurf.git/commit/d5d585cf70bbb26dd141245...
...tree http://git.netsurf-browser.org/netsurf.git/tree/d5d585cf70bbb26dd14124563...
The branch, tlsa/libcss-units has been updated
via d5d585cf70bbb26dd141245632ee4ae6f6e63686 (commit)
from 239ed38759495e31685b9c99a754cf71e8829017 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d5d585cf70bbb26dd14...
commit d5d585cf70bbb26dd141245632ee4ae6f6e63686
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
f table.c
diff --git a/render/layout.c b/render/layout.c
index a36160a..d301e38 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -2071,7 +2071,8 @@ 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);
+ 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,
diff --git a/render/table.c b/render/table.c
index c41b913..08a2e80 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 ecd3043..2eeffe6 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
-----------------------------------------------------------------------
Summary of changes:
render/layout.c | 3 +-
render/table.c | 319 ++++++++++++++++++++++++++++++++++---------------------
render/table.h | 8 +-
3 files changed, 207 insertions(+), 123 deletions(-)
diff --git a/render/layout.c b/render/layout.c
index a36160a..d301e38 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -2071,7 +2071,8 @@ 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);
+ 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,
diff --git a/render/table.c b/render/table.c
index c41b913..08a2e80 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 ecd3043..2eeffe6 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
--
NetSurf Browser
5 years, 4 months
netsurf: branch tlsa/libcss-units created. release/3.7-43-g239ed38
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/239ed38759495e31685b9...
...commit http://git.netsurf-browser.org/netsurf.git/commit/239ed38759495e31685b9c9...
...tree http://git.netsurf-browser.org/netsurf.git/tree/239ed38759495e31685b9c99a...
The branch, tlsa/libcss-units has been created
at 239ed38759495e31685b9c99a754cf71e8829017 (commit)
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=239ed38759495e31685...
commit 239ed38759495e31685b9c99a754cf71e8829017
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
WIP: make nscss_len2p{t|x} handle new libcss units.
This causes a ripple effect of all the callsites needing information
they didn't have. Most of the layout/redraw-time stuff is done,
although some remains (table.c and html_interaction).
Main things to do are:
1. We'll need know viewport dimensions at box-construction time.
e.g. for textarea setup.
2. The whole mess that is text selection needs some kind of
solution.
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index 5c7cbd9..c0d9628 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90;
+
+/**
+ * Map viewport-relative length units to either vh or vw.
+ *
+ * Non-viewport-relative units are unchanged.
+ *
+ * \param[in] ctx Length conversion context.
+ * \param[in] unit Unit to map.
+ * \return the mapped unit.
+ */
+static inline css_unit css_utils__fudge_viewport_units(
+ const nscss_len_ctx *ctx,
+ css_unit unit)
+{
+ switch (unit) {
+ case CSS_UNIT_VI:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VW;
+ } else {
+ unit = CSS_UNIT_VH;
+ }
+ break;
+ case CSS_UNIT_VB:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMIN:
+ if (ctx->vh < ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMAX:
+ if (ctx->vh > ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ default: break;
+ }
+
+ return unit;
+}
+
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(css_fixed length, css_unit unit)
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit)
{
/* Length must not be relative */
- assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX);
+ assert(unit != CSS_UNIT_EM &&
+ unit != CSS_UNIT_EX &&
+ unit != CSS_UNIT_CAP &&
+ unit != CSS_UNIT_CH &&
+ unit != CSS_UNIT_IC &&
+ unit != CSS_UNIT_REM &&
+ unit != CSS_UNIT_RLH);
+
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
/* We assume the screen and any other output has the same dpi */
@@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4)));
+ /* 1in = 101.6q => 1mm = (72/101.6)pt */
+ case CSS_UNIT_Q: return FMUL(length,
+ FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length;
/* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
+ case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
+ F_72), nscss_screen_dpi);
+ case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
+ F_72), nscss_screen_dpi);
default: break;
}
return 0;
}
-
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(css_fixed length, css_unit unit,
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
const css_computed_style *style)
{
/* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit;
- assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX));
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
case CSS_UNIT_EM:
case CSS_UNIT_EX:
+ case CSS_UNIT_CAP:
+ case CSS_UNIT_CH:
+ case CSS_UNIT_IC:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
+ assert(style != NULL);
+
css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */
- font_size = nscss_len2pt(font_size, font_unit);
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- /* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
- if (unit == CSS_UNIT_EX)
+ /* Scale non-em units to em. We have fixed ratios. */
+ switch (unit) {
+ case CSS_UNIT_EX:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
+ break;
+ case CSS_UNIT_CAP:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
+ break;
+ case CSS_UNIT_CH:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
+ break;
+ case CSS_UNIT_IC:
+ px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
+ break;
+ default: break;
+ }
}
break;
case CSS_UNIT_PX:
@@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break;
+ /* 1in = 101.6q => 1q = (DPI/101.6)px */
+ case CSS_UNIT_Q:
+ px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
+ break;
/* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72);
@@ -113,6 +208,41 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break;
+ case CSS_UNIT_REM:
+ {
+ css_fixed font_size = 0;
+ css_unit font_unit = CSS_UNIT_PT;
+
+ assert(ctx->root_style != NULL);
+
+ css_computed_font_size(ctx->root_style,
+ &font_size, &font_unit);
+
+ /* Convert to points */
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
+
+ /* Clamp to configured minimum */
+ if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
+ font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
+ }
+
+ /* Convert to pixels (manually, to maximise precision)
+ * 1in = 72pt => 1pt = (DPI/72)px */
+ px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
+ break;
+ }
+ /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
+ case CSS_UNIT_RLH:
+ px_per_unit = FDIV(nscss_screen_dpi, FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10)));
+ break;
+ case CSS_UNIT_VH:
+ px_per_unit = FDIV((length * ctx->vh), F_100);
+ break;
+ case CSS_UNIT_VW:
+ px_per_unit = FDIV((length * ctx->vw), F_100);
+ break;
default:
px_per_unit = 0;
break;
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index 21cb497..c8f4c82 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -27,24 +27,54 @@
extern css_fixed nscss_screen_dpi;
/**
+ * Length conversion context data.
+ */
+typedef struct nscss_len_ctx {
+ /**
+ * Viewport width in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vw;
+ /**
+ * Viewport height in px.
+ * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
+ */
+ int vh;
+ /**
+ * Computed style for the document root element.
+ * May be NULL if unit is not rem, or rlh.
+ */
+ const css_computed_style *root_style;
+} nscss_len_ctx;
+
+/**
* Convert an absolute CSS length to points.
*
- * \param[in] length Absolute CSS length.
- * \param[in] unit Unit of the length.
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Absolute CSS length.
+ * \param[in] unit Unit of the length.
* \return length in points
*/
-css_fixed nscss_len2pt(css_fixed length, css_unit unit);
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit);
/**
* Convert a CSS length to pixels.
*
- * \param length Length to convert
- * \param unit Corresponding unit
- * \param style Computed style applying to length. May be NULL if unit is
- * neither em nor ex
+ * \param[in] ctx Length conversion context.
+ * \param[in] length Length to convert.
+ * \param[in] unit Corresponding unit.
+ * \param[in] style Computed style applying to length.
+ * May be NULL if unit is not em, ex, cap, ch, or ic.
* \return length in pixels
*/
-css_fixed nscss_len2px(css_fixed length, css_unit unit, const css_computed_style *style);
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
+ const css_computed_style *style);
/**
diff --git a/desktop/print.c b/desktop/print.c
index 54cc545..5c0333a 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
+ nscss_len_ctx len_ctx = {
+ .vw = DEFAULT_PAGE_WIDTH,
+ .vh = DEFAULT_PAGE_HEIGHT,
+ .root_style = NULL,
+ };
switch (configuration){
case PRINT_DEFAULT:
@@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINLEFT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINRIGHT] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINTOP] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] =
- nscss_len2px(length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = nscss_len2px(
+ &len_ctx, length, unit, NULL);
break;
default:
return NULL;
diff --git a/render/box.c b/render/box.c
index 8b9c89e..c97e898 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 8208a6f..1af0a8b 100644
--- a/render/box.h
+++ b/render/box.h
@@ -91,6 +91,8 @@
#include <stdio.h>
#include <libcss/libcss.h>
+#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/font.c b/render/font.c
index 94ef877..a769b47 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 fba368a..52f5a62 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/html.c b/render/html.c
index 3cfc5e2..3160e3a 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 = width;
+ htmlc->len_ctx.root_style = htmlc->layout->style;
+
layout_document(htmlc, width, height);
layout = htmlc->layout;
@@ -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 30adaa0..a302b90 100644
--- a/render/html_interaction.c
+++ b/render/html_interaction.c
@@ -649,7 +649,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 */
diff --git a/render/html_internal.h b/render/html_internal.h
index 2f84cf8..66ecb2b 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -26,6 +26,7 @@
#include <libcss/libcss.h>
+#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_redraw.c b/render/html_redraw.c
index 2f87306..9a97e5e 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 83dbc53..a36160a 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,12 +302,13 @@ 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;
@@ -328,7 +341,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 +358,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 +381,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 +447,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 +456,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 +495,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 +542,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 +556,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 +567,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 +587,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 +709,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 +736,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 +753,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 +780,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 +805,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 +821,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 +851,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 +870,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 +894,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 +954,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 +968,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 +977,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 +994,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 +1004,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 +1013,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 +1052,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 +1082,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 +1123,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 +1133,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 +1150,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 +1165,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 +1182,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 +1212,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 +1300,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 +1325,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 +1334,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 +1351,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 +1360,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 +1377,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 +1398,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 +1437,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 +1471,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 +1519,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 +1538,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 +1547,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 +1567,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 +1642,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 +1879,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 +1892,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 +1906,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 +2060,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) {
@@ -2005,8 +2072,9 @@ static bool layout_table(struct box *table, int available_width,
assert(c->style);
table_used_border_for_cell(c);
- layout_find_dimensions(available_width, -1,
- c, c->style, 0, 0, 0, 0, 0, 0,
+ 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 +2102,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 +2115,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 +2194,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 +2385,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 +2424,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 +2570,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 +2638,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 +2668,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 +2837,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 +2845,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 +2866,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 +2902,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 +2942,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 +2983,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 +3055,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 +3075,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 +3156,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 +3166,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 +3206,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 +3230,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 +3265,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 +3336,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 +3359,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 +3398,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 +3456,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 +3611,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 +3974,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 +4039,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 +4091,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 +4332,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,7 +4390,7 @@ 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 &&
@@ -4317,7 +4416,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 +4432,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 +4447,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 +4458,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 +4467,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 +4478,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 +4501,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 +4515,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 +4529,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 +4543,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 +4600,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 +4925,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 +5002,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 +5028,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 +5076,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 +5088,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 +5117,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 +5154,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 +5183,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 +5191,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 +5215,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 +5226,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 +5258,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 +5296,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 +5310,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 +5344,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 +5362,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 +5370,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 +5398,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 +5432,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;
}
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=f231bab75e3b8469a13...
commit f231bab75e3b8469a130678f5d7902f5832c2dd1
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Layout: No need to expose layout_calculate_descendant_bboxes().
diff --git a/render/layout.c b/render/layout.c
index b19d93f..83dbc53 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -5061,56 +5061,6 @@ layout_position_relative(struct box *root, struct box *fp, int fx, int fy)
}
-/* exported function documented in render/layout.h */
-bool layout_document(html_content *content, int width, int height)
-{
- bool ret;
- struct box *doc = content->layout;
- const struct gui_layout_table *font_func = content->font_func;
-
- layout_minmax_block(doc, font_func);
-
- layout_block_find_dimensions(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 +
- doc->padding[LEFT] + doc->padding[RIGHT] +
- doc->border[RIGHT].width + doc->margin[RIGHT];
- if (width < 0) {
- width = 0;
- }
- doc->width = width;
-
- ret = layout_block_context(doc, height, content);
-
- /* make <html> and <body> fill available height */
- if (doc->y + doc->padding[TOP] + doc->height + doc->padding[BOTTOM] +
- doc->border[BOTTOM].width + doc->margin[BOTTOM] <
- height) {
- doc->height = height - (doc->y + doc->padding[TOP] +
- doc->padding[BOTTOM] +
- doc->border[BOTTOM].width +
- doc->margin[BOTTOM]);
- if (doc->children)
- doc->children->height = doc->height -
- (doc->children->margin[TOP] +
- doc->children->border[TOP].width +
- doc->children->padding[TOP] +
- doc->children->padding[BOTTOM] +
- doc->children->border[BOTTOM].width +
- doc->children->margin[BOTTOM]);
- }
-
- layout_lists(doc, font_func);
- layout_position_absolute(doc, doc, 0, 0, content);
- layout_position_relative(doc, doc, 0, 0);
-
- layout_calculate_descendant_bboxes(doc);
-
- return ret;
-}
-
-
/**
* Find a box's bounding box relative to itself, i.e. the box's border edge box
*
@@ -5215,8 +5165,13 @@ layout_update_descendant_bbox(struct box *box,
}
-/* exported function documented in render/layout.h */
-void layout_calculate_descendant_bboxes(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
+ */
+static void layout_calculate_descendant_bboxes(struct box *box)
{
struct box *child;
@@ -5303,3 +5258,53 @@ void layout_calculate_descendant_bboxes(struct box *box)
layout_update_descendant_bbox(box, child, 0, 0);
}
}
+
+
+/* exported function documented in render/layout.h */
+bool layout_document(html_content *content, int width, int height)
+{
+ bool ret;
+ struct box *doc = content->layout;
+ const struct gui_layout_table *font_func = content->font_func;
+
+ layout_minmax_block(doc, font_func);
+
+ layout_block_find_dimensions(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 +
+ doc->padding[LEFT] + doc->padding[RIGHT] +
+ doc->border[RIGHT].width + doc->margin[RIGHT];
+ if (width < 0) {
+ width = 0;
+ }
+ doc->width = width;
+
+ ret = layout_block_context(doc, height, content);
+
+ /* make <html> and <body> fill available height */
+ if (doc->y + doc->padding[TOP] + doc->height + doc->padding[BOTTOM] +
+ doc->border[BOTTOM].width + doc->margin[BOTTOM] <
+ height) {
+ doc->height = height - (doc->y + doc->padding[TOP] +
+ doc->padding[BOTTOM] +
+ doc->border[BOTTOM].width +
+ doc->margin[BOTTOM]);
+ if (doc->children)
+ doc->children->height = doc->height -
+ (doc->children->margin[TOP] +
+ doc->children->border[TOP].width +
+ doc->children->padding[TOP] +
+ doc->children->padding[BOTTOM] +
+ doc->children->border[BOTTOM].width +
+ doc->children->margin[BOTTOM]);
+ }
+
+ layout_lists(doc, font_func);
+ layout_position_absolute(doc, doc, 0, 0, content);
+ layout_position_relative(doc, doc, 0, 0);
+
+ layout_calculate_descendant_bboxes(doc);
+
+ return ret;
+}
diff --git a/render/layout.h b/render/layout.h
index 0aa0da3..cd5ddd7 100644
--- a/render/layout.h
+++ b/render/layout.h
@@ -42,12 +42,4 @@ struct gui_layout_table;
*/
bool layout_document(struct html_content *content, int width, int height);
-/**
- * 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
- */
-void layout_calculate_descendant_bboxes(struct box *box);
-
#endif
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=f7fd925aee7fc9aab6e...
commit f7fd925aee7fc9aab6e76411e5fba58e5abff14b
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Layout: No need to expose layout_inline_container().
diff --git a/render/layout.c b/render/layout.c
index fa49667..b19d93f 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -2634,493 +2634,340 @@ static bool layout_block_object(struct box *block)
/**
- * Layout a block formatting context.
+ * Insert a float into a container.
*
- * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
- * \param viewport_height Height of viewport in pixels or -ve if unknown
- * \param content Memory pool for any new boxes
- * \return true on success, false on memory exhaustion
+ * \param cont block formatting context block, used to contain float
+ * \param b box to add to float
*
- * This function carries out layout of a block and its children, as described
- * in CSS 2.1 9.4.1.
+ * This sorts floats in order of descending bottom edges.
*/
-static bool
-layout_block_context(struct box *block,
- int viewport_height,
- html_content *content)
+static void add_float_to_container(struct box *cont, struct box *b)
{
- struct box *box;
- int cx, cy; /**< current coordinates */
- int max_pos_margin = 0;
- int max_neg_margin = 0;
- int y = 0;
- int lm, rm;
- struct box *margin_collapse = NULL;
- bool in_margin = false;
- css_fixed gadget_size;
- css_unit gadget_unit; /* Checkbox / radio buttons */
-
- assert(block->type == BOX_BLOCK ||
- block->type == BOX_INLINE_BLOCK ||
- block->type == BOX_TABLE_CELL);
- assert(block->width != UNKNOWN_WIDTH);
- assert(block->width != AUTO);
+ struct box *box = cont->float_children;
+ int b_bottom = b->y + b->height;
- block->float_children = NULL;
- block->cached_place_below_level = 0;
- block->clear_level = 0;
+ assert(b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT);
- /* special case if the block contains an object */
- if (block->object) {
- int temp_width = block->width;
- if (!layout_block_object(block))
- return false;
- layout_get_object_dimensions(block, &temp_width,
- &block->height, INT_MIN, INT_MAX,
- INT_MIN, INT_MAX);
- return true;
- } else if (block->flags & REPLACE_DIM) {
- return true;
+ if (box == NULL) {
+ /* No other float children */
+ b->next_float = NULL;
+ cont->float_children = b;
+ return;
+ } else if (b_bottom >= box->y + box->height) {
+ /* Goes at start of list */
+ b->next_float = cont->float_children;
+ cont->float_children = b;
+ } else {
+ struct box *prev = NULL;
+ while (box != NULL && b_bottom < box->y + box->height) {
+ prev = box;
+ box = box->next_float;
+ }
+ if (prev != NULL) {
+ b->next_float = prev->next_float;
+ prev->next_float = b;
+ }
}
+}
- /* special case if the block contains an radio button or checkbox */
- if (block->gadget && (block->gadget->type == GADGET_RADIO ||
- block->gadget->type == GADGET_CHECKBOX)) {
- /* form checkbox or radio button
- * if width or height is AUTO, set it to 1em */
- gadget_unit = CSS_UNIT_EM;
- gadget_size = INTTOFIX(1);
- if (block->height == AUTO)
- block->height = FIXTOINT(nscss_len2px(gadget_size,
- gadget_unit, block->style));
+
+/**
+ * Split a text box.
+ *
+ * \param content memory pool for any new boxes
+ * \param fstyle style for text in text box
+ * \param split_box box with text to split
+ * \param new_length new length for text in split_box, after splitting
+ * \param new_width new width for text in split_box, after splitting
+ * \return true on success, false on memory exhaustion
+ *
+ * A new box is created and inserted into the box tree after split_box,
+ * containing the text after new_length excluding the initial space character.
+ */
+static bool
+layout_text_box_split(html_content *content,
+ plot_font_style_t *fstyle,
+ struct box *split_box,
+ size_t new_length,
+ int new_width)
+{
+ int space_width = split_box->space;
+ struct box *c2;
+ const struct gui_layout_table *font_func = content->font_func;
+ bool space = (split_box->text[new_length] == ' ');
+ int used_length = new_length + (space ? 1 : 0);
+
+ if ((space && space_width == 0) || space_width == UNKNOWN_WIDTH) {
+ /* We're need to add a space, and we don't know how big
+ * it's to be, OR we have a space of unknown width anyway;
+ * Calculate space width */
+ font_func->width(fstyle, " ", 1, &space_width);
}
- box = block->children;
- /* set current coordinates to top-left of the block */
- cx = 0;
- y = cy = block->padding[TOP];
- if (box)
- box->y = block->padding[TOP];
+ if (split_box->space == UNKNOWN_WIDTH)
+ split_box->space = space_width;
+ if (!space)
+ space_width = 0;
- /* Step through the descendants of the block in depth-first order, but
- * not into the children of boxes which aren't blocks. For example, if
- * the tree passed to this function looks like this (box->type shown):
- *
- * block -> BOX_BLOCK
- * BOX_BLOCK * (1)
- * BOX_INLINE_CONTAINER * (2)
- * BOX_INLINE
- * BOX_TEXT
- * ...
- * BOX_BLOCK * (3)
- * BOX_TABLE * (4)
- * BOX_TABLE_ROW
- * BOX_TABLE_CELL
- * ...
- * BOX_TABLE_CELL
- * ...
- * BOX_BLOCK * (5)
- * BOX_INLINE_CONTAINER * (6)
- * BOX_TEXT
- * ...
- * then the while loop will visit each box marked with *, setting box
- * to each in the order shown. */
- while (box) {
- enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
- enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
+ /* Create clone of split_box, c2 */
+ c2 = talloc_memdup(content->bctx, split_box, sizeof *c2);
+ if (!c2)
+ return false;
+ c2->flags |= CLONE;
- assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
- box->type == BOX_INLINE_CONTAINER);
+ /* Set remaining text in c2 */
+ c2->text += used_length;
- /* Tables are laid out before being positioned, because the
- * position depends on the width which is calculated in
- * table layout. Blocks and inline containers are positioned
- * before being laid out, because width is not dependent on
- * content, and the position is required during layout for
- * correct handling of floats.
- */
+ /* Set c2 according to the remaining text */
+ c2->width -= new_width + space_width;
+ c2->flags &= ~MEASURED; /* width has been estimated */
+ c2->length = split_box->length - used_length;
- if (box->style &&
- (css_computed_position(box->style) ==
- CSS_POSITION_ABSOLUTE ||
- css_computed_position(box->style) ==
- CSS_POSITION_FIXED)) {
- box->x = box->parent->padding[LEFT];
- /* absolute positioned; this element will establish
- * its own block context when it gets laid out later,
- * so no need to look at its children now. */
- goto advance_to_next_box;
- }
+ /* Update split_box for its reduced text */
+ split_box->width = new_width;
+ split_box->flags |= MEASURED;
+ split_box->length = new_length;
+ split_box->space = space_width;
- /* 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,
- viewport_height,
- &max_pos_margin, &max_neg_margin);
- /* We have a margin that has not yet been applied. */
- in_margin = true;
- }
+ /* Insert c2 into box list */
+ c2->next = split_box->next;
+ split_box->next = c2;
+ c2->prev = split_box;
+ if (c2->next)
+ c2->next->prev = c2;
+ else
+ c2->parent->last = c2;
- /* Clearance. */
- y = 0;
- if (box->style && css_computed_clear(box->style) !=
- CSS_CLEAR_NONE)
- y = layout_clear(block->float_children,
- css_computed_clear(box->style));
+ NSLOG(layout, DEBUG,
+ "split_box %p len: %" PRIsizet " \"%.*s\"",
+ split_box,
+ split_box->length,
+ (int)split_box->length,
+ split_box->text);
+ NSLOG(layout, DEBUG,
+ " new_box %p len: %" PRIsizet " \"%.*s\"",
+ c2,
+ c2->length,
+ (int)c2->length,
+ c2->text);
- /* Find box's overflow properties */
- if (box->style) {
- overflow_x = css_computed_overflow_x(box->style);
- overflow_y = css_computed_overflow_y(box->style);
- }
+ return true;
+}
- /* Blocks establishing a block formatting context get minimum
- * left and right margins to avoid any floats. */
- lm = rm = 0;
- if (box->type == BOX_BLOCK || box->flags & IFRAME) {
- if (!box->object && !(box->flags & IFRAME) &&
- !(box->flags & REPLACE_DIM) &&
- box->style &&
- (overflow_x != CSS_OVERFLOW_VISIBLE ||
- overflow_y != CSS_OVERFLOW_VISIBLE)) {
- /* box establishes new block formatting context
- * so available width may be diminished due to
- * floats. */
- int x0, x1, top;
- struct box *left, *right;
- top = cy + max_pos_margin - max_neg_margin;
- top = (top > y) ? top : y;
- x0 = cx;
- x1 = cx + box->parent->width -
- box->parent->padding[LEFT] -
- box->parent->padding[RIGHT];
- find_sides(block->float_children, top, top,
- &x0, &x1, &left, &right);
- /* calculate min required left & right margins
- * needed to avoid floats */
- lm = x0 - cx;
- rm = cx + box->parent->width -
- box->parent->padding[LEFT] -
- box->parent->padding[RIGHT] -
- x1;
- }
- layout_block_find_dimensions(box->parent->width,
- viewport_height, lm, rm, box);
- if (box->type == BOX_BLOCK && !(box->flags & IFRAME)) {
- layout_block_add_scrollbar(box, RIGHT);
- layout_block_add_scrollbar(box, BOTTOM);
- }
- } else if (box->type == BOX_TABLE) {
- if (box->style != NULL) {
- enum css_width_e wtype;
- css_fixed width = 0;
- css_unit unit = CSS_UNIT_PX;
+/**
+ * Compute dimensions of box, margins, paddings, and borders for a floating
+ * element using shrink-to-fit. Also used for inline-blocks.
+ *
+ * \param available_width Max width available in pixels
+ * \param style Box's style
+ * \param box Box for which to find dimensions
+ * Box margins, borders, paddings, width and
+ * height are updated.
+ */
+static void
+layout_float_find_dimensions(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;
+ int *padding = box->padding;
+ struct box_border *border = box->border;
+ enum css_overflow_e overflow_x = css_computed_overflow_x(style);
+ enum css_overflow_e overflow_y = css_computed_overflow_y(style);
+ int scrollbar_width_x =
+ (overflow_x == CSS_OVERFLOW_SCROLL ||
+ overflow_x == CSS_OVERFLOW_AUTO) ?
+ SCROLLBAR_WIDTH : 0;
+ int scrollbar_width_y =
+ (overflow_y == CSS_OVERFLOW_SCROLL ||
+ overflow_y == CSS_OVERFLOW_AUTO) ?
+ SCROLLBAR_WIDTH : 0;
- wtype = css_computed_width(box->style, &width,
- &unit);
+ layout_find_dimensions(available_width, -1, box, style, &width, &height,
+ &max_width, &min_width, &max_height, &min_height,
+ margin, padding, border);
- if (wtype == CSS_WIDTH_AUTO) {
- /* max available width may be
- * diminished due to floats. */
- int x0, x1, top;
- struct box *left, *right;
- top = cy + max_pos_margin -
- max_neg_margin;
- top = (top > y) ? top : y;
- x0 = cx;
- x1 = cx + box->parent->width -
- box->parent->padding[LEFT] -
- box->parent->padding[RIGHT];
- find_sides(block->float_children,
- top, top, &x0, &x1,
- &left, &right);
- /* calculate min required left & right
- * margins needed to avoid floats */
- lm = x0 - cx;
- rm = cx + box->parent->width -
- box->parent->padding[LEFT] -
- box->parent->padding[RIGHT] -
- x1;
- }
- }
- if (!layout_table(box, box->parent->width - lm - rm,
- content))
- return false;
- layout_solve_width(box, box->parent->width, box->width,
- lm, rm, -1, -1);
- }
+ if (margin[LEFT] == AUTO)
+ margin[LEFT] = 0;
+ if (margin[RIGHT] == AUTO)
+ margin[RIGHT] = 0;
- /* Position box: horizontal. */
- box->x = box->parent->padding[LEFT] + box->margin[LEFT] +
- box->border[LEFT].width;
- cx += box->x;
+ if (box->gadget == NULL) {
+ padding[RIGHT] += scrollbar_width_y;
+ padding[BOTTOM] += scrollbar_width_x;
+ }
- /* Position box: vertical. */
- if (box->border[TOP].width) {
- box->y += box->border[TOP].width;
- cy += box->border[TOP].width;
- }
+ if (box->object && !(box->flags & REPLACE_DIM) &&
+ content_get_type(box->object) != CONTENT_HTML) {
+ /* Floating replaced element, with intrinsic width or height.
+ * See 10.3.6 and 10.6.2 */
+ layout_get_object_dimensions(box, &width, &height,
+ min_width, max_width, min_height, max_height);
+ } else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX ||
+ box->gadget->type == GADGET_PASSWORD ||
+ box->gadget->type == GADGET_FILE ||
+ box->gadget->type == GADGET_TEXTAREA)) {
+ css_fixed size = 0;
+ css_unit unit = CSS_UNIT_EM;
- /* Vertical margin */
- if (((box->type == BOX_BLOCK &&
- (box->flags & HAS_HEIGHT)) ||
- box->type == BOX_TABLE ||
- (box->type == BOX_INLINE_CONTAINER &&
- box != box->parent->children) ||
- margin_collapse == box) &&
- in_margin == true) {
- /* Margin goes above this box. */
- cy += max_pos_margin - max_neg_margin;
- box->y += max_pos_margin - max_neg_margin;
+ /* Give sensible dimensions to gadgets, with auto width/height,
+ * that don't shrink to fit contained text. */
+ assert(box->style);
- /* Current margin has been applied. */
- in_margin = false;
- max_pos_margin = max_neg_margin = 0;
+ if (box->gadget->type == GADGET_TEXTBOX ||
+ box->gadget->type == GADGET_PASSWORD ||
+ box->gadget->type == GADGET_FILE) {
+ if (width == AUTO) {
+ size = INTTOFIX(10);
+ width = FIXTOINT(nscss_len2px(size, unit,
+ box->style));
+ }
+ if (box->gadget->type == GADGET_FILE &&
+ height == AUTO) {
+ size = FLTTOFIX(1.5);
+ height = FIXTOINT(nscss_len2px(size, unit,
+ box->style));
+ }
}
-
- /* Handle clearance */
- if (box->type != BOX_INLINE_CONTAINER &&
- (y > 0) && (cy < y)) {
- /* box clears something*/
- box->y += y - cy;
- cy = y;
+ if (box->gadget->type == GADGET_TEXTAREA) {
+ if (width == AUTO) {
+ size = INTTOFIX(10);
+ width = FIXTOINT(nscss_len2px(size, unit,
+ box->style));
+ }
+ if (height == AUTO) {
+ size = INTTOFIX(4);
+ height = FIXTOINT(nscss_len2px(size, unit,
+ box->style));
+ }
}
+ } else if (width == AUTO) {
+ /* CSS 2.1 section 10.3.5 */
+ width = min(max(box->min_width, available_width),
+ box->max_width);
- /* Unless the box has an overflow style of visible, the box
- * establishes a new block context. */
- if (box->type == BOX_BLOCK && box->style &&
- (overflow_x != CSS_OVERFLOW_VISIBLE ||
- overflow_y != CSS_OVERFLOW_VISIBLE)) {
+ /* width includes margin, borders and padding */
+ if (width == available_width) {
+ width -= box->margin[LEFT] + box->border[LEFT].width +
+ box->padding[LEFT] +
+ box->padding[RIGHT] +
+ box->border[RIGHT].width +
+ box->margin[RIGHT];
+ } else {
+ /* width was obtained from a min_width or max_width
+ * value, so need to use the same method for calculating
+ * 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);
+ if (fixed < 0)
+ fixed = 0;
- layout_block_context(box, viewport_height, content);
+ width -= fixed;
+ }
- cy += box->padding[TOP];
+ if (max_width >= 0 && width > max_width) width = max_width;
+ if (min_width > 0 && width < min_width) width = min_width;
- if (box->height == AUTO) {
- box->height = 0;
- layout_block_add_scrollbar(box, BOTTOM);
- }
+ } else {
+ if (max_width >= 0 && width > max_width) width = max_width;
+ if (min_width > 0 && width < min_width) width = min_width;
+ width -= scrollbar_width_y;
+ }
- cx -= box->x;
- cy += box->height + box->padding[BOTTOM] +
- box->border[BOTTOM].width;
- y = box->y + box->padding[TOP] + box->height +
- box->padding[BOTTOM] +
- box->border[BOTTOM].width;
+ box->width = width;
+ box->height = height;
- /* Skip children, because they are done in the new
- * block context */
- goto advance_to_next_box;
- }
+ if (margin[TOP] == AUTO)
+ margin[TOP] = 0;
+ if (margin[BOTTOM] == AUTO)
+ margin[BOTTOM] = 0;
+}
- NSLOG(layout, DEBUG, "box %p, cx %i, cy %i", box, cx, cy);
- /* Layout (except tables). */
- if (box->object) {
- if (!layout_block_object(box))
- return false;
+/**
+ * Layout the contents of a float or inline block.
+ *
+ * \param b float or inline block box
+ * \param width available width
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+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);
+ if (b->type == BOX_TABLE) {
+ if (!layout_table(b, width, content))
+ return false;
+ if (b->margin[LEFT] == AUTO)
+ b->margin[LEFT] = 0;
+ if (b->margin[RIGHT] == AUTO)
+ b->margin[RIGHT] = 0;
+ if (b->margin[TOP] == AUTO)
+ b->margin[TOP] = 0;
+ if (b->margin[BOTTOM] == AUTO)
+ b->margin[BOTTOM] = 0;
+ } else
+ return layout_block_context(b, -1, content);
+ return true;
+}
- } else if (box->type == BOX_INLINE_CONTAINER) {
- box->width = box->parent->width;
- if (!layout_inline_container(box, box->width, block,
- cx, cy, content))
- return false;
- } else if (box->type == BOX_TABLE) {
- /* Move down to avoid floats if necessary. */
- int x0, x1;
- struct box *left, *right;
- y = cy;
- while (1) {
- enum css_width_e wtype;
- css_fixed width = 0;
- css_unit unit = CSS_UNIT_PX;
-
- wtype = css_computed_width(box->style,
- &width, &unit);
-
- x0 = cx;
- x1 = cx + box->parent->width;
- find_sides(block->float_children, y,
- y + box->height,
- &x0, &x1, &left, &right);
- if (wtype == CSS_WIDTH_AUTO)
- break;
- if (box->width <= x1 - x0)
- break;
- if (!left && !right)
- break;
- else if (!left)
- y = right->y + right->height + 1;
- else if (!right)
- y = left->y + left->height + 1;
- else if (left->y + left->height <
- right->y + right->height)
- y = left->y + left->height + 1;
- else
- y = right->y + right->height + 1;
- }
- box->x += x0 - cx;
- cx = x0;
- box->y += y - cy;
- cy = y;
- }
-
- /* Advance to next box. */
- if (box->type == BOX_BLOCK && !box->object && !(box->iframe) &&
- box->children) {
- /* Down into children. */
-
- if (box == margin_collapse) {
- /* Current margin collapsed though to this box.
- * Unset margin_collapse. */
- margin_collapse = NULL;
- }
-
- y = box->padding[TOP];
- box = box->children;
- box->y = y;
- cy += y;
- continue;
- } else if (box->type == BOX_BLOCK || box->object ||
- box->flags & IFRAME)
- cy += box->padding[TOP];
-
- if (box->type == BOX_BLOCK && box->height == AUTO) {
- box->height = 0;
- layout_block_add_scrollbar(box, BOTTOM);
- }
-
- cy += box->height + box->padding[BOTTOM] +
- box->border[BOTTOM].width;
- cx -= box->x;
- y = box->y + box->padding[TOP] + box->height +
- box->padding[BOTTOM] +
- box->border[BOTTOM].width;
-
- advance_to_next_box:
- if (!box->next) {
- /* No more siblings:
- * up to first ancestor with a sibling. */
-
- do {
- if (box == margin_collapse) {
- /* Current margin collapsed though to
- * this box. Unset margin_collapse. */
- margin_collapse = NULL;
- }
-
- /* Apply bottom margin */
- if (max_pos_margin < box->margin[BOTTOM])
- max_pos_margin = box->margin[BOTTOM];
- else if (max_neg_margin < -box->margin[BOTTOM])
- max_neg_margin = -box->margin[BOTTOM];
-
- box = box->parent;
- if (box == block)
- break;
-
- /* Margin is invalidated if this is a box
- * margins can't collapse through. */
- if (box->type == BOX_BLOCK &&
- box->flags & MAKE_HEIGHT) {
- margin_collapse = NULL;
- in_margin = false;
- max_pos_margin = max_neg_margin = 0;
- }
-
- if (box->height == AUTO) {
- box->height = y - box->padding[TOP];
-
- if (box->type == BOX_BLOCK)
- layout_block_add_scrollbar(box,
- BOTTOM);
- } else
- cy += box->height -
- (y - box->padding[TOP]);
-
- /* Apply any min-height and max-height to
- * boxes in normal flow */
- if (box->style &&
- css_computed_position(box->style) !=
- CSS_POSITION_ABSOLUTE &&
- layout_apply_minmax_height(box,
- NULL)) {
- /* Height altered */
- /* Set current cy */
- cy += box->height -
- (y - box->padding[TOP]);
- }
-
- cy += box->padding[BOTTOM] +
- box->border[BOTTOM].width;
- cx -= box->x;
- y = box->y + box->padding[TOP] + box->height +
- box->padding[BOTTOM] +
- box->border[BOTTOM].width;
+/**
+ * Position a float in the first available space.
+ *
+ * \param c float box to position
+ * \param width available width
+ * \param cx x coordinate relative to cont to place float right of
+ * \param y y coordinate relative to cont to place float below
+ * \param cont ancestor box which defines horizontal space, for floats
+ */
+static void
+place_float_below(struct box *c, int width, int cx, int y, struct box *cont)
+{
+ int x0, x1, yy;
+ struct box *left;
+ struct box *right;
- } while (box->next == NULL);
- if (box == block)
- break;
- }
+ yy = y > cont->cached_place_below_level ?
+ y : cont->cached_place_below_level;
- /* To next sibling. */
+ NSLOG(layout, DEBUG,
+ "c %p, width %i, cx %i, y %i, cont %p", c,
+ width, cx, y, cont);
- if (box == margin_collapse) {
- /* Current margin collapsed though to this box.
- * Unset margin_collapse. */
- margin_collapse = NULL;
+ do {
+ y = yy;
+ x0 = cx;
+ x1 = cx + width;
+ find_sides(cont->float_children, y, y + c->height, &x0, &x1,
+ &left, &right);
+ if (left != 0 && right != 0) {
+ yy = (left->y + left->height <
+ right->y + right->height ?
+ left->y + left->height :
+ right->y + right->height);
+ } else if (left == 0 && right != 0) {
+ yy = right->y + right->height;
+ } else if (left != 0 && right == 0) {
+ yy = left->y + left->height;
}
+ } while ((left != 0 || right != 0) && (c->width > x1 - x0));
- if (max_pos_margin < box->margin[BOTTOM])
- max_pos_margin = box->margin[BOTTOM];
- else if (max_neg_margin < -box->margin[BOTTOM])
- max_neg_margin = -box->margin[BOTTOM];
-
- box = box->next;
- box->y = y;
- }
-
- /* Account for bottom margin of last contained block */
- cy += max_pos_margin - max_neg_margin;
-
- /* Increase height to contain any floats inside (CSS 2.1 10.6.7). */
- for (box = block->float_children; box; box = box->next_float) {
- y = box->y + box->height + box->padding[BOTTOM] +
- box->border[BOTTOM].width + box->margin[BOTTOM];
- if (cy < y)
- cy = y;
- }
-
- if (block->height == AUTO) {
- block->height = cy - block->padding[TOP];
- if (block->type == BOX_BLOCK)
- layout_block_add_scrollbar(block, BOTTOM);
- }
-
- if (block->style && css_computed_position(block->style) !=
- CSS_POSITION_ABSOLUTE) {
- /* Block is in normal flow */
- layout_apply_minmax_height(block, NULL);
- }
-
- if (block->gadget &&
- (block->gadget->type == GADGET_TEXTAREA ||
- block->gadget->type == GADGET_PASSWORD ||
- block->gadget->type == GADGET_TEXTBOX)) {
- int ta_width = block->padding[LEFT] + block->width +
- block->padding[RIGHT];
- int ta_height = block->padding[TOP] + block->height +
- block->padding[BOTTOM];
- textarea_set_layout(block->gadget->data.text.ta,
- ta_width, ta_height,
- block->padding[TOP], block->padding[RIGHT],
- block->padding[BOTTOM], block->padding[LEFT]);
+ if (c->type == BOX_FLOAT_LEFT) {
+ c->x = x0;
+ } else {
+ c->x = x1 - c->width;
}
-
- return true;
+ c->y = y;
+ cont->cached_place_below_level = y;
}
@@ -3160,1944 +3007,2107 @@ static int line_height(const css_computed_style *style)
/**
- * Layout list markers.
+ * Position a line of boxes in inline formatting context.
+ *
+ * \param first box at start of line
+ * \param width available width on input, updated with actual width on output
+ * (may be incorrect if the line gets split?)
+ * \param y coordinate of top of line, updated on exit to bottom
+ * \param cx coordinate of left of line relative to cont
+ * \param cy coordinate of top of line relative to cont
+ * \param cont ancestor box which defines horizontal space, for floats
+ * \param indent apply any first-line indent
+ * \param has_text_children at least one TEXT in the inline_container
+ * \param next_box updated to first box for next line, or 0 at end
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
*/
-static void
-layout_lists(struct box *box,
- const struct gui_layout_table *font_func)
+static bool
+layout_line(struct box *first,
+ int *width,
+ int *y,
+ int cx,
+ int cy,
+ struct box *cont,
+ bool indent,
+ bool has_text_children,
+ html_content *content,
+ struct box **next_box)
{
- struct box *child;
- struct box *marker;
- plot_font_style_t fstyle;
-
- for (child = box->children; child; child = child->next) {
- if (child->list_marker) {
- marker = child->list_marker;
- if (marker->object) {
- marker->width =
- content_get_width(marker->object);
- marker->x = -marker->width;
- marker->height =
- content_get_height(marker->object);
- marker->y = (line_height(marker->style) -
- marker->height) / 2;
- } else if (marker->text) {
- if (marker->width == UNKNOWN_WIDTH) {
- font_plot_style_from_css(marker->style,
- &fstyle);
- font_func->width(&fstyle,
- marker->text,
- marker->length,
- &marker->width);
- marker->flags |= MEASURED;
- }
- marker->x = -marker->width;
- marker->y = 0;
- marker->height = line_height(marker->style);
- } else {
- marker->x = 0;
- marker->y = 0;
- marker->width = 0;
- marker->height = 0;
- }
- /* Gap between marker and content */
- marker->x -= 4;
- }
- layout_lists(child, font_func);
- }
-}
+ int height, used_height;
+ int x0 = 0;
+ int x1 = *width;
+ int x, h, x_previous;
+ int fy = cy;
+ struct box *left;
+ struct box *right;
+ struct box *b;
+ struct box *split_box = 0;
+ struct box *d;
+ struct box *br_box = 0;
+ bool move_y = false;
+ bool place_below = false;
+ int space_before = 0, space_after = 0;
+ unsigned int inline_count = 0;
+ unsigned int i;
+ const struct gui_layout_table *font_func = content->font_func;
+ plot_font_style_t fstyle;
+ NSLOG(layout, DEBUG,
+ "first %p, first->text '%.*s', width %i, y %i, cx %i, cy %i",
+ first,
+ (int)first->length,
+ first->text,
+ *width,
+ *y,
+ cx,
+ cy);
-/**
- * Compute box offsets for a relatively or absolutely positioned box with
- * respect to a box.
- *
- * \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
- * \param right updated to right offset, or AUTO
- * \param bottom updated to bottom offset, or AUTO
- * \param left updated to left offset, or AUTO
- *
- * See CSS 2.1 9.3.2. containing_block must have width and height.
- */
-static void
-layout_compute_offsets(struct box *box,
- struct box *containing_block,
- int *top,
- int *right,
- int *bottom,
- int *left)
-{
- uint32_t type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
+ /* find sides at top of line */
+ x0 += cx;
+ x1 += cx;
+ find_sides(cont->float_children, cy, cy, &x0, &x1, &left, &right);
+ x0 -= cx;
+ x1 -= cx;
- assert(containing_block->width != UNKNOWN_WIDTH &&
- containing_block->width != AUTO &&
- containing_block->height != AUTO);
+ if (indent)
+ x0 += layout_text_indent(first->parent->parent->style, *width);
- /* left */
- type = css_computed_left(box->style, &value, &unit);
- if (type == CSS_LEFT_SET) {
- if (unit == CSS_UNIT_PCT) {
- *left = FPCT_OF_INT_TOINT(value,
- containing_block->width);
- } else {
- *left = FIXTOINT(nscss_len2px(value, unit, box->style));
- }
- } else {
- *left = AUTO;
- }
+ if (x1 < x0)
+ x1 = x0;
- /* right */
- type = css_computed_right(box->style, &value, &unit);
- if (type == CSS_RIGHT_SET) {
- if (unit == CSS_UNIT_PCT) {
- *right = FPCT_OF_INT_TOINT(value,
- containing_block->width);
- } else {
- *right = FIXTOINT(nscss_len2px(value, unit,
- box->style));
- }
- } else {
- *right = AUTO;
- }
+ /* get minimum line height from containing block.
+ * 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);
+ else
+ /* inline containers with no text are usually for layout and
+ * look better with no minimum line-height */
+ used_height = height = 0;
- /* top */
- type = css_computed_top(box->style, &value, &unit);
- if (type == CSS_TOP_SET) {
- if (unit == CSS_UNIT_PCT) {
- *top = FPCT_OF_INT_TOINT(value,
- containing_block->height);
- } else {
- *top = FIXTOINT(nscss_len2px(value, unit, box->style));
- }
- } else {
- *top = AUTO;
- }
+ /* pass 1: find height of line assuming sides at top of line: loop
+ * body executed at least once
+ * keep in sync with the loop in layout_minmax_line() */
- /* bottom */
- type = css_computed_bottom(box->style, &value, &unit);
- if (type == CSS_BOTTOM_SET) {
- if (unit == CSS_UNIT_PCT) {
- *bottom = FPCT_OF_INT_TOINT(value,
- containing_block->height);
- } else {
- *bottom = FIXTOINT(nscss_len2px(value, unit,
- box->style));
- }
- } else {
- *bottom = AUTO;
- }
-}
+ NSLOG(layout, DEBUG, "x0 %i, x1 %i, x1 - x0 %i", x0, x1, x1 - x0);
-/**
- * Layout and position an absolutely positioned box.
- *
- * \param box absolute box to layout and position
- * \param containing_block containing block
- * \param cx position of box relative to containing_block
- * \param cy position of box relative to containing_block
- * \param content memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- */
-static bool
-layout_absolute(struct box *box,
- struct box *containing_block,
- int cx, int cy,
- html_content *content)
-{
- int static_left, static_top; /* static position */
- int top, right, bottom, left;
- int width, height, max_width, min_width;
- int *margin = box->margin;
- int *padding = box->padding;
- struct box_border *border = box->border;
- int available_width = containing_block->width;
- int space;
+ for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) {
+ int min_width, max_width, min_height, max_height;
- assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
- box->type == BOX_INLINE_BLOCK);
+ assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_FLOAT_LEFT ||
+ b->type == BOX_FLOAT_RIGHT ||
+ b->type == BOX_BR || b->type == BOX_TEXT ||
+ b->type == BOX_INLINE_END);
- /* The static position is where the box would be if it was not
- * absolutely positioned. The x and y are filled in by
- * layout_block_context(). */
- static_left = cx + box->x;
- static_top = cy + box->y;
- if (containing_block->type == BOX_BLOCK ||
- containing_block->type == BOX_INLINE_BLOCK ||
- containing_block->type == BOX_TABLE_CELL) {
- /* Block level container => temporarily increase containing
- * block dimensions to include padding (we restore this
- * again at the end) */
- containing_block->width += containing_block->padding[LEFT] +
- containing_block->padding[RIGHT];
- containing_block->height += containing_block->padding[TOP] +
- containing_block->padding[BOTTOM];
- } else {
- /** \todo inline containers */
- }
+ NSLOG(layout, DEBUG, "pass 1: b %p, x %i", b, x);
- layout_compute_offsets(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);
- box->float_container = NULL;
+ if (b->type == BOX_BR)
+ break;
- /* 10.3.7 */
- NSLOG(layout, DEBUG,
- "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
- left, margin[LEFT], border[LEFT].width, padding[LEFT], width,
- padding[RIGHT], border[RIGHT].width, margin[RIGHT], right,
- containing_block->width);
+ if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT)
+ continue;
+ if (b->type == BOX_INLINE_BLOCK &&
+ (css_computed_position(b->style) ==
+ CSS_POSITION_ABSOLUTE ||
+ css_computed_position(b->style) ==
+ CSS_POSITION_FIXED))
+ continue;
+ assert(b->style != NULL);
+ font_plot_style_from_css(b->style, &fstyle);
- if (left == AUTO && width == AUTO && right == AUTO) {
- if (margin[LEFT] == AUTO)
- margin[LEFT] = 0;
- if (margin[RIGHT] == AUTO)
- margin[RIGHT] = 0;
- left = static_left;
+ x += space_after;
- width = min(max(box->min_width, available_width),
- box->max_width);
- width -= box->margin[LEFT] + box->border[LEFT].width +
- box->padding[LEFT] + box->padding[RIGHT] +
- box->border[RIGHT].width + box->margin[RIGHT];
-
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width) width = max_width;
- if (width < min_width) width = min_width;
-
- right = containing_block->width -
- left -
- margin[LEFT] - border[LEFT].width - padding[LEFT] -
- width -
- padding[RIGHT] - border[RIGHT].width - margin[RIGHT];
- } else if (left != AUTO && width != AUTO && right != AUTO) {
-
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width) width = max_width;
- if (min_width > 0 && width < min_width) width = min_width;
+ if (b->type == BOX_INLINE_BLOCK) {
+ if (b->max_width != UNKNOWN_WIDTH)
+ if (!layout_float(b, *width, content))
+ return false;
+ h = b->border[TOP].width + b->padding[TOP] + b->height +
+ b->padding[BOTTOM] +
+ b->border[BOTTOM].width;
+ if (height < h)
+ height = h;
+ x += b->margin[LEFT] + b->border[LEFT].width +
+ b->padding[LEFT] + b->width +
+ b->padding[RIGHT] +
+ b->border[RIGHT].width +
+ b->margin[RIGHT];
+ space_after = 0;
+ continue;
+ }
- if (margin[LEFT] == AUTO && margin[RIGHT] == AUTO) {
- space = containing_block->width -
- left - border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - right;
- if (space < 0) {
- margin[LEFT] = 0;
- margin[RIGHT] = space;
+ 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);
+ for (i = 0; i != 4; i++)
+ if (b->margin[i] == AUTO)
+ b->margin[i] = 0;
+ x += b->margin[LEFT] + b->border[LEFT].width +
+ b->padding[LEFT];
+ if (b->inline_end) {
+ b->inline_end->margin[RIGHT] = b->margin[RIGHT];
+ b->inline_end->padding[RIGHT] =
+ b->padding[RIGHT];
+ b->inline_end->border[RIGHT] =
+ b->border[RIGHT];
} else {
- margin[LEFT] = margin[RIGHT] = space / 2;
+ x += b->padding[RIGHT] +
+ b->border[RIGHT].width +
+ b->margin[RIGHT];
}
- } else if (margin[LEFT] == AUTO) {
- margin[LEFT] = containing_block->width -
- left - border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT] -
- right;
- } else if (margin[RIGHT] == AUTO) {
- margin[RIGHT] = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - right;
- } else {
- right = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT];
+ } else if (b->type == BOX_INLINE_END) {
+ b->width = 0;
+ if (b->space == UNKNOWN_WIDTH) {
+ font_func->width(&fstyle, " ", 1, &b->space);
+ /** \todo handle errors */
+ }
+ space_after = b->space;
+
+ x += b->padding[RIGHT] + b->border[RIGHT].width +
+ b->margin[RIGHT];
+ continue;
}
- } else {
- if (margin[LEFT] == AUTO)
- margin[LEFT] = 0;
- if (margin[RIGHT] == AUTO)
- margin[RIGHT] = 0;
- if (left == AUTO && width == AUTO && right != AUTO) {
- available_width -= right;
+ 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->parent->parent->style);
+ if (height < b->height)
+ height = b->height;
- width = min(max(box->min_width, available_width),
- box->max_width);
- width -= box->margin[LEFT] + box->border[LEFT].width +
- box->padding[LEFT] + box->padding[RIGHT] +
- box->border[RIGHT].width + box->margin[RIGHT];
+ if (!b->text) {
+ b->width = 0;
+ space_after = 0;
+ continue;
+ }
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (width < min_width)
- width = min_width;
+ if (b->width == UNKNOWN_WIDTH) {
+ /** \todo handle errors */
- left = containing_block->width -
- margin[LEFT] - border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT] -
- right;
- } else if (left == AUTO && width != AUTO && right == AUTO) {
+ /* If it's a select element, we must use the
+ * width of the widest option text */
+ if (b->parent->parent->gadget &&
+ b->parent->parent->gadget->type
+ == GADGET_SELECT) {
+ int opt_maxwidth = 0;
+ struct form_option *o;
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (min_width > 0 && width < min_width)
- width = min_width;
+ for (o = b->parent->parent->gadget->
+ data.select.items; o;
+ o = o->next) {
+ int opt_width;
+ font_func->width(&fstyle,
+ o->text,
+ strlen(o->text),
+ &opt_width);
- left = static_left;
- right = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT];
- } else if (left != AUTO && width == AUTO && right == AUTO) {
- available_width -= left;
+ if (opt_maxwidth < opt_width)
+ opt_maxwidth =opt_width;
+ }
+ b->width = opt_maxwidth;
+ if (nsoption_bool(core_select_menu))
+ b->width += SCROLLBAR_WIDTH;
+ } else {
+ font_func->width(&fstyle, b->text,
+ b->length, &b->width);
+ b->flags |= MEASURED;
+ }
+ }
- width = min(max(box->min_width, available_width),
- box->max_width);
- width -= box->margin[LEFT] + box->border[LEFT].width +
- box->padding[LEFT] + box->padding[RIGHT] +
- box->border[RIGHT].width + box->margin[RIGHT];
+ /* If the current text has not been measured (i.e. its
+ * width was estimated after splitting), and it fits on
+ * the line, measure it properly, so next box is placed
+ * correctly. */
+ if (b->text && (x + b->width < x1 - x0) &&
+ !(b->flags & MEASURED) &&
+ b->next) {
+ font_func->width(&fstyle, b->text,
+ b->length, &b->width);
+ b->flags |= MEASURED;
+ }
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (width < min_width)
- width = min_width;
+ x += b->width;
+ if (b->space == UNKNOWN_WIDTH) {
+ font_func->width(&fstyle, " ", 1, &b->space);
+ /** \todo handle errors */
+ }
+ space_after = b->space;
+ continue;
+ }
- right = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT];
- } else if (left == AUTO && width != AUTO && right != AUTO) {
+ space_after = 0;
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (width < min_width)
- width = min_width;
+ /* inline replaced, 10.3.2 and 10.6.2 */
+ assert(b->style);
- left = containing_block->width -
- margin[LEFT] - border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT] -
- right;
- } else if (left != AUTO && width == AUTO && right != AUTO) {
- width = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT] -
- right;
+ layout_find_dimensions(*width, -1, b, b->style,
+ &b->width, &b->height, &max_width, &min_width,
+ &max_height, &min_height, NULL, NULL, NULL);
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (width < min_width)
- width = min_width;
+ if (b->object && !(b->flags & REPLACE_DIM)) {
+ layout_get_object_dimensions(b, &b->width, &b->height,
+ min_width, max_width,
+ min_height, max_height);
+ } else if (b->flags & IFRAME) {
+ /* TODO: should we look at the content dimensions? */
+ if (b->width == AUTO)
+ b->width = 400;
+ if (b->height == AUTO)
+ b->height = 300;
- } else if (left != AUTO && width != AUTO && right == AUTO) {
+ /* We reformat the iframe browser window to new
+ * dimensions in pass 2 */
+ } else {
+ /* form control with no object */
+ if (b->width == AUTO)
+ b->width = FIXTOINT(nscss_len2px(INTTOFIX(1),
+ CSS_UNIT_EM, b->style));
+ if (b->height == AUTO)
+ b->height = FIXTOINT(nscss_len2px(INTTOFIX(1),
+ CSS_UNIT_EM, b->style));
+ }
- /* Adjust for {min|max}-width */
- if (max_width >= 0 && width > max_width)
- width = max_width;
- if (width < min_width)
- width = min_width;
+ /* Reformat object to new box size */
+ if (b->object && content_get_type(b->object) == CONTENT_HTML &&
+ b->width !=
+ content_get_available_width(b->object)) {
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+ enum css_height_e htype = css_computed_height(b->style,
+ &value, &unit);
- right = containing_block->width -
- left - margin[LEFT] -
- border[LEFT].width -
- padding[LEFT] - width - padding[RIGHT] -
- border[RIGHT].width - margin[RIGHT];
+ content_reformat(b->object, false, b->width, b->height);
+
+ if (htype == CSS_HEIGHT_AUTO)
+ b->height = content_get_height(b->object);
}
- }
- NSLOG(layout, DEBUG,
- "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
- left, margin[LEFT], border[LEFT].width, padding[LEFT], width,
- padding[RIGHT], border[RIGHT].width, margin[RIGHT], right,
- containing_block->width);
+ if (height < b->height)
+ height = b->height;
- box->x = left + margin[LEFT] + border[LEFT].width - cx;
- if (containing_block->type == BOX_BLOCK ||
- containing_block->type == BOX_INLINE_BLOCK ||
- containing_block->type == BOX_TABLE_CELL) {
- /* Block-level ancestor => reset container's width */
- containing_block->width -= containing_block->padding[LEFT] +
- containing_block->padding[RIGHT];
- } else {
- /** \todo inline ancestors */
+ x += b->width;
}
- box->width = width;
- box->height = height;
- if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->object || box->flags & IFRAME) {
- if (!layout_block_context(box, -1, content))
- return false;
- } else if (box->type == BOX_TABLE) {
- /* layout_table also expects the containing block to be
- * stored in the float_container field */
- box->float_container = containing_block;
- /* \todo layout_table considers margins etc. again */
- if (!layout_table(box, width, content))
- return false;
- box->float_container = NULL;
- layout_solve_width(box, box->parent->width, box->width, 0, 0,
- -1, -1);
- }
+ /* find new sides using this height */
+ x0 = cx;
+ x1 = cx + *width;
+ find_sides(cont->float_children, cy, cy + height, &x0, &x1,
+ &left, &right);
+ x0 -= cx;
+ x1 -= cx;
- /* 10.6.4 */
- NSLOG(layout, DEBUG,
- "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
- top, margin[TOP], border[TOP].width, padding[TOP], height,
- padding[BOTTOM], border[BOTTOM].width, margin[BOTTOM], bottom,
- containing_block->height);
+ if (indent)
+ x0 += layout_text_indent(first->parent->parent->style, *width);
- if (top == AUTO && height == AUTO && bottom == AUTO) {
- top = static_top;
- height = box->height;
- if (margin[TOP] == AUTO)
- margin[TOP] = 0;
- if (margin[BOTTOM] == AUTO)
- margin[BOTTOM] = 0;
- bottom = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height - padding[BOTTOM] -
- border[BOTTOM].width - margin[BOTTOM];
- } else if (top != AUTO && height != AUTO && bottom != AUTO) {
- if (margin[TOP] == AUTO && margin[BOTTOM] == AUTO) {
- space = containing_block->height -
- top - border[TOP].width - padding[TOP] -
- height - padding[BOTTOM] -
- border[BOTTOM].width - bottom;
- margin[TOP] = margin[BOTTOM] = space / 2;
- } else if (margin[TOP] == AUTO) {
- margin[TOP] = containing_block->height -
- top - border[TOP].width - padding[TOP] -
- height - padding[BOTTOM] -
- border[BOTTOM].width - margin[BOTTOM] -
- bottom;
- } else if (margin[BOTTOM] == AUTO) {
- margin[BOTTOM] = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- bottom;
- } else {
- bottom = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM];
- }
- } else {
- if (margin[TOP] == AUTO)
- margin[TOP] = 0;
- if (margin[BOTTOM] == AUTO)
- margin[BOTTOM] = 0;
- if (top == AUTO && height == AUTO && bottom != AUTO) {
- height = box->height;
- top = containing_block->height -
- margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM] - bottom;
- } else if (top == AUTO && height != AUTO && bottom == AUTO) {
- top = static_top;
- bottom = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM];
- } else if (top != AUTO && height == AUTO && bottom == AUTO) {
- height = box->height;
- bottom = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM];
- } else if (top == AUTO && height != AUTO && bottom != AUTO) {
- top = containing_block->height -
- margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM] - bottom;
- } else if (top != AUTO && height == AUTO && bottom != AUTO) {
- height = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - padding[BOTTOM] -
- border[BOTTOM].width - margin[BOTTOM] -
- bottom;
- } else if (top != AUTO && height != AUTO && bottom == AUTO) {
- bottom = containing_block->height -
- top - margin[TOP] - border[TOP].width -
- padding[TOP] - height -
- padding[BOTTOM] - border[BOTTOM].width -
- margin[BOTTOM];
- }
- }
+ if (x1 < x0)
+ x1 = x0;
- NSLOG(layout, DEBUG,
- "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
- top, margin[TOP], border[TOP].width, padding[TOP], height,
- padding[BOTTOM], border[BOTTOM].width, margin[BOTTOM], bottom,
- containing_block->height);
+ space_after = space_before = 0;
- box->y = top + margin[TOP] + border[TOP].width - cy;
- if (containing_block->type == BOX_BLOCK ||
- containing_block->type == BOX_INLINE_BLOCK ||
- containing_block->type == BOX_TABLE_CELL) {
- /* Block-level ancestor => reset container's height */
- containing_block->height -= containing_block->padding[TOP] +
- containing_block->padding[BOTTOM];
- } else {
- /** \todo Inline ancestors */
- }
- box->height = height;
- layout_apply_minmax_height(box, containing_block);
+ /* pass 2: place boxes in line: loop body executed at least once */
- return true;
-}
+ NSLOG(layout, DEBUG, "x0 %i, x1 %i, x1 - x0 %i", x0, x1, x1 - x0);
+ for (x = x_previous = 0, b = first; x <= x1 - x0 && b; b = b->next) {
-/**
- * Recursively layout and position absolutely positioned boxes.
- *
- * \param box tree of boxes to layout
- * \param containing_block current containing block
- * \param cx position of box relative to containing_block
- * \param cy position of box relative to containing_block
- * \param content memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- */
-static bool
-layout_position_absolute(struct box *box,
- struct box *containing_block,
- int cx, int cy,
- html_content *content)
-{
- struct box *c;
+ NSLOG(layout, DEBUG, "pass 2: b %p, x %i", b, x);
- for (c = box->children; c; c = c->next) {
- if ((c->type == BOX_BLOCK || c->type == BOX_TABLE ||
- c->type == BOX_INLINE_BLOCK) &&
- (css_computed_position(c->style) ==
+ if (b->type == BOX_INLINE_BLOCK &&
+ (css_computed_position(b->style) ==
CSS_POSITION_ABSOLUTE ||
- css_computed_position(c->style) ==
+ css_computed_position(b->style) ==
CSS_POSITION_FIXED)) {
- if (!layout_absolute(c, containing_block,
- cx, cy, content))
- return false;
- if (!layout_position_absolute(c, c, 0, 0, content))
- return false;
- } else if (c->style && css_computed_position(c->style) ==
- CSS_POSITION_RELATIVE) {
- if (!layout_position_absolute(c, c, 0, 0, content))
- return false;
- } else {
- int px, py;
- if (c->style && (css_computed_float(c->style) ==
- CSS_FLOAT_LEFT ||
- css_computed_float(c->style) ==
- CSS_FLOAT_RIGHT)) {
- /* Float x/y coords are relative to nearest
- * ansestor with float_children, rather than
- * relative to parent. Need to get x/y relative
- * to parent */
- struct box *p;
- px = c->x;
- py = c->y;
- for (p = box->parent; p && !p->float_children;
- p = p->parent) {
- px -= p->x;
- py -= p->y;
- }
- } else {
- /* Not a float, so box x/y coords are relative
- * to parent */
- px = c->x;
- py = c->y;
- }
- if (!layout_position_absolute(c, containing_block,
- cx + px, cy + py, content))
- return false;
- }
- }
+ b->x = x + space_after;
- return true;
-}
+ } else if (b->type == BOX_INLINE ||
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_TEXT ||
+ b->type == BOX_INLINE_END) {
+ assert(b->width != UNKNOWN_WIDTH);
+ x_previous = x;
+ x += space_after;
+ b->x = x;
-/**
- * Compute a box's relative offset as per CSS 2.1 9.4.3
- *
- * \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)
-{
- int left, right, top, bottom;
- struct box *containing_block;
-
- assert(box && box->parent && box->style &&
- css_computed_position(box->style) ==
- CSS_POSITION_RELATIVE);
-
- if (box->float_container &&
- (css_computed_float(box->style) == CSS_FLOAT_LEFT ||
- css_computed_float(box->style) == CSS_FLOAT_RIGHT)) {
- containing_block = box->float_container;
- } else {
- containing_block = box->parent;
- }
+ if ((b->type == BOX_INLINE && !b->inline_end) ||
+ b->type == BOX_INLINE_BLOCK) {
+ b->x += b->margin[LEFT] + b->border[LEFT].width;
+ x = b->x + b->padding[LEFT] + b->width +
+ b->padding[RIGHT] +
+ b->border[RIGHT].width +
+ b->margin[RIGHT];
+ } else if (b->type == BOX_INLINE) {
+ b->x += b->margin[LEFT] + b->border[LEFT].width;
+ x = b->x + b->padding[LEFT] + b->width;
+ } else if (b->type == BOX_INLINE_END) {
+ b->height = b->inline_end->height;
+ x += b->padding[RIGHT] +
+ b->border[RIGHT].width +
+ b->margin[RIGHT];
+ } else {
+ x += b->width;
+ }
- layout_compute_offsets(box, containing_block,
- &top, &right, &bottom, &left);
+ space_before = space_after;
+ if (b->object || b->flags & REPLACE_DIM ||
+ b->flags & IFRAME)
+ 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);
+ /** \todo handle errors */
+ font_func->width(&fstyle, " ", 1,
+ &b->space);
+ }
+ space_after = b->space;
+ } else {
+ space_after = 0;
+ }
+ split_box = b;
+ move_y = true;
+ inline_count++;
+ } else if (b->type == BOX_BR) {
+ b->x = x;
+ b->width = 0;
+ br_box = b;
+ b = b->next;
+ split_box = 0;
+ move_y = true;
+ break;
- if (left == AUTO && right == AUTO)
- left = right = 0;
- else if (left == AUTO)
- /* left is auto => computed = -right */
- left = -right;
- else if (right == AUTO)
- /* right is auto => computed = -left */
- right = -left;
- else {
- /* over constrained => examine direction property
- * of containing block */
- if (containing_block->style &&
- css_computed_direction(
- containing_block->style) ==
- CSS_DIRECTION_RTL) {
- /* right wins */
- left = -right;
} else {
- /* assume LTR in all other cases */
- right = -left;
- }
- }
+ /* float */
+ NSLOG(layout, DEBUG, "float %p", b);
- assert(left == -right);
+ d = b->children;
+ d->float_children = 0;
+ d->cached_place_below_level = 0;
+ b->float_container = d->float_container = cont;
- if (top == AUTO && bottom == AUTO) {
- top = bottom = 0;
- } else if (top == AUTO) {
- top = -bottom;
- } else {
- /* bottom is AUTO, or neither are AUTO */
- bottom = -top;
- }
+ if (!layout_float(d, *width, content))
+ return false;
- NSLOG(layout, DEBUG, "left %i, right %i, top %i, bottom %i", left,
- right, top, bottom);
+ NSLOG(layout, DEBUG,
+ "%p : %d %d",
+ d,
+ d->margin[TOP],
+ d->border[TOP].width);
- *x = left;
- *y = top;
-}
+ d->x = d->margin[LEFT] + d->border[LEFT].width;
+ d->y = d->margin[TOP] + d->border[TOP].width;
+ b->width = d->margin[LEFT] + d->border[LEFT].width +
+ d->padding[LEFT] + d->width +
+ d->padding[RIGHT] +
+ d->border[RIGHT].width +
+ d->margin[RIGHT];
+ b->height = d->margin[TOP] + d->border[TOP].width +
+ d->padding[TOP] + d->height +
+ d->padding[BOTTOM] +
+ d->border[BOTTOM].width +
+ d->margin[BOTTOM];
+ if (b->width > (x1 - x0) - x)
+ place_below = true;
+ if (d->style && (css_computed_clear(d->style) ==
+ CSS_CLEAR_NONE ||
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_LEFT && left == 0) ||
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_RIGHT &&
+ right == 0) ||
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_BOTH &&
+ left == 0 && right == 0)) &&
+ (!place_below ||
+ (left == 0 && right == 0 && x == 0)) &&
+ cy >= cont->clear_level &&
+ cy >= cont->cached_place_below_level) {
+ /* + not cleared or,
+ * cleared and there are no floats to clear
+ * + fits without needing to be placed below or,
+ * this line is empty with no floats
+ * + current y, cy, is below the clear level
+ *
+ * Float affects current line */
+ if (b->type == BOX_FLOAT_LEFT) {
+ b->x = cx + x0;
+ if (b->width > 0)
+ x0 += b->width;
+ left = b;
+ } else {
+ b->x = cx + x1 - b->width;
+ if (b->width > 0)
+ x1 -= b->width;
+ right = b;
+ }
+ b->y = cy;
+ } else {
+ /* cleared or doesn't fit on line */
+ /* place below into next available space */
+ int fcy = (cy > cont->clear_level) ? cy :
+ cont->clear_level;
+ fcy = (fcy > cont->cached_place_below_level) ?
+ fcy :
+ cont->cached_place_below_level;
+ fy = (fy > fcy) ? fy : fcy;
+ fy = (fy == cy) ? fy + height : fy;
-/**
- * Adjust positions of relatively positioned boxes.
- *
- * \param root box to adjust the position of
- * \param fp box which forms the block formatting context for children of
- * "root" which are floats
- * \param fx x offset due to intervening relatively positioned boxes
- * between current box, "root", and the block formatting context
- * box, "fp", for float children of "root"
- * \param fy y offset due to intervening relatively positioned boxes
- * between current box, "root", and the block formatting context
- * box, "fp", for float children of "root"
- */
-static void
-layout_position_relative(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
- * "box" */
- struct box *fc; /* for float children of the block formatting context,
- * "fp" */
- int x, y; /* for the offsets resulting from any relative
- * positioning on the current block */
- int fnx, fny; /* for affsets which apply to flat children of "box" */
+ place_float_below(b, *width, cx, fy, cont);
+ fy = b->y;
+ if (d->style && (
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_LEFT && left != 0) ||
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_RIGHT &&
+ right != 0) ||
+ (css_computed_clear(d->style) ==
+ CSS_CLEAR_BOTH &&
+ (left != 0 || right != 0)))) {
+ /* to be cleared below existing
+ * floats */
+ if (b->type == BOX_FLOAT_LEFT)
+ b->x = cx;
+ else
+ b->x = cx + *width - b->width;
- /**\todo ensure containing box is large enough after moving boxes */
+ fcy = layout_clear(cont->float_children,
+ css_computed_clear(d->style));
+ if (fcy > cont->clear_level)
+ cont->clear_level = fcy;
+ if (b->y < fcy)
+ b->y = fcy;
+ }
+ if (b->type == BOX_FLOAT_LEFT)
+ left = b;
+ else
+ right = b;
+ }
+ add_float_to_container(cont, b);
- assert(root);
+ split_box = 0;
+ }
+ }
- /* Normal children */
- for (box = root->children; box; box = box->next) {
+ if (x1 - x0 < x && split_box) {
+ /* the last box went over the end */
+ size_t split = 0;
+ int w;
+ bool no_wrap = css_computed_white_space(
+ split_box->style) == CSS_WHITE_SPACE_NOWRAP ||
+ css_computed_white_space(
+ split_box->style) == CSS_WHITE_SPACE_PRE;
- if (box->type == BOX_TEXT)
- continue;
+ x = x_previous;
- /* If relatively positioned, get offsets */
- if (box->style && css_computed_position(box->style) ==
- CSS_POSITION_RELATIVE)
- layout_compute_relative_offset(box, &x, &y);
- else
- x = y = 0;
+ if (!no_wrap &&
+ (split_box->type == BOX_INLINE ||
+ split_box->type == BOX_TEXT) &&
+ !split_box->object &&
+ !(split_box->flags & REPLACE_DIM) &&
+ !(split_box->flags & IFRAME) &&
+ !split_box->gadget && split_box->text) {
- /* Adjust float coordinates.
- * (note float x and y are relative to their block formatting
- * context box and not their parent) */
- if (box->style && (css_computed_float(box->style) ==
- CSS_FLOAT_LEFT ||
- css_computed_float(box->style) ==
- CSS_FLOAT_RIGHT) &&
- (fx != 0 || fy != 0)) {
- /* box is a float and there is a float offset to
- * apply */
- for (fc = fp->float_children; fc; fc = fc->next_float) {
- if (box == fc->children) {
- /* Box is floated in the block
- * formatting context block, fp.
- * Apply float offsets. */
- box->x += fx;
- box->y += fy;
- fx = fy = 0;
- }
- }
+ font_plot_style_from_css(split_box->style, &fstyle);
+ /** \todo handle errors */
+ font_func->split(&fstyle,
+ split_box->text,
+ split_box->length,
+ x1 - x0 - x - space_before,
+ &split,
+ &w);
}
- if (box->float_children) {
- fn = box;
- fnx = fny = 0;
- } else {
- fn = fp;
- fnx = fx + x;
- fny = fy + y;
- }
+ /* split == 0 implies that text can't be split */
- /* recurse first */
- layout_position_relative(box, fn, fnx, fny);
+ if (split == 0)
+ w = split_box->width;
- /* Ignore things we're not interested in. */
- if (!box->style || (box->style &&
- css_computed_position(box->style) !=
- CSS_POSITION_RELATIVE))
- continue;
- box->x += x;
- box->y += y;
+ NSLOG(layout, DEBUG,
+ "splitting: split_box %p \"%.*s\", spilt %zu, w %i, "
+ "left %p, right %p, inline_count %u",
+ split_box,
+ (int)split_box->length,
+ split_box->text,
+ split,
+ w,
+ left,
+ right,
+ inline_count);
- /* Handle INLINEs - their "children" are in fact
- * the sibling boxes between the INLINE and
- * INLINE_END boxes */
- if (box->type == BOX_INLINE && box->inline_end) {
- struct box *b;
- for (b = box->next; b && b != box->inline_end;
- b = b->next) {
- b->x += x;
- b->y += y;
+ if ((split == 0 || x1 - x0 <= x + space_before + w) &&
+ !left && !right && inline_count == 1) {
+ /* first word of box doesn't fit, but no floats and
+ * first box on line so force in */
+ if (split == 0 || split == split_box->length) {
+ /* only one word in this box, or not text
+ * or white-space:nowrap */
+ b = split_box->next;
+ } else {
+ /* cut off first word for this line */
+ if (!layout_text_box_split(content, &fstyle,
+ split_box, split, w))
+ return false;
+ b = split_box->next;
}
- }
- }
-}
+ x += space_before + w;
+ NSLOG(layout, DEBUG, "forcing");
-/* exported function documented in render/layout.h */
-bool layout_document(html_content *content, int width, int height)
-{
- bool ret;
- struct box *doc = content->layout;
- const struct gui_layout_table *font_func = content->font_func;
+ } else if ((split == 0 || x1 - x0 <= x + space_before + w) &&
+ inline_count == 1) {
+ /* first word of first box doesn't fit, but a float is
+ * taking some of the width so move below it */
+ assert(left || right);
+ used_height = 0;
+ if (left) {
- layout_minmax_block(doc, font_func);
+ NSLOG(layout, DEBUG,
+ "cy %i, left->y %i, left->height %i",
+ cy,
+ left->y,
+ left->height);
- layout_block_find_dimensions(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 +
- doc->padding[LEFT] + doc->padding[RIGHT] +
- doc->border[RIGHT].width + doc->margin[RIGHT];
- if (width < 0) {
- width = 0;
- }
- doc->width = width;
+ used_height = left->y + left->height - cy + 1;
- ret = layout_block_context(doc, height, content);
+ NSLOG(layout, DEBUG, "used_height %i",
+ used_height);
- /* make <html> and <body> fill available height */
- if (doc->y + doc->padding[TOP] + doc->height + doc->padding[BOTTOM] +
- doc->border[BOTTOM].width + doc->margin[BOTTOM] <
- height) {
- doc->height = height - (doc->y + doc->padding[TOP] +
- doc->padding[BOTTOM] +
- doc->border[BOTTOM].width +
- doc->margin[BOTTOM]);
- if (doc->children)
- doc->children->height = doc->height -
- (doc->children->margin[TOP] +
- doc->children->border[TOP].width +
- doc->children->padding[TOP] +
- doc->children->padding[BOTTOM] +
- doc->children->border[BOTTOM].width +
- doc->children->margin[BOTTOM]);
- }
+ }
+ if (right && used_height <
+ right->y + right->height - cy + 1)
+ used_height = right->y + right->height - cy + 1;
- layout_lists(doc, font_func);
- layout_position_absolute(doc, doc, 0, 0, content);
- layout_position_relative(doc, doc, 0, 0);
+ if (used_height < 0)
+ used_height = 0;
- layout_calculate_descendant_bboxes(doc);
+ b = split_box;
- return ret;
-}
+ NSLOG(layout, DEBUG, "moving below float");
+ } else if (split == 0 || x1 - x0 <= x + space_before + w) {
+ /* first word of box doesn't fit so leave box for next
+ * line */
+ b = split_box;
-/**
- * Insert a float into a container.
- *
- * \param cont block formatting context block, used to contain float
- * \param b box to add to float
- *
- * This sorts floats in order of descending bottom edges.
- */
-static void add_float_to_container(struct box *cont, struct box *b)
-{
- struct box *box = cont->float_children;
- int b_bottom = b->y + b->height;
+ NSLOG(layout, DEBUG, "leaving for next line");
- assert(b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT);
+ } else {
+ /* fit as many words as possible */
+ assert(split != 0);
- if (box == NULL) {
- /* No other float children */
- b->next_float = NULL;
- cont->float_children = b;
- return;
- } else if (b_bottom >= box->y + box->height) {
- /* Goes at start of list */
- b->next_float = cont->float_children;
- cont->float_children = b;
- } else {
- struct box *prev = NULL;
- while (box != NULL && b_bottom < box->y + box->height) {
- prev = box;
- box = box->next_float;
- }
- if (prev != NULL) {
- b->next_float = prev->next_float;
- prev->next_float = b;
- }
- }
-}
+ NSLOG(layout, DEBUG, "'%.*s' %i %zu %i",
+ (int)split_box->length, split_box->text,
+ x1 - x0, split, w);
+ if (split != split_box->length) {
+ if (!layout_text_box_split(content, &fstyle,
+ split_box, split, w))
+ return false;
+ b = split_box->next;
+ }
+ x += space_before + w;
-/**
- * Split a text box.
- *
- * \param content memory pool for any new boxes
- * \param fstyle style for text in text box
- * \param split_box box with text to split
- * \param new_length new length for text in split_box, after splitting
- * \param new_width new width for text in split_box, after splitting
- * \return true on success, false on memory exhaustion
- *
- * A new box is created and inserted into the box tree after split_box,
- * containing the text after new_length excluding the initial space character.
- */
-static bool
-layout_text_box_split(html_content *content,
- plot_font_style_t *fstyle,
- struct box *split_box,
- size_t new_length,
- int new_width)
-{
- int space_width = split_box->space;
- struct box *c2;
- const struct gui_layout_table *font_func = content->font_func;
- bool space = (split_box->text[new_length] == ' ');
- int used_length = new_length + (space ? 1 : 0);
+ NSLOG(layout, DEBUG, "fitting words");
- if ((space && space_width == 0) || space_width == UNKNOWN_WIDTH) {
- /* We're need to add a space, and we don't know how big
- * it's to be, OR we have a space of unknown width anyway;
- * Calculate space width */
- font_func->width(fstyle, " ", 1, &space_width);
+ }
+ move_y = true;
}
- if (split_box->space == UNKNOWN_WIDTH)
- split_box->space = space_width;
- if (!space)
- space_width = 0;
-
- /* Create clone of split_box, c2 */
- c2 = talloc_memdup(content->bctx, split_box, sizeof *c2);
- if (!c2)
- return false;
- c2->flags |= CLONE;
-
- /* Set remaining text in c2 */
- c2->text += used_length;
-
- /* Set c2 according to the remaining text */
- c2->width -= new_width + space_width;
- c2->flags &= ~MEASURED; /* width has been estimated */
- c2->length = split_box->length - used_length;
-
- /* Update split_box for its reduced text */
- split_box->width = new_width;
- split_box->flags |= MEASURED;
- split_box->length = new_length;
- split_box->space = space_width;
+ /* set positions */
+ switch (css_computed_text_align(first->parent->parent->style)) {
+ case CSS_TEXT_ALIGN_RIGHT:
+ case CSS_TEXT_ALIGN_LIBCSS_RIGHT:
+ x0 = x1 - x;
+ break;
+ case CSS_TEXT_ALIGN_CENTER:
+ case CSS_TEXT_ALIGN_LIBCSS_CENTER:
+ x0 = (x0 + (x1 - x)) / 2;
+ break;
+ case CSS_TEXT_ALIGN_LEFT:
+ case CSS_TEXT_ALIGN_LIBCSS_LEFT:
+ case CSS_TEXT_ALIGN_JUSTIFY:
+ /* leave on left */
+ break;
+ case CSS_TEXT_ALIGN_DEFAULT:
+ /* None; consider text direction */
+ switch (css_computed_direction(first->parent->parent->style)) {
+ case CSS_DIRECTION_LTR:
+ /* leave on left */
+ break;
+ case CSS_DIRECTION_RTL:
+ x0 = x1 - x;
+ break;
+ }
+ break;
+ }
- /* Insert c2 into box list */
- c2->next = split_box->next;
- split_box->next = c2;
- c2->prev = split_box;
- if (c2->next)
- c2->next->prev = c2;
- else
- c2->parent->last = c2;
+ for (d = first; d != b; d = d->next) {
+ d->flags &= ~NEW_LINE;
- NSLOG(layout, DEBUG,
- "split_box %p len: %" PRIsizet " \"%.*s\"",
- split_box,
- split_box->length,
- (int)split_box->length,
- split_box->text);
- NSLOG(layout, DEBUG,
- " new_box %p len: %" PRIsizet " \"%.*s\"",
- c2,
- c2->length,
- (int)c2->length,
- c2->text);
+ if (d->type == BOX_INLINE_BLOCK &&
+ (css_computed_position(d->style) ==
+ CSS_POSITION_ABSOLUTE ||
+ css_computed_position(d->style) ==
+ CSS_POSITION_FIXED)) {
+ /* positioned inline-blocks:
+ * set static position (x,y) only, rest of positioning
+ * is handled later */
+ d->x += x0;
+ d->y = *y;
+ continue;
+ } else if ((d->type == BOX_INLINE &&
+ ((d->object || d->gadget) == false) &&
+ !(d->flags & IFRAME) &&
+ !(d->flags & REPLACE_DIM)) ||
+ d->type == BOX_BR ||
+ d->type == BOX_TEXT ||
+ d->type == BOX_INLINE_END) {
+ /* regular (non-replaced) inlines */
+ d->x += x0;
+ d->y = *y - d->padding[TOP];
+
+ if (d->type == BOX_TEXT && d->height > used_height) {
+ /* text */
+ used_height = d->height;
+ }
+ } else if ((d->type == BOX_INLINE) ||
+ d->type == BOX_INLINE_BLOCK) {
+ /* replaced inlines and inline-blocks */
+ d->x += x0;
+ d->y = *y + d->border[TOP].width + d->margin[TOP];
+ h = d->margin[TOP] + d->border[TOP].width +
+ d->padding[TOP] + d->height +
+ d->padding[BOTTOM] +
+ d->border[BOTTOM].width +
+ d->margin[BOTTOM];
+ if (used_height < h)
+ used_height = h;
+ }
+ }
+
+ first->flags |= NEW_LINE;
+
+ assert(b != first || (move_y && 0 < used_height && (left || right)));
+
+ /* handle vertical-align by adjusting box y values */
+ /** \todo proper vertical alignment handling */
+ for (d = first; d != b; d = d->next) {
+ if ((d->type == BOX_INLINE && d->inline_end) ||
+ d->type == BOX_BR ||
+ d->type == BOX_TEXT ||
+ d->type == BOX_INLINE_END) {
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+ switch (css_computed_vertical_align(d->style, &value,
+ &unit)) {
+ case CSS_VERTICAL_ALIGN_SUPER:
+ case CSS_VERTICAL_ALIGN_TOP:
+ case CSS_VERTICAL_ALIGN_TEXT_TOP:
+ /* already at top */
+ break;
+ case CSS_VERTICAL_ALIGN_SUB:
+ case CSS_VERTICAL_ALIGN_BOTTOM:
+ case CSS_VERTICAL_ALIGN_TEXT_BOTTOM:
+ d->y += used_height - d->height;
+ break;
+ default:
+ case CSS_VERTICAL_ALIGN_BASELINE:
+ d->y += 0.75 * (used_height - d->height);
+ break;
+ }
+ }
+ }
+
+ /* handle clearance for br */
+ if (br_box && css_computed_clear(br_box->style) != CSS_CLEAR_NONE) {
+ int clear_y = layout_clear(cont->float_children,
+ css_computed_clear(br_box->style));
+ if (used_height < clear_y - cy)
+ used_height = clear_y - cy;
+ }
+ if (move_y)
+ *y += used_height;
+ *next_box = b;
+ *width = x; /* return actual width */
return true;
}
/**
- * Compute dimensions of box, margins, paddings, and borders for a floating
- * element using shrink-to-fit. Also used for inline-blocks.
+ * Layout lines of text or inline boxes with floats.
*
- * \param available_width Max width available in pixels
- * \param style Box's style
- * \param box Box for which to find dimensions
- * Box margins, borders, paddings, width and
- * height are updated.
+ * \param box inline container box
+ * \param width horizontal space available
+ * \param cont ancestor box which defines horizontal space, for floats
+ * \param cx box position relative to cont
+ * \param cy box position relative to cont
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
*/
-static void
-layout_float_find_dimensions(int available_width,
- const css_computed_style *style,
- struct box *box)
+static bool layout_inline_container(struct box *inline_container, int width,
+ struct box *cont, int cx, int cy, html_content *content)
{
- int width, height, max_width, min_width, max_height, min_height;
- int *margin = box->margin;
- int *padding = box->padding;
- struct box_border *border = box->border;
- enum css_overflow_e overflow_x = css_computed_overflow_x(style);
- enum css_overflow_e overflow_y = css_computed_overflow_y(style);
- int scrollbar_width_x =
- (overflow_x == CSS_OVERFLOW_SCROLL ||
- overflow_x == CSS_OVERFLOW_AUTO) ?
- SCROLLBAR_WIDTH : 0;
- int scrollbar_width_y =
- (overflow_y == CSS_OVERFLOW_SCROLL ||
- overflow_y == CSS_OVERFLOW_AUTO) ?
- SCROLLBAR_WIDTH : 0;
+ bool first_line = true;
+ bool has_text_children;
+ struct box *c, *next;
+ int y = 0;
+ int curwidth,maxwidth = width;
- layout_find_dimensions(available_width, -1, box, style, &width, &height,
- &max_width, &min_width, &max_height, &min_height,
- margin, padding, border);
+ assert(inline_container->type == BOX_INLINE_CONTAINER);
- if (margin[LEFT] == AUTO)
- margin[LEFT] = 0;
- if (margin[RIGHT] == AUTO)
- margin[RIGHT] = 0;
+ NSLOG(layout, DEBUG,
+ "inline_container %p, width %i, cont %p, cx %i, cy %i",
+ inline_container,
+ width,
+ cont,
+ cx,
+ cy);
- if (box->gadget == NULL) {
- padding[RIGHT] += scrollbar_width_y;
- padding[BOTTOM] += scrollbar_width_x;
- }
- if (box->object && !(box->flags & REPLACE_DIM) &&
- content_get_type(box->object) != CONTENT_HTML) {
- /* Floating replaced element, with intrinsic width or height.
- * See 10.3.6 and 10.6.2 */
- layout_get_object_dimensions(box, &width, &height,
- min_width, max_width, min_height, max_height);
- } else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_FILE ||
- box->gadget->type == GADGET_TEXTAREA)) {
- css_fixed size = 0;
- css_unit unit = CSS_UNIT_EM;
+ has_text_children = false;
+ for (c = inline_container->children; c; c = c->next) {
+ bool is_pre = false;
- /* Give sensible dimensions to gadgets, with auto width/height,
- * that don't shrink to fit contained text. */
- assert(box->style);
+ if (c->style) {
+ enum css_white_space_e whitespace;
- if (box->gadget->type == GADGET_TEXTBOX ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_FILE) {
- if (width == AUTO) {
- size = INTTOFIX(10);
- width = FIXTOINT(nscss_len2px(size, unit,
- box->style));
- }
- if (box->gadget->type == GADGET_FILE &&
- height == AUTO) {
- size = FLTTOFIX(1.5);
- height = FIXTOINT(nscss_len2px(size, unit,
- box->style));
- }
- }
- if (box->gadget->type == GADGET_TEXTAREA) {
- if (width == AUTO) {
- size = INTTOFIX(10);
- width = FIXTOINT(nscss_len2px(size, unit,
- box->style));
- }
- if (height == AUTO) {
- size = INTTOFIX(4);
- height = FIXTOINT(nscss_len2px(size, unit,
- box->style));
- }
+ whitespace = css_computed_white_space(c->style);
+
+ is_pre = (whitespace == CSS_WHITE_SPACE_PRE ||
+ whitespace == CSS_WHITE_SPACE_PRE_LINE ||
+ whitespace == CSS_WHITE_SPACE_PRE_WRAP);
}
- } else if (width == AUTO) {
- /* CSS 2.1 section 10.3.5 */
- width = min(max(box->min_width, available_width),
- box->max_width);
- /* width includes margin, borders and padding */
- if (width == available_width) {
- width -= box->margin[LEFT] + box->border[LEFT].width +
- box->padding[LEFT] +
- box->padding[RIGHT] +
- box->border[RIGHT].width +
- box->margin[RIGHT];
- } else {
- /* width was obtained from a min_width or max_width
- * value, so need to use the same method for calculating
- * 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);
- if (fixed < 0)
- fixed = 0;
+ if ((!c->object && !(c->flags & REPLACE_DIM) &&
+ !(c->flags & IFRAME) &&
+ c->text && (c->length || is_pre)) ||
+ c->type == BOX_BR)
+ has_text_children = true;
+ }
- width -= fixed;
- }
+ /** \todo fix wrapping so that a box with horizontal scrollbar will
+ * shrink back to 'width' if no word is wider than 'width' (Or just set
+ * curwidth = width and have the multiword lines wrap to the min width)
+ */
+ for (c = inline_container->children; c; ) {
- if (max_width >= 0 && width > max_width) width = max_width;
- if (min_width > 0 && width < min_width) width = min_width;
+ NSLOG(layout, DEBUG, "c %p", c);
- } else {
- if (max_width >= 0 && width > max_width) width = max_width;
- if (min_width > 0 && width < min_width) width = min_width;
- width -= scrollbar_width_y;
+ curwidth = inline_container->width;
+ if (!layout_line(c, &curwidth, &y, cx, cy + y, cont, first_line,
+ has_text_children, content, &next))
+ return false;
+ maxwidth = max(maxwidth,curwidth);
+ c = next;
+ first_line = false;
}
- box->width = width;
- box->height = height;
+ inline_container->width = maxwidth;
+ inline_container->height = y;
- if (margin[TOP] == AUTO)
- margin[TOP] = 0;
- if (margin[BOTTOM] == AUTO)
- margin[BOTTOM] = 0;
+ return true;
}
/**
- * Layout the contents of a float or inline block.
+ * Layout a block formatting context.
*
- * \param b float or inline block box
- * \param width available width
- * \param content memory pool for any new boxes
+ * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
+ * \param viewport_height Height of viewport in pixels or -ve if unknown
+ * \param content Memory pool for any new boxes
* \return true on success, false on memory exhaustion
- */
-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);
- if (b->type == BOX_TABLE) {
- if (!layout_table(b, width, content))
- return false;
- if (b->margin[LEFT] == AUTO)
- b->margin[LEFT] = 0;
- if (b->margin[RIGHT] == AUTO)
- b->margin[RIGHT] = 0;
- if (b->margin[TOP] == AUTO)
- b->margin[TOP] = 0;
- if (b->margin[BOTTOM] == AUTO)
- b->margin[BOTTOM] = 0;
- } else
- return layout_block_context(b, -1, content);
- return true;
-}
-
-
-/**
- * Position a float in the first available space.
*
- * \param c float box to position
- * \param width available width
- * \param cx x coordinate relative to cont to place float right of
- * \param y y coordinate relative to cont to place float below
- * \param cont ancestor box which defines horizontal space, for floats
+ * This function carries out layout of a block and its children, as described
+ * in CSS 2.1 9.4.1.
*/
-static void
-place_float_below(struct box *c, int width, int cx, int y, struct box *cont)
+static bool
+layout_block_context(struct box *block,
+ int viewport_height,
+ html_content *content)
{
- int x0, x1, yy;
- struct box *left;
- struct box *right;
-
- yy = y > cont->cached_place_below_level ?
- y : cont->cached_place_below_level;
+ struct box *box;
+ int cx, cy; /**< current coordinates */
+ int max_pos_margin = 0;
+ int max_neg_margin = 0;
+ int y = 0;
+ int lm, rm;
+ struct box *margin_collapse = NULL;
+ bool in_margin = false;
+ css_fixed gadget_size;
+ css_unit gadget_unit; /* Checkbox / radio buttons */
- NSLOG(layout, DEBUG,
- "c %p, width %i, cx %i, y %i, cont %p", c,
- width, cx, y, cont);
+ assert(block->type == BOX_BLOCK ||
+ block->type == BOX_INLINE_BLOCK ||
+ block->type == BOX_TABLE_CELL);
+ assert(block->width != UNKNOWN_WIDTH);
+ assert(block->width != AUTO);
- do {
- y = yy;
- x0 = cx;
- x1 = cx + width;
- find_sides(cont->float_children, y, y + c->height, &x0, &x1,
- &left, &right);
- if (left != 0 && right != 0) {
- yy = (left->y + left->height <
- right->y + right->height ?
- left->y + left->height :
- right->y + right->height);
- } else if (left == 0 && right != 0) {
- yy = right->y + right->height;
- } else if (left != 0 && right == 0) {
- yy = left->y + left->height;
- }
- } while ((left != 0 || right != 0) && (c->width > x1 - x0));
+ block->float_children = NULL;
+ block->cached_place_below_level = 0;
+ block->clear_level = 0;
- if (c->type == BOX_FLOAT_LEFT) {
- c->x = x0;
- } else {
- c->x = x1 - c->width;
+ /* special case if the block contains an object */
+ if (block->object) {
+ int temp_width = block->width;
+ if (!layout_block_object(block))
+ return false;
+ layout_get_object_dimensions(block, &temp_width,
+ &block->height, INT_MIN, INT_MAX,
+ INT_MIN, INT_MAX);
+ return true;
+ } else if (block->flags & REPLACE_DIM) {
+ return true;
}
- c->y = y;
- cont->cached_place_below_level = y;
-}
+ /* special case if the block contains an radio button or checkbox */
+ if (block->gadget && (block->gadget->type == GADGET_RADIO ||
+ block->gadget->type == GADGET_CHECKBOX)) {
+ /* form checkbox or radio button
+ * if width or height is AUTO, set it to 1em */
+ gadget_unit = CSS_UNIT_EM;
+ gadget_size = INTTOFIX(1);
+ if (block->height == AUTO)
+ block->height = FIXTOINT(nscss_len2px(gadget_size,
+ gadget_unit, block->style));
+ }
-/**
- * Position a line of boxes in inline formatting context.
- *
- * \param first box at start of line
- * \param width available width on input, updated with actual width on output
- * (may be incorrect if the line gets split?)
- * \param y coordinate of top of line, updated on exit to bottom
- * \param cx coordinate of left of line relative to cont
- * \param cy coordinate of top of line relative to cont
- * \param cont ancestor box which defines horizontal space, for floats
- * \param indent apply any first-line indent
- * \param has_text_children at least one TEXT in the inline_container
- * \param next_box updated to first box for next line, or 0 at end
- * \param content memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- */
-static bool
-layout_line(struct box *first,
- int *width,
- int *y,
- int cx,
- int cy,
- struct box *cont,
- bool indent,
- bool has_text_children,
- html_content *content,
- struct box **next_box)
-{
- int height, used_height;
- int x0 = 0;
- int x1 = *width;
- int x, h, x_previous;
- int fy = cy;
- struct box *left;
- struct box *right;
- struct box *b;
- struct box *split_box = 0;
- struct box *d;
- struct box *br_box = 0;
- bool move_y = false;
- bool place_below = false;
- int space_before = 0, space_after = 0;
- unsigned int inline_count = 0;
- unsigned int i;
- const struct gui_layout_table *font_func = content->font_func;
- plot_font_style_t fstyle;
+ box = block->children;
+ /* set current coordinates to top-left of the block */
+ cx = 0;
+ y = cy = block->padding[TOP];
+ if (box)
+ box->y = block->padding[TOP];
- NSLOG(layout, DEBUG,
- "first %p, first->text '%.*s', width %i, y %i, cx %i, cy %i",
- first,
- (int)first->length,
- first->text,
- *width,
- *y,
- cx,
- cy);
+ /* Step through the descendants of the block in depth-first order, but
+ * not into the children of boxes which aren't blocks. For example, if
+ * the tree passed to this function looks like this (box->type shown):
+ *
+ * block -> BOX_BLOCK
+ * BOX_BLOCK * (1)
+ * BOX_INLINE_CONTAINER * (2)
+ * BOX_INLINE
+ * BOX_TEXT
+ * ...
+ * BOX_BLOCK * (3)
+ * BOX_TABLE * (4)
+ * BOX_TABLE_ROW
+ * BOX_TABLE_CELL
+ * ...
+ * BOX_TABLE_CELL
+ * ...
+ * BOX_BLOCK * (5)
+ * BOX_INLINE_CONTAINER * (6)
+ * BOX_TEXT
+ * ...
+ * then the while loop will visit each box marked with *, setting box
+ * to each in the order shown. */
+ while (box) {
+ enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
+ enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
- /* find sides at top of line */
- x0 += cx;
- x1 += cx;
- find_sides(cont->float_children, cy, cy, &x0, &x1, &left, &right);
- x0 -= cx;
- x1 -= cx;
+ assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
+ box->type == BOX_INLINE_CONTAINER);
- if (indent)
- x0 += layout_text_indent(first->parent->parent->style, *width);
+ /* Tables are laid out before being positioned, because the
+ * position depends on the width which is calculated in
+ * table layout. Blocks and inline containers are positioned
+ * before being laid out, because width is not dependent on
+ * content, and the position is required during layout for
+ * correct handling of floats.
+ */
- if (x1 < x0)
- x1 = x0;
+ if (box->style &&
+ (css_computed_position(box->style) ==
+ CSS_POSITION_ABSOLUTE ||
+ css_computed_position(box->style) ==
+ CSS_POSITION_FIXED)) {
+ box->x = box->parent->padding[LEFT];
+ /* absolute positioned; this element will establish
+ * its own block context when it gets laid out later,
+ * so no need to look at its children now. */
+ goto advance_to_next_box;
+ }
- /* get minimum line height from containing block.
- * 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);
- else
- /* inline containers with no text are usually for layout and
- * look better with no minimum line-height */
- used_height = height = 0;
+ /* 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,
+ viewport_height,
+ &max_pos_margin, &max_neg_margin);
+ /* We have a margin that has not yet been applied. */
+ in_margin = true;
+ }
- /* pass 1: find height of line assuming sides at top of line: loop
- * body executed at least once
- * keep in sync with the loop in layout_minmax_line() */
+ /* Clearance. */
+ y = 0;
+ if (box->style && css_computed_clear(box->style) !=
+ CSS_CLEAR_NONE)
+ y = layout_clear(block->float_children,
+ css_computed_clear(box->style));
- NSLOG(layout, DEBUG, "x0 %i, x1 %i, x1 - x0 %i", x0, x1, x1 - x0);
+ /* Find box's overflow properties */
+ if (box->style) {
+ overflow_x = css_computed_overflow_x(box->style);
+ overflow_y = css_computed_overflow_y(box->style);
+ }
+ /* Blocks establishing a block formatting context get minimum
+ * left and right margins to avoid any floats. */
+ lm = rm = 0;
- for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) {
- int min_width, max_width, min_height, max_height;
+ if (box->type == BOX_BLOCK || box->flags & IFRAME) {
+ if (!box->object && !(box->flags & IFRAME) &&
+ !(box->flags & REPLACE_DIM) &&
+ box->style &&
+ (overflow_x != CSS_OVERFLOW_VISIBLE ||
+ overflow_y != CSS_OVERFLOW_VISIBLE)) {
+ /* box establishes new block formatting context
+ * so available width may be diminished due to
+ * floats. */
+ int x0, x1, top;
+ struct box *left, *right;
+ top = cy + max_pos_margin - max_neg_margin;
+ top = (top > y) ? top : y;
+ x0 = cx;
+ x1 = cx + box->parent->width -
+ box->parent->padding[LEFT] -
+ box->parent->padding[RIGHT];
+ find_sides(block->float_children, top, top,
+ &x0, &x1, &left, &right);
+ /* calculate min required left & right margins
+ * needed to avoid floats */
+ lm = x0 - cx;
+ rm = cx + box->parent->width -
+ box->parent->padding[LEFT] -
+ box->parent->padding[RIGHT] -
+ x1;
+ }
+ layout_block_find_dimensions(box->parent->width,
+ viewport_height, lm, rm, box);
+ if (box->type == BOX_BLOCK && !(box->flags & IFRAME)) {
+ layout_block_add_scrollbar(box, RIGHT);
+ layout_block_add_scrollbar(box, BOTTOM);
+ }
+ } else if (box->type == BOX_TABLE) {
+ if (box->style != NULL) {
+ enum css_width_e wtype;
+ css_fixed width = 0;
+ css_unit unit = CSS_UNIT_PX;
- assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
- b->type == BOX_FLOAT_LEFT ||
- b->type == BOX_FLOAT_RIGHT ||
- b->type == BOX_BR || b->type == BOX_TEXT ||
- b->type == BOX_INLINE_END);
+ wtype = css_computed_width(box->style, &width,
+ &unit);
+
+ if (wtype == CSS_WIDTH_AUTO) {
+ /* max available width may be
+ * diminished due to floats. */
+ int x0, x1, top;
+ struct box *left, *right;
+ top = cy + max_pos_margin -
+ max_neg_margin;
+ top = (top > y) ? top : y;
+ x0 = cx;
+ x1 = cx + box->parent->width -
+ box->parent->padding[LEFT] -
+ box->parent->padding[RIGHT];
+ find_sides(block->float_children,
+ top, top, &x0, &x1,
+ &left, &right);
+ /* calculate min required left & right
+ * margins needed to avoid floats */
+ lm = x0 - cx;
+ rm = cx + box->parent->width -
+ box->parent->padding[LEFT] -
+ box->parent->padding[RIGHT] -
+ x1;
+ }
+ }
+ if (!layout_table(box, box->parent->width - lm - rm,
+ content))
+ return false;
+ layout_solve_width(box, box->parent->width, box->width,
+ lm, rm, -1, -1);
+ }
+ /* Position box: horizontal. */
+ box->x = box->parent->padding[LEFT] + box->margin[LEFT] +
+ box->border[LEFT].width;
+ cx += box->x;
- NSLOG(layout, DEBUG, "pass 1: b %p, x %i", b, x);
+ /* Position box: vertical. */
+ if (box->border[TOP].width) {
+ box->y += box->border[TOP].width;
+ cy += box->border[TOP].width;
+ }
+ /* Vertical margin */
+ if (((box->type == BOX_BLOCK &&
+ (box->flags & HAS_HEIGHT)) ||
+ box->type == BOX_TABLE ||
+ (box->type == BOX_INLINE_CONTAINER &&
+ box != box->parent->children) ||
+ margin_collapse == box) &&
+ in_margin == true) {
+ /* Margin goes above this box. */
+ cy += max_pos_margin - max_neg_margin;
+ box->y += max_pos_margin - max_neg_margin;
- if (b->type == BOX_BR)
- break;
+ /* Current margin has been applied. */
+ in_margin = false;
+ max_pos_margin = max_neg_margin = 0;
+ }
- if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT)
- continue;
- if (b->type == BOX_INLINE_BLOCK &&
- (css_computed_position(b->style) ==
- CSS_POSITION_ABSOLUTE ||
- css_computed_position(b->style) ==
- CSS_POSITION_FIXED))
- continue;
+ /* Handle clearance */
+ if (box->type != BOX_INLINE_CONTAINER &&
+ (y > 0) && (cy < y)) {
+ /* box clears something*/
+ box->y += y - cy;
+ cy = y;
+ }
- assert(b->style != NULL);
- font_plot_style_from_css(b->style, &fstyle);
+ /* Unless the box has an overflow style of visible, the box
+ * establishes a new block context. */
+ if (box->type == BOX_BLOCK && box->style &&
+ (overflow_x != CSS_OVERFLOW_VISIBLE ||
+ overflow_y != CSS_OVERFLOW_VISIBLE)) {
- x += space_after;
+ layout_block_context(box, viewport_height, content);
- if (b->type == BOX_INLINE_BLOCK) {
- if (b->max_width != UNKNOWN_WIDTH)
- if (!layout_float(b, *width, content))
- return false;
- h = b->border[TOP].width + b->padding[TOP] + b->height +
- b->padding[BOTTOM] +
- b->border[BOTTOM].width;
- if (height < h)
- height = h;
- x += b->margin[LEFT] + b->border[LEFT].width +
- b->padding[LEFT] + b->width +
- b->padding[RIGHT] +
- b->border[RIGHT].width +
- b->margin[RIGHT];
- space_after = 0;
- continue;
- }
+ cy += box->padding[TOP];
- 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);
- for (i = 0; i != 4; i++)
- if (b->margin[i] == AUTO)
- b->margin[i] = 0;
- x += b->margin[LEFT] + b->border[LEFT].width +
- b->padding[LEFT];
- if (b->inline_end) {
- b->inline_end->margin[RIGHT] = b->margin[RIGHT];
- b->inline_end->padding[RIGHT] =
- b->padding[RIGHT];
- b->inline_end->border[RIGHT] =
- b->border[RIGHT];
- } else {
- x += b->padding[RIGHT] +
- b->border[RIGHT].width +
- b->margin[RIGHT];
- }
- } else if (b->type == BOX_INLINE_END) {
- b->width = 0;
- if (b->space == UNKNOWN_WIDTH) {
- font_func->width(&fstyle, " ", 1, &b->space);
- /** \todo handle errors */
+ if (box->height == AUTO) {
+ box->height = 0;
+ layout_block_add_scrollbar(box, BOTTOM);
}
- space_after = b->space;
- x += b->padding[RIGHT] + b->border[RIGHT].width +
- b->margin[RIGHT];
- continue;
+ cx -= box->x;
+ cy += box->height + box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
+ y = box->y + box->padding[TOP] + box->height +
+ box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
+
+ /* Skip children, because they are done in the new
+ * block context */
+ goto advance_to_next_box;
}
- 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->parent->parent->style);
- if (height < b->height)
- height = b->height;
+ NSLOG(layout, DEBUG, "box %p, cx %i, cy %i", box, cx, cy);
- if (!b->text) {
- b->width = 0;
- space_after = 0;
- continue;
- }
+ /* Layout (except tables). */
+ if (box->object) {
+ if (!layout_block_object(box))
+ return false;
- if (b->width == UNKNOWN_WIDTH) {
- /** \todo handle errors */
+ } else if (box->type == BOX_INLINE_CONTAINER) {
+ box->width = box->parent->width;
+ if (!layout_inline_container(box, box->width, block,
+ cx, cy, content))
+ return false;
- /* If it's a select element, we must use the
- * width of the widest option text */
- if (b->parent->parent->gadget &&
- b->parent->parent->gadget->type
- == GADGET_SELECT) {
- int opt_maxwidth = 0;
- struct form_option *o;
+ } else if (box->type == BOX_TABLE) {
+ /* Move down to avoid floats if necessary. */
+ int x0, x1;
+ struct box *left, *right;
+ y = cy;
+ while (1) {
+ enum css_width_e wtype;
+ css_fixed width = 0;
+ css_unit unit = CSS_UNIT_PX;
- for (o = b->parent->parent->gadget->
- data.select.items; o;
- o = o->next) {
- int opt_width;
- font_func->width(&fstyle,
- o->text,
- strlen(o->text),
- &opt_width);
+ wtype = css_computed_width(box->style,
+ &width, &unit);
- if (opt_maxwidth < opt_width)
- opt_maxwidth =opt_width;
- }
- b->width = opt_maxwidth;
- if (nsoption_bool(core_select_menu))
- b->width += SCROLLBAR_WIDTH;
- } else {
- font_func->width(&fstyle, b->text,
- b->length, &b->width);
- b->flags |= MEASURED;
- }
+ x0 = cx;
+ x1 = cx + box->parent->width;
+ find_sides(block->float_children, y,
+ y + box->height,
+ &x0, &x1, &left, &right);
+ if (wtype == CSS_WIDTH_AUTO)
+ break;
+ if (box->width <= x1 - x0)
+ break;
+ if (!left && !right)
+ break;
+ else if (!left)
+ y = right->y + right->height + 1;
+ else if (!right)
+ y = left->y + left->height + 1;
+ else if (left->y + left->height <
+ right->y + right->height)
+ y = left->y + left->height + 1;
+ else
+ y = right->y + right->height + 1;
}
+ box->x += x0 - cx;
+ cx = x0;
+ box->y += y - cy;
+ cy = y;
+ }
- /* If the current text has not been measured (i.e. its
- * width was estimated after splitting), and it fits on
- * the line, measure it properly, so next box is placed
- * correctly. */
- if (b->text && (x + b->width < x1 - x0) &&
- !(b->flags & MEASURED) &&
- b->next) {
- font_func->width(&fstyle, b->text,
- b->length, &b->width);
- b->flags |= MEASURED;
- }
+ /* Advance to next box. */
+ if (box->type == BOX_BLOCK && !box->object && !(box->iframe) &&
+ box->children) {
+ /* Down into children. */
- x += b->width;
- if (b->space == UNKNOWN_WIDTH) {
- font_func->width(&fstyle, " ", 1, &b->space);
- /** \todo handle errors */
+ if (box == margin_collapse) {
+ /* Current margin collapsed though to this box.
+ * Unset margin_collapse. */
+ margin_collapse = NULL;
}
- space_after = b->space;
+
+ y = box->padding[TOP];
+ box = box->children;
+ box->y = y;
+ cy += y;
continue;
+ } else if (box->type == BOX_BLOCK || box->object ||
+ box->flags & IFRAME)
+ cy += box->padding[TOP];
+
+ if (box->type == BOX_BLOCK && box->height == AUTO) {
+ box->height = 0;
+ layout_block_add_scrollbar(box, BOTTOM);
}
- space_after = 0;
+ cy += box->height + box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
+ cx -= box->x;
+ y = box->y + box->padding[TOP] + box->height +
+ box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
- /* inline replaced, 10.3.2 and 10.6.2 */
- assert(b->style);
+ advance_to_next_box:
+ if (!box->next) {
+ /* No more siblings:
+ * up to first ancestor with a sibling. */
- layout_find_dimensions(*width, -1, b, b->style,
- &b->width, &b->height, &max_width, &min_width,
- &max_height, &min_height, NULL, NULL, NULL);
+ do {
+ if (box == margin_collapse) {
+ /* Current margin collapsed though to
+ * this box. Unset margin_collapse. */
+ margin_collapse = NULL;
+ }
- if (b->object && !(b->flags & REPLACE_DIM)) {
- layout_get_object_dimensions(b, &b->width, &b->height,
- min_width, max_width,
- min_height, max_height);
- } else if (b->flags & IFRAME) {
- /* TODO: should we look at the content dimensions? */
- if (b->width == AUTO)
- b->width = 400;
- if (b->height == AUTO)
- b->height = 300;
+ /* Apply bottom margin */
+ if (max_pos_margin < box->margin[BOTTOM])
+ max_pos_margin = box->margin[BOTTOM];
+ else if (max_neg_margin < -box->margin[BOTTOM])
+ max_neg_margin = -box->margin[BOTTOM];
- /* We reformat the iframe browser window to new
- * dimensions in pass 2 */
- } else {
- /* form control with no object */
- if (b->width == AUTO)
- b->width = FIXTOINT(nscss_len2px(INTTOFIX(1),
- CSS_UNIT_EM, b->style));
- if (b->height == AUTO)
- b->height = FIXTOINT(nscss_len2px(INTTOFIX(1),
- CSS_UNIT_EM, b->style));
- }
+ box = box->parent;
+ if (box == block)
+ break;
- /* Reformat object to new box size */
- if (b->object && content_get_type(b->object) == CONTENT_HTML &&
- b->width !=
- content_get_available_width(b->object)) {
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
- enum css_height_e htype = css_computed_height(b->style,
- &value, &unit);
+ /* Margin is invalidated if this is a box
+ * margins can't collapse through. */
+ if (box->type == BOX_BLOCK &&
+ box->flags & MAKE_HEIGHT) {
+ margin_collapse = NULL;
+ in_margin = false;
+ max_pos_margin = max_neg_margin = 0;
+ }
- content_reformat(b->object, false, b->width, b->height);
+ if (box->height == AUTO) {
+ box->height = y - box->padding[TOP];
- if (htype == CSS_HEIGHT_AUTO)
- b->height = content_get_height(b->object);
- }
+ if (box->type == BOX_BLOCK)
+ layout_block_add_scrollbar(box,
+ BOTTOM);
+ } else
+ cy += box->height -
+ (y - box->padding[TOP]);
- if (height < b->height)
- height = b->height;
+ /* Apply any min-height and max-height to
+ * boxes in normal flow */
+ if (box->style &&
+ css_computed_position(box->style) !=
+ CSS_POSITION_ABSOLUTE &&
+ layout_apply_minmax_height(box,
+ NULL)) {
+ /* Height altered */
+ /* Set current cy */
+ cy += box->height -
+ (y - box->padding[TOP]);
+ }
- x += b->width;
- }
+ cy += box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
+ cx -= box->x;
+ y = box->y + box->padding[TOP] + box->height +
+ box->padding[BOTTOM] +
+ box->border[BOTTOM].width;
- /* find new sides using this height */
- x0 = cx;
- x1 = cx + *width;
- find_sides(cont->float_children, cy, cy + height, &x0, &x1,
- &left, &right);
- x0 -= cx;
- x1 -= cx;
+ } while (box->next == NULL);
+ if (box == block)
+ break;
+ }
- if (indent)
- x0 += layout_text_indent(first->parent->parent->style, *width);
+ /* To next sibling. */
- if (x1 < x0)
- x1 = x0;
+ if (box == margin_collapse) {
+ /* Current margin collapsed though to this box.
+ * Unset margin_collapse. */
+ margin_collapse = NULL;
+ }
- space_after = space_before = 0;
+ if (max_pos_margin < box->margin[BOTTOM])
+ max_pos_margin = box->margin[BOTTOM];
+ else if (max_neg_margin < -box->margin[BOTTOM])
+ max_neg_margin = -box->margin[BOTTOM];
- /* pass 2: place boxes in line: loop body executed at least once */
+ box = box->next;
+ box->y = y;
+ }
- NSLOG(layout, DEBUG, "x0 %i, x1 %i, x1 - x0 %i", x0, x1, x1 - x0);
+ /* Account for bottom margin of last contained block */
+ cy += max_pos_margin - max_neg_margin;
- for (x = x_previous = 0, b = first; x <= x1 - x0 && b; b = b->next) {
+ /* Increase height to contain any floats inside (CSS 2.1 10.6.7). */
+ for (box = block->float_children; box; box = box->next_float) {
+ y = box->y + box->height + box->padding[BOTTOM] +
+ box->border[BOTTOM].width + box->margin[BOTTOM];
+ if (cy < y)
+ cy = y;
+ }
- NSLOG(layout, DEBUG, "pass 2: b %p, x %i", b, x);
+ if (block->height == AUTO) {
+ block->height = cy - block->padding[TOP];
+ if (block->type == BOX_BLOCK)
+ layout_block_add_scrollbar(block, BOTTOM);
+ }
- if (b->type == BOX_INLINE_BLOCK &&
- (css_computed_position(b->style) ==
- CSS_POSITION_ABSOLUTE ||
- css_computed_position(b->style) ==
- CSS_POSITION_FIXED)) {
- b->x = x + space_after;
+ if (block->style && css_computed_position(block->style) !=
+ CSS_POSITION_ABSOLUTE) {
+ /* Block is in normal flow */
+ layout_apply_minmax_height(block, NULL);
+ }
- } else if (b->type == BOX_INLINE ||
- b->type == BOX_INLINE_BLOCK ||
- b->type == BOX_TEXT ||
- b->type == BOX_INLINE_END) {
- assert(b->width != UNKNOWN_WIDTH);
+ if (block->gadget &&
+ (block->gadget->type == GADGET_TEXTAREA ||
+ block->gadget->type == GADGET_PASSWORD ||
+ block->gadget->type == GADGET_TEXTBOX)) {
+ int ta_width = block->padding[LEFT] + block->width +
+ block->padding[RIGHT];
+ int ta_height = block->padding[TOP] + block->height +
+ block->padding[BOTTOM];
+ textarea_set_layout(block->gadget->data.text.ta,
+ ta_width, ta_height,
+ block->padding[TOP], block->padding[RIGHT],
+ block->padding[BOTTOM], block->padding[LEFT]);
+ }
- x_previous = x;
- x += space_after;
- b->x = x;
+ return true;
+}
- if ((b->type == BOX_INLINE && !b->inline_end) ||
- b->type == BOX_INLINE_BLOCK) {
- b->x += b->margin[LEFT] + b->border[LEFT].width;
- x = b->x + b->padding[LEFT] + b->width +
- b->padding[RIGHT] +
- b->border[RIGHT].width +
- b->margin[RIGHT];
- } else if (b->type == BOX_INLINE) {
- b->x += b->margin[LEFT] + b->border[LEFT].width;
- x = b->x + b->padding[LEFT] + b->width;
- } else if (b->type == BOX_INLINE_END) {
- b->height = b->inline_end->height;
- x += b->padding[RIGHT] +
- b->border[RIGHT].width +
- b->margin[RIGHT];
- } else {
- x += b->width;
- }
- space_before = space_after;
- if (b->object || b->flags & REPLACE_DIM ||
- b->flags & IFRAME)
- space_after = 0;
- else if (b->text || b->type == BOX_INLINE_END) {
- if (b->space == UNKNOWN_WIDTH) {
- font_plot_style_from_css(b->style,
+/**
+ * Layout list markers.
+ */
+static void
+layout_lists(struct box *box,
+ const struct gui_layout_table *font_func)
+{
+ struct box *child;
+ struct box *marker;
+ plot_font_style_t fstyle;
+
+ for (child = box->children; child; child = child->next) {
+ if (child->list_marker) {
+ marker = child->list_marker;
+ if (marker->object) {
+ marker->width =
+ content_get_width(marker->object);
+ marker->x = -marker->width;
+ marker->height =
+ content_get_height(marker->object);
+ marker->y = (line_height(marker->style) -
+ marker->height) / 2;
+ } else if (marker->text) {
+ if (marker->width == UNKNOWN_WIDTH) {
+ font_plot_style_from_css(marker->style,
&fstyle);
- /** \todo handle errors */
- font_func->width(&fstyle, " ", 1,
- &b->space);
+ font_func->width(&fstyle,
+ marker->text,
+ marker->length,
+ &marker->width);
+ marker->flags |= MEASURED;
}
- space_after = b->space;
+ marker->x = -marker->width;
+ marker->y = 0;
+ marker->height = line_height(marker->style);
} else {
- space_after = 0;
+ marker->x = 0;
+ marker->y = 0;
+ marker->width = 0;
+ marker->height = 0;
}
- split_box = b;
- move_y = true;
- inline_count++;
- } else if (b->type == BOX_BR) {
- b->x = x;
- b->width = 0;
- br_box = b;
- b = b->next;
- split_box = 0;
- move_y = true;
- break;
+ /* Gap between marker and content */
+ marker->x -= 4;
+ }
+ layout_lists(child, font_func);
+ }
+}
+
+
+/**
+ * Compute box offsets for a relatively or absolutely positioned box with
+ * respect to a box.
+ *
+ * \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
+ * \param right updated to right offset, or AUTO
+ * \param bottom updated to bottom offset, or AUTO
+ * \param left updated to left offset, or AUTO
+ *
+ * See CSS 2.1 9.3.2. containing_block must have width and height.
+ */
+static void
+layout_compute_offsets(struct box *box,
+ struct box *containing_block,
+ int *top,
+ int *right,
+ int *bottom,
+ int *left)
+{
+ uint32_t type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ assert(containing_block->width != UNKNOWN_WIDTH &&
+ containing_block->width != AUTO &&
+ containing_block->height != AUTO);
+ /* left */
+ type = css_computed_left(box->style, &value, &unit);
+ if (type == CSS_LEFT_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *left = FPCT_OF_INT_TOINT(value,
+ containing_block->width);
} else {
- /* float */
- NSLOG(layout, DEBUG, "float %p", b);
+ *left = FIXTOINT(nscss_len2px(value, unit, box->style));
+ }
+ } else {
+ *left = AUTO;
+ }
- d = b->children;
- d->float_children = 0;
- d->cached_place_below_level = 0;
- b->float_container = d->float_container = cont;
+ /* right */
+ type = css_computed_right(box->style, &value, &unit);
+ if (type == CSS_RIGHT_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *right = FPCT_OF_INT_TOINT(value,
+ containing_block->width);
+ } else {
+ *right = FIXTOINT(nscss_len2px(value, unit,
+ box->style));
+ }
+ } else {
+ *right = AUTO;
+ }
- if (!layout_float(d, *width, content))
- return false;
+ /* top */
+ type = css_computed_top(box->style, &value, &unit);
+ if (type == CSS_TOP_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *top = FPCT_OF_INT_TOINT(value,
+ containing_block->height);
+ } else {
+ *top = FIXTOINT(nscss_len2px(value, unit, box->style));
+ }
+ } else {
+ *top = AUTO;
+ }
- NSLOG(layout, DEBUG,
- "%p : %d %d",
- d,
- d->margin[TOP],
- d->border[TOP].width);
+ /* bottom */
+ type = css_computed_bottom(box->style, &value, &unit);
+ if (type == CSS_BOTTOM_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *bottom = FPCT_OF_INT_TOINT(value,
+ containing_block->height);
+ } else {
+ *bottom = FIXTOINT(nscss_len2px(value, unit,
+ box->style));
+ }
+ } else {
+ *bottom = AUTO;
+ }
+}
- d->x = d->margin[LEFT] + d->border[LEFT].width;
- d->y = d->margin[TOP] + d->border[TOP].width;
- b->width = d->margin[LEFT] + d->border[LEFT].width +
- d->padding[LEFT] + d->width +
- d->padding[RIGHT] +
- d->border[RIGHT].width +
- d->margin[RIGHT];
- b->height = d->margin[TOP] + d->border[TOP].width +
- d->padding[TOP] + d->height +
- d->padding[BOTTOM] +
- d->border[BOTTOM].width +
- d->margin[BOTTOM];
- if (b->width > (x1 - x0) - x)
- place_below = true;
- if (d->style && (css_computed_clear(d->style) ==
- CSS_CLEAR_NONE ||
- (css_computed_clear(d->style) ==
- CSS_CLEAR_LEFT && left == 0) ||
- (css_computed_clear(d->style) ==
- CSS_CLEAR_RIGHT &&
- right == 0) ||
- (css_computed_clear(d->style) ==
- CSS_CLEAR_BOTH &&
- left == 0 && right == 0)) &&
- (!place_below ||
- (left == 0 && right == 0 && x == 0)) &&
- cy >= cont->clear_level &&
- cy >= cont->cached_place_below_level) {
- /* + not cleared or,
- * cleared and there are no floats to clear
- * + fits without needing to be placed below or,
- * this line is empty with no floats
- * + current y, cy, is below the clear level
- *
- * Float affects current line */
- if (b->type == BOX_FLOAT_LEFT) {
- b->x = cx + x0;
- if (b->width > 0)
- x0 += b->width;
- left = b;
- } else {
- b->x = cx + x1 - b->width;
- if (b->width > 0)
- x1 -= b->width;
- right = b;
- }
- b->y = cy;
- } else {
- /* cleared or doesn't fit on line */
- /* place below into next available space */
- int fcy = (cy > cont->clear_level) ? cy :
- cont->clear_level;
- fcy = (fcy > cont->cached_place_below_level) ?
- fcy :
- cont->cached_place_below_level;
- fy = (fy > fcy) ? fy : fcy;
- fy = (fy == cy) ? fy + height : fy;
+/**
+ * Layout and position an absolutely positioned box.
+ *
+ * \param box absolute box to layout and position
+ * \param containing_block containing block
+ * \param cx position of box relative to containing_block
+ * \param cy position of box relative to containing_block
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+static bool
+layout_absolute(struct box *box,
+ struct box *containing_block,
+ int cx, int cy,
+ html_content *content)
+{
+ int static_left, static_top; /* static position */
+ int top, right, bottom, left;
+ int width, height, max_width, min_width;
+ int *margin = box->margin;
+ int *padding = box->padding;
+ struct box_border *border = box->border;
+ int available_width = containing_block->width;
+ int space;
- place_float_below(b, *width, cx, fy, cont);
- fy = b->y;
- if (d->style && (
- (css_computed_clear(d->style) ==
- CSS_CLEAR_LEFT && left != 0) ||
- (css_computed_clear(d->style) ==
- CSS_CLEAR_RIGHT &&
- right != 0) ||
- (css_computed_clear(d->style) ==
- CSS_CLEAR_BOTH &&
- (left != 0 || right != 0)))) {
- /* to be cleared below existing
- * floats */
- if (b->type == BOX_FLOAT_LEFT)
- b->x = cx;
- else
- b->x = cx + *width - b->width;
+ assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
+ box->type == BOX_INLINE_BLOCK);
- fcy = layout_clear(cont->float_children,
- css_computed_clear(d->style));
- if (fcy > cont->clear_level)
- cont->clear_level = fcy;
- if (b->y < fcy)
- b->y = fcy;
- }
- if (b->type == BOX_FLOAT_LEFT)
- left = b;
- else
- right = b;
+ /* The static position is where the box would be if it was not
+ * absolutely positioned. The x and y are filled in by
+ * layout_block_context(). */
+ static_left = cx + box->x;
+ static_top = cy + box->y;
+
+ if (containing_block->type == BOX_BLOCK ||
+ containing_block->type == BOX_INLINE_BLOCK ||
+ containing_block->type == BOX_TABLE_CELL) {
+ /* Block level container => temporarily increase containing
+ * block dimensions to include padding (we restore this
+ * again at the end) */
+ containing_block->width += containing_block->padding[LEFT] +
+ containing_block->padding[RIGHT];
+ containing_block->height += containing_block->padding[TOP] +
+ containing_block->padding[BOTTOM];
+ } else {
+ /** \todo inline containers */
+ }
+
+ layout_compute_offsets(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);
+ box->float_container = NULL;
+
+ /* 10.3.7 */
+ NSLOG(layout, DEBUG,
+ "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
+ left, margin[LEFT], border[LEFT].width, padding[LEFT], width,
+ padding[RIGHT], border[RIGHT].width, margin[RIGHT], right,
+ containing_block->width);
+
+
+ if (left == AUTO && width == AUTO && right == AUTO) {
+ if (margin[LEFT] == AUTO)
+ margin[LEFT] = 0;
+ if (margin[RIGHT] == AUTO)
+ margin[RIGHT] = 0;
+ left = static_left;
+
+ width = min(max(box->min_width, available_width),
+ box->max_width);
+ width -= box->margin[LEFT] + box->border[LEFT].width +
+ box->padding[LEFT] + box->padding[RIGHT] +
+ box->border[RIGHT].width + box->margin[RIGHT];
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width) width = max_width;
+ if (width < min_width) width = min_width;
+
+ right = containing_block->width -
+ left -
+ margin[LEFT] - border[LEFT].width - padding[LEFT] -
+ width -
+ padding[RIGHT] - border[RIGHT].width - margin[RIGHT];
+ } else if (left != AUTO && width != AUTO && right != AUTO) {
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width) width = max_width;
+ if (min_width > 0 && width < min_width) width = min_width;
+
+ if (margin[LEFT] == AUTO && margin[RIGHT] == AUTO) {
+ space = containing_block->width -
+ left - border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - right;
+ if (space < 0) {
+ margin[LEFT] = 0;
+ margin[RIGHT] = space;
+ } else {
+ margin[LEFT] = margin[RIGHT] = space / 2;
}
- add_float_to_container(cont, b);
+ } else if (margin[LEFT] == AUTO) {
+ margin[LEFT] = containing_block->width -
+ left - border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT] -
+ right;
+ } else if (margin[RIGHT] == AUTO) {
+ margin[RIGHT] = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - right;
+ } else {
+ right = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT];
+ }
+ } else {
+ if (margin[LEFT] == AUTO)
+ margin[LEFT] = 0;
+ if (margin[RIGHT] == AUTO)
+ margin[RIGHT] = 0;
- split_box = 0;
+ if (left == AUTO && width == AUTO && right != AUTO) {
+ available_width -= right;
+
+ width = min(max(box->min_width, available_width),
+ box->max_width);
+ width -= box->margin[LEFT] + box->border[LEFT].width +
+ box->padding[LEFT] + box->padding[RIGHT] +
+ box->border[RIGHT].width + box->margin[RIGHT];
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (width < min_width)
+ width = min_width;
+
+ left = containing_block->width -
+ margin[LEFT] - border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT] -
+ right;
+ } else if (left == AUTO && width != AUTO && right == AUTO) {
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (min_width > 0 && width < min_width)
+ width = min_width;
+
+ left = static_left;
+ right = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT];
+ } else if (left != AUTO && width == AUTO && right == AUTO) {
+ available_width -= left;
+
+ width = min(max(box->min_width, available_width),
+ box->max_width);
+ width -= box->margin[LEFT] + box->border[LEFT].width +
+ box->padding[LEFT] + box->padding[RIGHT] +
+ box->border[RIGHT].width + box->margin[RIGHT];
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (width < min_width)
+ width = min_width;
+
+ right = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT];
+ } else if (left == AUTO && width != AUTO && right != AUTO) {
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (width < min_width)
+ width = min_width;
+
+ left = containing_block->width -
+ margin[LEFT] - border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT] -
+ right;
+ } else if (left != AUTO && width == AUTO && right != AUTO) {
+ width = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT] -
+ right;
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (width < min_width)
+ width = min_width;
+
+ } else if (left != AUTO && width != AUTO && right == AUTO) {
+
+ /* Adjust for {min|max}-width */
+ if (max_width >= 0 && width > max_width)
+ width = max_width;
+ if (width < min_width)
+ width = min_width;
+
+ right = containing_block->width -
+ left - margin[LEFT] -
+ border[LEFT].width -
+ padding[LEFT] - width - padding[RIGHT] -
+ border[RIGHT].width - margin[RIGHT];
}
}
- if (x1 - x0 < x && split_box) {
- /* the last box went over the end */
- size_t split = 0;
- int w;
- bool no_wrap = css_computed_white_space(
- split_box->style) == CSS_WHITE_SPACE_NOWRAP ||
- css_computed_white_space(
- split_box->style) == CSS_WHITE_SPACE_PRE;
+ NSLOG(layout, DEBUG,
+ "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
+ left, margin[LEFT], border[LEFT].width, padding[LEFT], width,
+ padding[RIGHT], border[RIGHT].width, margin[RIGHT], right,
+ containing_block->width);
- x = x_previous;
+ box->x = left + margin[LEFT] + border[LEFT].width - cx;
+ if (containing_block->type == BOX_BLOCK ||
+ containing_block->type == BOX_INLINE_BLOCK ||
+ containing_block->type == BOX_TABLE_CELL) {
+ /* Block-level ancestor => reset container's width */
+ containing_block->width -= containing_block->padding[LEFT] +
+ containing_block->padding[RIGHT];
+ } else {
+ /** \todo inline ancestors */
+ }
+ box->width = width;
+ box->height = height;
- if (!no_wrap &&
- (split_box->type == BOX_INLINE ||
- split_box->type == BOX_TEXT) &&
- !split_box->object &&
- !(split_box->flags & REPLACE_DIM) &&
- !(split_box->flags & IFRAME) &&
- !split_box->gadget && split_box->text) {
+ if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
+ box->object || box->flags & IFRAME) {
+ if (!layout_block_context(box, -1, content))
+ return false;
+ } else if (box->type == BOX_TABLE) {
+ /* layout_table also expects the containing block to be
+ * stored in the float_container field */
+ box->float_container = containing_block;
+ /* \todo layout_table considers margins etc. again */
+ if (!layout_table(box, width, content))
+ return false;
+ box->float_container = NULL;
+ layout_solve_width(box, box->parent->width, box->width, 0, 0,
+ -1, -1);
+ }
- font_plot_style_from_css(split_box->style, &fstyle);
- /** \todo handle errors */
- font_func->split(&fstyle,
- split_box->text,
- split_box->length,
- x1 - x0 - x - space_before,
- &split,
- &w);
+ /* 10.6.4 */
+ NSLOG(layout, DEBUG,
+ "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
+ top, margin[TOP], border[TOP].width, padding[TOP], height,
+ padding[BOTTOM], border[BOTTOM].width, margin[BOTTOM], bottom,
+ containing_block->height);
+
+ if (top == AUTO && height == AUTO && bottom == AUTO) {
+ top = static_top;
+ height = box->height;
+ if (margin[TOP] == AUTO)
+ margin[TOP] = 0;
+ if (margin[BOTTOM] == AUTO)
+ margin[BOTTOM] = 0;
+ bottom = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height - padding[BOTTOM] -
+ border[BOTTOM].width - margin[BOTTOM];
+ } else if (top != AUTO && height != AUTO && bottom != AUTO) {
+ if (margin[TOP] == AUTO && margin[BOTTOM] == AUTO) {
+ space = containing_block->height -
+ top - border[TOP].width - padding[TOP] -
+ height - padding[BOTTOM] -
+ border[BOTTOM].width - bottom;
+ margin[TOP] = margin[BOTTOM] = space / 2;
+ } else if (margin[TOP] == AUTO) {
+ margin[TOP] = containing_block->height -
+ top - border[TOP].width - padding[TOP] -
+ height - padding[BOTTOM] -
+ border[BOTTOM].width - margin[BOTTOM] -
+ bottom;
+ } else if (margin[BOTTOM] == AUTO) {
+ margin[BOTTOM] = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ bottom;
+ } else {
+ bottom = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM];
+ }
+ } else {
+ if (margin[TOP] == AUTO)
+ margin[TOP] = 0;
+ if (margin[BOTTOM] == AUTO)
+ margin[BOTTOM] = 0;
+ if (top == AUTO && height == AUTO && bottom != AUTO) {
+ height = box->height;
+ top = containing_block->height -
+ margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM] - bottom;
+ } else if (top == AUTO && height != AUTO && bottom == AUTO) {
+ top = static_top;
+ bottom = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM];
+ } else if (top != AUTO && height == AUTO && bottom == AUTO) {
+ height = box->height;
+ bottom = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM];
+ } else if (top == AUTO && height != AUTO && bottom != AUTO) {
+ top = containing_block->height -
+ margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM] - bottom;
+ } else if (top != AUTO && height == AUTO && bottom != AUTO) {
+ height = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - padding[BOTTOM] -
+ border[BOTTOM].width - margin[BOTTOM] -
+ bottom;
+ } else if (top != AUTO && height != AUTO && bottom == AUTO) {
+ bottom = containing_block->height -
+ top - margin[TOP] - border[TOP].width -
+ padding[TOP] - height -
+ padding[BOTTOM] - border[BOTTOM].width -
+ margin[BOTTOM];
}
+ }
- /* split == 0 implies that text can't be split */
-
- if (split == 0)
- w = split_box->width;
-
-
- NSLOG(layout, DEBUG,
- "splitting: split_box %p \"%.*s\", spilt %zu, w %i, "
- "left %p, right %p, inline_count %u",
- split_box,
- (int)split_box->length,
- split_box->text,
- split,
- w,
- left,
- right,
- inline_count);
-
- if ((split == 0 || x1 - x0 <= x + space_before + w) &&
- !left && !right && inline_count == 1) {
- /* first word of box doesn't fit, but no floats and
- * first box on line so force in */
- if (split == 0 || split == split_box->length) {
- /* only one word in this box, or not text
- * or white-space:nowrap */
- b = split_box->next;
- } else {
- /* cut off first word for this line */
- if (!layout_text_box_split(content, &fstyle,
- split_box, split, w))
- return false;
- b = split_box->next;
- }
- x += space_before + w;
-
- NSLOG(layout, DEBUG, "forcing");
-
- } else if ((split == 0 || x1 - x0 <= x + space_before + w) &&
- inline_count == 1) {
- /* first word of first box doesn't fit, but a float is
- * taking some of the width so move below it */
- assert(left || right);
- used_height = 0;
- if (left) {
-
- NSLOG(layout, DEBUG,
- "cy %i, left->y %i, left->height %i",
- cy,
- left->y,
- left->height);
-
- used_height = left->y + left->height - cy + 1;
-
- NSLOG(layout, DEBUG, "used_height %i",
- used_height);
-
- }
- if (right && used_height <
- right->y + right->height - cy + 1)
- used_height = right->y + right->height - cy + 1;
-
- if (used_height < 0)
- used_height = 0;
+ NSLOG(layout, DEBUG,
+ "%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",
+ top, margin[TOP], border[TOP].width, padding[TOP], height,
+ padding[BOTTOM], border[BOTTOM].width, margin[BOTTOM], bottom,
+ containing_block->height);
- b = split_box;
+ box->y = top + margin[TOP] + border[TOP].width - cy;
+ if (containing_block->type == BOX_BLOCK ||
+ containing_block->type == BOX_INLINE_BLOCK ||
+ containing_block->type == BOX_TABLE_CELL) {
+ /* Block-level ancestor => reset container's height */
+ containing_block->height -= containing_block->padding[TOP] +
+ containing_block->padding[BOTTOM];
+ } else {
+ /** \todo Inline ancestors */
+ }
+ box->height = height;
+ layout_apply_minmax_height(box, containing_block);
- NSLOG(layout, DEBUG, "moving below float");
+ return true;
+}
- } else if (split == 0 || x1 - x0 <= x + space_before + w) {
- /* first word of box doesn't fit so leave box for next
- * line */
- b = split_box;
- NSLOG(layout, DEBUG, "leaving for next line");
+/**
+ * Recursively layout and position absolutely positioned boxes.
+ *
+ * \param box tree of boxes to layout
+ * \param containing_block current containing block
+ * \param cx position of box relative to containing_block
+ * \param cy position of box relative to containing_block
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+static bool
+layout_position_absolute(struct box *box,
+ struct box *containing_block,
+ int cx, int cy,
+ html_content *content)
+{
+ struct box *c;
+ for (c = box->children; c; c = c->next) {
+ if ((c->type == BOX_BLOCK || c->type == BOX_TABLE ||
+ c->type == BOX_INLINE_BLOCK) &&
+ (css_computed_position(c->style) ==
+ CSS_POSITION_ABSOLUTE ||
+ css_computed_position(c->style) ==
+ CSS_POSITION_FIXED)) {
+ if (!layout_absolute(c, containing_block,
+ cx, cy, content))
+ return false;
+ if (!layout_position_absolute(c, c, 0, 0, content))
+ return false;
+ } else if (c->style && css_computed_position(c->style) ==
+ CSS_POSITION_RELATIVE) {
+ if (!layout_position_absolute(c, c, 0, 0, content))
+ return false;
} else {
- /* fit as many words as possible */
- assert(split != 0);
-
- NSLOG(layout, DEBUG, "'%.*s' %i %zu %i",
- (int)split_box->length, split_box->text,
- x1 - x0, split, w);
-
- if (split != split_box->length) {
- if (!layout_text_box_split(content, &fstyle,
- split_box, split, w))
- return false;
- b = split_box->next;
+ int px, py;
+ if (c->style && (css_computed_float(c->style) ==
+ CSS_FLOAT_LEFT ||
+ css_computed_float(c->style) ==
+ CSS_FLOAT_RIGHT)) {
+ /* Float x/y coords are relative to nearest
+ * ansestor with float_children, rather than
+ * relative to parent. Need to get x/y relative
+ * to parent */
+ struct box *p;
+ px = c->x;
+ py = c->y;
+ for (p = box->parent; p && !p->float_children;
+ p = p->parent) {
+ px -= p->x;
+ py -= p->y;
+ }
+ } else {
+ /* Not a float, so box x/y coords are relative
+ * to parent */
+ px = c->x;
+ py = c->y;
}
- x += space_before + w;
-
- NSLOG(layout, DEBUG, "fitting words");
-
+ if (!layout_position_absolute(c, containing_block,
+ cx + px, cy + py, content))
+ return false;
}
- move_y = true;
}
- /* set positions */
- switch (css_computed_text_align(first->parent->parent->style)) {
- case CSS_TEXT_ALIGN_RIGHT:
- case CSS_TEXT_ALIGN_LIBCSS_RIGHT:
- x0 = x1 - x;
- break;
- case CSS_TEXT_ALIGN_CENTER:
- case CSS_TEXT_ALIGN_LIBCSS_CENTER:
- x0 = (x0 + (x1 - x)) / 2;
- break;
- case CSS_TEXT_ALIGN_LEFT:
- case CSS_TEXT_ALIGN_LIBCSS_LEFT:
- case CSS_TEXT_ALIGN_JUSTIFY:
- /* leave on left */
- break;
- case CSS_TEXT_ALIGN_DEFAULT:
- /* None; consider text direction */
- switch (css_computed_direction(first->parent->parent->style)) {
- case CSS_DIRECTION_LTR:
- /* leave on left */
- break;
- case CSS_DIRECTION_RTL:
- x0 = x1 - x;
- break;
- }
- break;
- }
+ return true;
+}
- for (d = first; d != b; d = d->next) {
- d->flags &= ~NEW_LINE;
- if (d->type == BOX_INLINE_BLOCK &&
- (css_computed_position(d->style) ==
- CSS_POSITION_ABSOLUTE ||
- css_computed_position(d->style) ==
- CSS_POSITION_FIXED)) {
- /* positioned inline-blocks:
- * set static position (x,y) only, rest of positioning
- * is handled later */
- d->x += x0;
- d->y = *y;
- continue;
- } else if ((d->type == BOX_INLINE &&
- ((d->object || d->gadget) == false) &&
- !(d->flags & IFRAME) &&
- !(d->flags & REPLACE_DIM)) ||
- d->type == BOX_BR ||
- d->type == BOX_TEXT ||
- d->type == BOX_INLINE_END) {
- /* regular (non-replaced) inlines */
- d->x += x0;
- d->y = *y - d->padding[TOP];
+/**
+ * Compute a box's relative offset as per CSS 2.1 9.4.3
+ *
+ * \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)
+{
+ int left, right, top, bottom;
+ struct box *containing_block;
- if (d->type == BOX_TEXT && d->height > used_height) {
- /* text */
- used_height = d->height;
- }
- } else if ((d->type == BOX_INLINE) ||
- d->type == BOX_INLINE_BLOCK) {
- /* replaced inlines and inline-blocks */
- d->x += x0;
- d->y = *y + d->border[TOP].width + d->margin[TOP];
- h = d->margin[TOP] + d->border[TOP].width +
- d->padding[TOP] + d->height +
- d->padding[BOTTOM] +
- d->border[BOTTOM].width +
- d->margin[BOTTOM];
- if (used_height < h)
- used_height = h;
- }
+ assert(box && box->parent && box->style &&
+ css_computed_position(box->style) ==
+ CSS_POSITION_RELATIVE);
+
+ if (box->float_container &&
+ (css_computed_float(box->style) == CSS_FLOAT_LEFT ||
+ css_computed_float(box->style) == CSS_FLOAT_RIGHT)) {
+ containing_block = box->float_container;
+ } else {
+ containing_block = box->parent;
}
- first->flags |= NEW_LINE;
-
- assert(b != first || (move_y && 0 < used_height && (left || right)));
+ layout_compute_offsets(box, containing_block,
+ &top, &right, &bottom, &left);
- /* handle vertical-align by adjusting box y values */
- /** \todo proper vertical alignment handling */
- for (d = first; d != b; d = d->next) {
- if ((d->type == BOX_INLINE && d->inline_end) ||
- d->type == BOX_BR ||
- d->type == BOX_TEXT ||
- d->type == BOX_INLINE_END) {
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
- switch (css_computed_vertical_align(d->style, &value,
- &unit)) {
- case CSS_VERTICAL_ALIGN_SUPER:
- case CSS_VERTICAL_ALIGN_TOP:
- case CSS_VERTICAL_ALIGN_TEXT_TOP:
- /* already at top */
- break;
- case CSS_VERTICAL_ALIGN_SUB:
- case CSS_VERTICAL_ALIGN_BOTTOM:
- case CSS_VERTICAL_ALIGN_TEXT_BOTTOM:
- d->y += used_height - d->height;
- break;
- default:
- case CSS_VERTICAL_ALIGN_BASELINE:
- d->y += 0.75 * (used_height - d->height);
- break;
- }
+ if (left == AUTO && right == AUTO)
+ left = right = 0;
+ else if (left == AUTO)
+ /* left is auto => computed = -right */
+ left = -right;
+ else if (right == AUTO)
+ /* right is auto => computed = -left */
+ right = -left;
+ else {
+ /* over constrained => examine direction property
+ * of containing block */
+ if (containing_block->style &&
+ css_computed_direction(
+ containing_block->style) ==
+ CSS_DIRECTION_RTL) {
+ /* right wins */
+ left = -right;
+ } else {
+ /* assume LTR in all other cases */
+ right = -left;
}
}
- /* handle clearance for br */
- if (br_box && css_computed_clear(br_box->style) != CSS_CLEAR_NONE) {
- int clear_y = layout_clear(cont->float_children,
- css_computed_clear(br_box->style));
- if (used_height < clear_y - cy)
- used_height = clear_y - cy;
+ assert(left == -right);
+
+ if (top == AUTO && bottom == AUTO) {
+ top = bottom = 0;
+ } else if (top == AUTO) {
+ top = -bottom;
+ } else {
+ /* bottom is AUTO, or neither are AUTO */
+ bottom = -top;
}
- if (move_y)
- *y += used_height;
- *next_box = b;
- *width = x; /* return actual width */
- return true;
+ NSLOG(layout, DEBUG, "left %i, right %i, top %i, bottom %i", left,
+ right, top, bottom);
+
+ *x = left;
+ *y = top;
}
-/* exported function documented in render/layout.h */
-bool layout_inline_container(struct box *inline_container, int width,
- struct box *cont, int cx, int cy, html_content *content)
+/**
+ * Adjust positions of relatively positioned boxes.
+ *
+ * \param root box to adjust the position of
+ * \param fp box which forms the block formatting context for children of
+ * "root" which are floats
+ * \param fx x offset due to intervening relatively positioned boxes
+ * between current box, "root", and the block formatting context
+ * box, "fp", for float children of "root"
+ * \param fy y offset due to intervening relatively positioned boxes
+ * between current box, "root", and the block formatting context
+ * box, "fp", for float children of "root"
+ */
+static void
+layout_position_relative(struct box *root, struct box *fp, int fx, int fy)
{
- bool first_line = true;
- bool has_text_children;
- struct box *c, *next;
- int y = 0;
- int curwidth,maxwidth = width;
+ struct box *box; /* for children of "root" */
+ struct box *fn; /* for block formatting context box for children of
+ * "box" */
+ struct box *fc; /* for float children of the block formatting context,
+ * "fp" */
+ int x, y; /* for the offsets resulting from any relative
+ * positioning on the current block */
+ int fnx, fny; /* for affsets which apply to flat children of "box" */
- assert(inline_container->type == BOX_INLINE_CONTAINER);
+ /**\todo ensure containing box is large enough after moving boxes */
- NSLOG(layout, DEBUG,
- "inline_container %p, width %i, cont %p, cx %i, cy %i",
- inline_container,
- width,
- cont,
- cx,
- cy);
+ assert(root);
+ /* Normal children */
+ for (box = root->children; box; box = box->next) {
- has_text_children = false;
- for (c = inline_container->children; c; c = c->next) {
- bool is_pre = false;
+ if (box->type == BOX_TEXT)
+ continue;
- if (c->style) {
- enum css_white_space_e whitespace;
+ /* If relatively positioned, get offsets */
+ if (box->style && css_computed_position(box->style) ==
+ CSS_POSITION_RELATIVE)
+ layout_compute_relative_offset(box, &x, &y);
+ else
+ x = y = 0;
- whitespace = css_computed_white_space(c->style);
+ /* Adjust float coordinates.
+ * (note float x and y are relative to their block formatting
+ * context box and not their parent) */
+ if (box->style && (css_computed_float(box->style) ==
+ CSS_FLOAT_LEFT ||
+ css_computed_float(box->style) ==
+ CSS_FLOAT_RIGHT) &&
+ (fx != 0 || fy != 0)) {
+ /* box is a float and there is a float offset to
+ * apply */
+ for (fc = fp->float_children; fc; fc = fc->next_float) {
+ if (box == fc->children) {
+ /* Box is floated in the block
+ * formatting context block, fp.
+ * Apply float offsets. */
+ box->x += fx;
+ box->y += fy;
+ fx = fy = 0;
+ }
+ }
+ }
- is_pre = (whitespace == CSS_WHITE_SPACE_PRE ||
- whitespace == CSS_WHITE_SPACE_PRE_LINE ||
- whitespace == CSS_WHITE_SPACE_PRE_WRAP);
+ if (box->float_children) {
+ fn = box;
+ fnx = fny = 0;
+ } else {
+ fn = fp;
+ fnx = fx + x;
+ fny = fy + y;
}
- if ((!c->object && !(c->flags & REPLACE_DIM) &&
- !(c->flags & IFRAME) &&
- c->text && (c->length || is_pre)) ||
- c->type == BOX_BR)
- has_text_children = true;
+ /* recurse first */
+ layout_position_relative(box, fn, fnx, fny);
+
+ /* Ignore things we're not interested in. */
+ if (!box->style || (box->style &&
+ css_computed_position(box->style) !=
+ CSS_POSITION_RELATIVE))
+ continue;
+
+ box->x += x;
+ box->y += y;
+
+ /* Handle INLINEs - their "children" are in fact
+ * the sibling boxes between the INLINE and
+ * INLINE_END boxes */
+ if (box->type == BOX_INLINE && box->inline_end) {
+ struct box *b;
+ for (b = box->next; b && b != box->inline_end;
+ b = b->next) {
+ b->x += x;
+ b->y += y;
+ }
+ }
}
+}
- /** \todo fix wrapping so that a box with horizontal scrollbar will
- * shrink back to 'width' if no word is wider than 'width' (Or just set
- * curwidth = width and have the multiword lines wrap to the min width)
- */
- for (c = inline_container->children; c; ) {
- NSLOG(layout, DEBUG, "c %p", c);
+/* exported function documented in render/layout.h */
+bool layout_document(html_content *content, int width, int height)
+{
+ bool ret;
+ struct box *doc = content->layout;
+ const struct gui_layout_table *font_func = content->font_func;
- curwidth = inline_container->width;
- if (!layout_line(c, &curwidth, &y, cx, cy + y, cont, first_line,
- has_text_children, content, &next))
- return false;
- maxwidth = max(maxwidth,curwidth);
- c = next;
- first_line = false;
+ layout_minmax_block(doc, font_func);
+
+ layout_block_find_dimensions(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 +
+ doc->padding[LEFT] + doc->padding[RIGHT] +
+ doc->border[RIGHT].width + doc->margin[RIGHT];
+ if (width < 0) {
+ width = 0;
}
+ doc->width = width;
- inline_container->width = maxwidth;
- inline_container->height = y;
+ ret = layout_block_context(doc, height, content);
- return true;
+ /* make <html> and <body> fill available height */
+ if (doc->y + doc->padding[TOP] + doc->height + doc->padding[BOTTOM] +
+ doc->border[BOTTOM].width + doc->margin[BOTTOM] <
+ height) {
+ doc->height = height - (doc->y + doc->padding[TOP] +
+ doc->padding[BOTTOM] +
+ doc->border[BOTTOM].width +
+ doc->margin[BOTTOM]);
+ if (doc->children)
+ doc->children->height = doc->height -
+ (doc->children->margin[TOP] +
+ doc->children->border[TOP].width +
+ doc->children->padding[TOP] +
+ doc->children->padding[BOTTOM] +
+ doc->children->border[BOTTOM].width +
+ doc->children->margin[BOTTOM]);
+ }
+
+ layout_lists(doc, font_func);
+ layout_position_absolute(doc, doc, 0, 0, content);
+ layout_position_relative(doc, doc, 0, 0);
+
+ layout_calculate_descendant_bboxes(doc);
+
+ return ret;
}
diff --git a/render/layout.h b/render/layout.h
index 7a579ca..0aa0da3 100644
--- a/render/layout.h
+++ b/render/layout.h
@@ -43,19 +43,6 @@ struct gui_layout_table;
bool layout_document(struct html_content *content, int width, int height);
/**
- * Layout lines of text or inline boxes with floats.
- *
- * \param box inline container box
- * \param width horizontal space available
- * \param cont ancestor box which defines horizontal space, for floats
- * \param cx box position relative to cont
- * \param cy box position relative to cont
- * \param content memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- */
-bool layout_inline_container(struct box *box, int width, struct box *cont, int cx, int cy, struct html_content *content);
-
-/**
* Recursively calculate the descendant_[xy][01] values for a laid-out box tree
* and inform iframe browser windows of their size and position.
*
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=526725d9efdc34a9438...
commit 526725d9efdc34a9438670b54147a1fd72234c7d
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Layout: No need to expose layout_minmax_table().
diff --git a/render/layout.c b/render/layout.c
index 7ca688f..fa49667 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -286,6 +286,181 @@ calculate_mbp_width(const css_computed_style *style,
/**
+ * Calculate minimum and maximum width of a table.
+ *
+ * \param table box of type TABLE
+ * \param font_func Font functions
+ * \param content The HTML content being layed 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)
+{
+ 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 box *row_group, *row, *cell;
+ enum css_width_e wtype;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ /* check if the widths have already been calculated */
+ if (table->max_width != UNKNOWN_MAX_WIDTH)
+ return;
+
+ /* start with 0 except for fixed-width columns */
+ for (i = 0; i != table->columns; i++) {
+ if (col[i].type == COLUMN_WIDTH_FIXED)
+ col[i].min = col[i].max = col[i].width;
+ else
+ col[i].min = col[i].max = 0;
+ }
+
+ /* border-spacing is used in the separated borders model */
+ if (css_computed_border_collapse(table->style) ==
+ CSS_BORDER_COLLAPSE_SEPARATE) {
+ css_fixed h = 0, v = 0;
+ css_unit hu = CSS_UNIT_PX, vu = CSS_UNIT_PX;
+
+ css_computed_border_spacing(table->style, &h, &hu, &v, &vu);
+
+ border_spacing_h = FIXTOINT(nscss_len2px(h, hu, table->style));
+ }
+
+ /* 1st pass: consider cells with colspan 1 only */
+ for (row_group = table->children; row_group; row_group =row_group->next)
+ for (row = row_group->children; row; row = row->next)
+ for (cell = row->children; cell; cell = cell->next) {
+ assert(cell->type == BOX_TABLE_CELL);
+ assert(cell->style);
+ /** TODO: Handle colspan="0" correctly.
+ * It's currently converted to 1 in box normaisation */
+ assert(cell->columns != 0);
+
+ if (cell->columns != 1)
+ continue;
+
+ layout_minmax_block(cell, font_func);
+ i = cell->start_column;
+
+ if (col[i].positioned)
+ continue;
+
+ /* update column min, max widths using cell widths */
+ if (col[i].min < cell->min_width)
+ col[i].min = cell->min_width;
+ if (col[i].max < cell->max_width)
+ col[i].max = cell->max_width;
+ }
+
+ /* 2nd pass: cells which span multiple columns */
+ for (row_group = table->children; row_group; row_group =row_group->next)
+ for (row = row_group->children; row; row = row->next)
+ for (cell = row->children; cell; cell = cell->next) {
+ unsigned int flexible_columns = 0;
+ int min = 0, max = 0, fixed_width = 0, extra;
+
+ if (cell->columns == 1)
+ continue;
+
+ layout_minmax_block(cell, font_func);
+ i = cell->start_column;
+
+ /* find min width so far of spanned columns, and count
+ * number of non-fixed spanned columns and total fixed width */
+ for (j = 0; j != cell->columns; j++) {
+ min += col[i + j].min;
+ if (col[i + j].type == COLUMN_WIDTH_FIXED)
+ fixed_width += col[i + j].width;
+ else
+ flexible_columns++;
+ }
+ min += (cell->columns - 1) * border_spacing_h;
+
+ /* distribute extra min to spanned columns */
+ if (min < cell->min_width) {
+ if (flexible_columns == 0) {
+ extra = 1 + (cell->min_width - min) /
+ cell->columns;
+ for (j = 0; j != cell->columns; j++) {
+ col[i + j].min += extra;
+ if (col[i + j].max < col[i + j].min)
+ col[i + j].max = col[i + j].min;
+ }
+ } else {
+ extra = 1 + (cell->min_width - min) /
+ flexible_columns;
+ for (j = 0; j != cell->columns; j++) {
+ if (col[i + j].type !=
+ COLUMN_WIDTH_FIXED) {
+ col[i + j].min += extra;
+ if (col[i + j].max <
+ col[i + j].min)
+ col[i + j].max =
+ col[i + j].min;
+ }
+ }
+ }
+ }
+
+ /* find max width so far of spanned columns */
+ for (j = 0; j != cell->columns; j++)
+ max += col[i + j].max;
+ max += (cell->columns - 1) * border_spacing_h;
+
+ /* distribute extra max to spanned columns */
+ if (max < cell->max_width && flexible_columns) {
+ extra = 1 + (cell->max_width - max) / flexible_columns;
+ for (j = 0; j != cell->columns; j++)
+ if (col[i + j].type != COLUMN_WIDTH_FIXED)
+ col[i + j].max += extra;
+ }
+ }
+
+ for (i = 0; i != table->columns; i++) {
+ if (col[i].max < col[i].min) {
+ box_dump(stderr, table, 0, true);
+ assert(0);
+ }
+ table_min += col[i].min;
+ table_max += col[i].max;
+ }
+
+ /* 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));
+ if (table_min < width)
+ table_min = width;
+ if (table_max < width)
+ table_max = width;
+ }
+
+ /* add margins, border, padding to min, max widths */
+ calculate_mbp_width(table->style, LEFT, true, true, true,
+ &extra_fixed, &extra_frac);
+ calculate_mbp_width(table->style, RIGHT, true, true, true,
+ &extra_fixed, &extra_frac);
+ if (extra_fixed < 0)
+ extra_fixed = 0;
+ if (extra_frac < 0)
+ extra_frac = 0;
+ if (1.0 <= extra_frac)
+ extra_frac = 0.9;
+ table->min_width = (table_min + extra_fixed) / (1.0 - extra_frac);
+ table->max_width = (table_max + extra_fixed) / (1.0 - extra_frac);
+ table->min_width += (table->columns + 1) * border_spacing_h;
+ table->max_width += (table->columns + 1) * border_spacing_h;
+
+ assert(0 <= table->min_width && table->min_width <= table->max_width);
+}
+
+
+/**
* Calculate minimum and maximum width of a line.
*
* \param first a box in an inline container
@@ -4926,173 +5101,6 @@ bool layout_inline_container(struct box *inline_container, int width,
}
-/* exported function documented in render/layout.h */
-void
-layout_minmax_table(struct box *table, const struct gui_layout_table *font_func)
-{
- 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 box *row_group, *row, *cell;
- enum css_width_e wtype;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- /* check if the widths have already been calculated */
- if (table->max_width != UNKNOWN_MAX_WIDTH)
- return;
-
- /* start with 0 except for fixed-width columns */
- for (i = 0; i != table->columns; i++) {
- if (col[i].type == COLUMN_WIDTH_FIXED)
- col[i].min = col[i].max = col[i].width;
- else
- col[i].min = col[i].max = 0;
- }
-
- /* border-spacing is used in the separated borders model */
- if (css_computed_border_collapse(table->style) ==
- CSS_BORDER_COLLAPSE_SEPARATE) {
- css_fixed h = 0, v = 0;
- css_unit hu = CSS_UNIT_PX, vu = CSS_UNIT_PX;
-
- css_computed_border_spacing(table->style, &h, &hu, &v, &vu);
-
- border_spacing_h = FIXTOINT(nscss_len2px(h, hu, table->style));
- }
-
- /* 1st pass: consider cells with colspan 1 only */
- for (row_group = table->children; row_group; row_group =row_group->next)
- for (row = row_group->children; row; row = row->next)
- for (cell = row->children; cell; cell = cell->next) {
- assert(cell->type == BOX_TABLE_CELL);
- assert(cell->style);
- /** TODO: Handle colspan="0" correctly.
- * It's currently converted to 1 in box normaisation */
- assert(cell->columns != 0);
-
- if (cell->columns != 1)
- continue;
-
- layout_minmax_block(cell, font_func);
- i = cell->start_column;
-
- if (col[i].positioned)
- continue;
-
- /* update column min, max widths using cell widths */
- if (col[i].min < cell->min_width)
- col[i].min = cell->min_width;
- if (col[i].max < cell->max_width)
- col[i].max = cell->max_width;
- }
-
- /* 2nd pass: cells which span multiple columns */
- for (row_group = table->children; row_group; row_group =row_group->next)
- for (row = row_group->children; row; row = row->next)
- for (cell = row->children; cell; cell = cell->next) {
- unsigned int flexible_columns = 0;
- int min = 0, max = 0, fixed_width = 0, extra;
-
- if (cell->columns == 1)
- continue;
-
- layout_minmax_block(cell, font_func);
- i = cell->start_column;
-
- /* find min width so far of spanned columns, and count
- * number of non-fixed spanned columns and total fixed width */
- for (j = 0; j != cell->columns; j++) {
- min += col[i + j].min;
- if (col[i + j].type == COLUMN_WIDTH_FIXED)
- fixed_width += col[i + j].width;
- else
- flexible_columns++;
- }
- min += (cell->columns - 1) * border_spacing_h;
-
- /* distribute extra min to spanned columns */
- if (min < cell->min_width) {
- if (flexible_columns == 0) {
- extra = 1 + (cell->min_width - min) /
- cell->columns;
- for (j = 0; j != cell->columns; j++) {
- col[i + j].min += extra;
- if (col[i + j].max < col[i + j].min)
- col[i + j].max = col[i + j].min;
- }
- } else {
- extra = 1 + (cell->min_width - min) /
- flexible_columns;
- for (j = 0; j != cell->columns; j++) {
- if (col[i + j].type !=
- COLUMN_WIDTH_FIXED) {
- col[i + j].min += extra;
- if (col[i + j].max <
- col[i + j].min)
- col[i + j].max =
- col[i + j].min;
- }
- }
- }
- }
-
- /* find max width so far of spanned columns */
- for (j = 0; j != cell->columns; j++)
- max += col[i + j].max;
- max += (cell->columns - 1) * border_spacing_h;
-
- /* distribute extra max to spanned columns */
- if (max < cell->max_width && flexible_columns) {
- extra = 1 + (cell->max_width - max) / flexible_columns;
- for (j = 0; j != cell->columns; j++)
- if (col[i + j].type != COLUMN_WIDTH_FIXED)
- col[i + j].max += extra;
- }
- }
-
- for (i = 0; i != table->columns; i++) {
- if (col[i].max < col[i].min) {
- box_dump(stderr, table, 0, true);
- assert(0);
- }
- table_min += col[i].min;
- table_max += col[i].max;
- }
-
- /* 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));
- if (table_min < width)
- table_min = width;
- if (table_max < width)
- table_max = width;
- }
-
- /* add margins, border, padding to min, max widths */
- calculate_mbp_width(table->style, LEFT, true, true, true,
- &extra_fixed, &extra_frac);
- calculate_mbp_width(table->style, RIGHT, true, true, true,
- &extra_fixed, &extra_frac);
- if (extra_fixed < 0)
- extra_fixed = 0;
- if (extra_frac < 0)
- extra_frac = 0;
- if (1.0 <= extra_frac)
- extra_frac = 0.9;
- table->min_width = (table_min + extra_fixed) / (1.0 - extra_frac);
- table->max_width = (table_max + extra_fixed) / (1.0 - extra_frac);
- table->min_width += (table->columns + 1) * border_spacing_h;
- table->max_width += (table->columns + 1) * border_spacing_h;
-
- assert(0 <= table->min_width && table->min_width <= table->max_width);
-}
-
-
/**
* Find a box's bounding box relative to itself, i.e. the box's border edge box
*
diff --git a/render/layout.h b/render/layout.h
index 78a3002..7a579ca 100644
--- a/render/layout.h
+++ b/render/layout.h
@@ -63,14 +63,4 @@ bool layout_inline_container(struct box *box, int width, struct box *cont, int c
*/
void layout_calculate_descendant_bboxes(struct box *box);
-/**
- * Calculate minimum and maximum width of a table.
- *
- * \param table box of type TABLE
- * \param font_func Font functions
- * \post table->min_width and table->max_width filled in,
- * 0 <= table->min_width <= table->max_width
- */
-void layout_minmax_table(struct box *table, const struct gui_layout_table *font_func);
-
#endif
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d372480fd76b521d14d...
commit d372480fd76b521d14dd31190d198fe73cd85598
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
CSS computed style composition: Update for new CSS units.
Since the nscss_compute_font_size callback now needs to convert
new units to absolute values, and some of these units require info
from the root element's style, there are knock-on changes to ensure
that the required info is available where its needed.
diff --git a/content/handlers/css/select.c b/content/handlers/css/select.c
index 328d6a7..d8827ec 100644
--- a/content/handlers/css/select.c
+++ b/content/handlers/css/select.c
@@ -278,7 +278,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
* element's style */
error = css_computed_style_compose(ctx->parent_style,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
- nscss_compute_font_size, NULL,
+ nscss_compute_font_size, ctx,
&composed);
if (error != CSS_OK) {
css_select_results_destroy(styles);
@@ -310,7 +310,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
error = css_computed_style_compose(
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
styles->styles[pseudo_element],
- nscss_compute_font_size, NULL,
+ nscss_compute_font_size, ctx,
&composed);
if (error != CSS_OK) {
/* TODO: perhaps this shouldn't be quite so
@@ -349,7 +349,7 @@ css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
/* TODO: Do we really need to compose? Initial style shouldn't
* have any inherited properties. */
error = css_computed_style_compose(parent, partial,
- nscss_compute_font_size, NULL, &composed);
+ nscss_compute_font_size, ctx, &composed);
css_computed_style_destroy(partial);
if (error != CSS_OK) {
css_computed_style_destroy(composed);
@@ -422,14 +422,37 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent,
FDIV(parent_size.value, FLTTOFIX(1.2));
size->data.length.unit = parent_size.unit;
} else if (size->data.length.unit == CSS_UNIT_EM ||
- size->data.length.unit == CSS_UNIT_EX) {
+ size->data.length.unit == CSS_UNIT_EX ||
+ size->data.length.unit == CSS_UNIT_CAP ||
+ size->data.length.unit == CSS_UNIT_CH ||
+ size->data.length.unit == CSS_UNIT_IC) {
size->data.length.value =
FMUL(size->data.length.value, parent_size.value);
- if (size->data.length.unit == CSS_UNIT_EX) {
+ switch (size->data.length.unit) {
+ case CSS_UNIT_EX:
/* 1ex = 0.6em in NetSurf */
size->data.length.value = FMUL(size->data.length.value,
FLTTOFIX(0.6));
+ break;
+ case CSS_UNIT_CAP:
+ /* Height of captals. 1cap = 0.9em in NetSurf. */
+ size->data.length.value = FMUL(size->data.length.value,
+ FLTTOFIX(0.9));
+ break;
+ case CSS_UNIT_CH:
+ /* Width of '0'. 1ch = 0.4em in NetSurf. */
+ size->data.length.value = FMUL(size->data.length.value,
+ FLTTOFIX(0.4));
+ break;
+ case CSS_UNIT_IC:
+ /* Width of U+6C43. 1ic = 1.1em in NetSurf. */
+ size->data.length.value = FMUL(size->data.length.value,
+ FLTTOFIX(1.1));
+ break;
+ default:
+ /* No scaling required for EM. */
+ break;
}
size->data.length.unit = parent_size.unit;
@@ -437,6 +460,22 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent,
size->data.length.value = FDIV(FMUL(size->data.length.value,
parent_size.value), INTTOFIX(100));
size->data.length.unit = parent_size.unit;
+ } else if (size->data.length.unit == CSS_UNIT_REM) {
+ nscss_select_ctx *ctx = pw;
+ if (parent == NULL) {
+ size->data.length.value = parent_size.value;
+ size->data.length.unit = parent_size.unit;
+ } else {
+ css_computed_font_size(ctx->root_style,
+ &size->data.length.value,
+ &size->data.length.unit);
+ }
+ } else if (size->data.length.unit == CSS_UNIT_RLH) {
+ /** TODO: Convert root element line-height to absolute value. */
+ size->data.length.value = FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10));
+ size->data.length.unit = CSS_UNIT_PT;
}
size->status = CSS_FONT_SIZE_DIMENSION;
diff --git a/content/handlers/css/select.h b/content/handlers/css/select.h
index abfb858..9fa6d3a 100644
--- a/content/handlers/css/select.h
+++ b/content/handlers/css/select.h
@@ -37,6 +37,7 @@ typedef struct nscss_select_ctx
bool quirks;
struct nsurl *base_url;
lwc_string *universal;
+ const css_computed_style *root_style;
const css_computed_style *parent_style;
} nscss_select_ctx;
diff --git a/render/box.h b/render/box.h
index 2800d40..8208a6f 100644
--- a/render/box.h
+++ b/render/box.h
@@ -356,6 +356,9 @@ bool box_hscrollbar_present(const struct box *box);
nserror dom_to_box(struct dom_node *n, struct html_content *c,
box_construct_complete_cb cb);
-bool box_normalise_block(struct box *block, struct html_content *c);
+bool box_normalise_block(
+ struct box *block,
+ const struct box *root,
+ struct html_content *c);
#endif
diff --git a/render/box_construct.c b/render/box_construct.c
index 1982622..1aa99e2 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -104,7 +104,8 @@ static bool box_construct_element(struct box_construct_ctx *ctx,
static void box_construct_element_after(dom_node *n, html_content *content);
static bool box_construct_text(struct box_construct_ctx *ctx);
static css_select_results * box_get_style(html_content *c,
- const css_computed_style *parent_style, dom_node *n);
+ const css_computed_style *parent_style,
+ const css_computed_style *root_style, dom_node *n);
static void box_text_transform(char *s, unsigned int len,
enum css_text_transform_e tt);
#define BOX_SPECIAL_PARAMS dom_node *n, html_content *content, \
@@ -429,7 +430,8 @@ void convert_xml_to_box(struct box_construct_ctx *ctx)
root.children->parent = &root;
/** \todo Remove box_normalise_block */
- if (box_normalise_block(&root, ctx->content) == false) {
+ if (box_normalise_block(&root, ctx->root_box,
+ ctx->content) == false) {
ctx->cb(ctx->content, false);
} else {
ctx->content->layout = root.children;
@@ -741,6 +743,7 @@ bool box_construct_element(struct box_construct_ctx *ctx,
lwc_string *bgimage_uri;
dom_exception err;
struct box_construct_props props;
+ const css_computed_style *root_style = NULL;
assert(ctx->n != NULL);
@@ -753,7 +756,12 @@ bool box_construct_element(struct box_construct_ctx *ctx,
props.containing_block->flags &= ~PRE_STRIP;
}
- styles = box_get_style(ctx->content, props.parent_style, ctx->n);
+ if (props.node_is_root == false) {
+ root_style = ctx->root_box->style;
+ }
+
+ styles = box_get_style(ctx->content, props.parent_style, root_style,
+ ctx->n);
if (styles == NULL)
return false;
@@ -1321,13 +1329,15 @@ bool box_construct_text(struct box_construct_ctx *ctx)
/**
* Get the style for an element.
*
- * \param c content of type CONTENT_HTML that is being processed
+ * \param c content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree, or NULL for root
- * \param n node in xml tree
+ * \param root_style root node's style, or NULL for root
+ * \param n node in xml tree
* \return the new style, or NULL on memory exhaustion
*/
css_select_results *box_get_style(html_content *c,
- const css_computed_style *parent_style, dom_node *n)
+ const css_computed_style *parent_style,
+ const css_computed_style *root_style, dom_node *n)
{
dom_string *s;
dom_exception err;
@@ -1359,6 +1369,7 @@ css_select_results *box_get_style(html_content *c,
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
+ ctx.root_style = root_style;
ctx.parent_style = parent_style;
/* Select style for element */
diff --git a/render/box_normalise.c b/render/box_normalise.c
index 9f78f75..9c0875b 100644
--- a/render/box_normalise.c
+++ b/render/box_normalise.c
@@ -65,24 +65,38 @@ struct columns {
};
-static bool box_normalise_table(struct box *table, html_content *c);
-static bool box_normalise_table_spans(struct box *table,
- struct span_info *spans, html_content *c);
-static bool box_normalise_table_row_group(struct box *row_group,
+static bool box_normalise_table(
+ struct box *table,
+ const struct box *root,
+ html_content *c);
+static bool box_normalise_table_spans(
+ struct box *table,
+ const struct box *root,
+ struct span_info *spans,
+ html_content *c);
+static bool box_normalise_table_row_group(
+ struct box *row_group,
+ const struct box *root,
struct columns *col_info,
html_content *c);
-static bool box_normalise_table_row(struct box *row,
+static bool box_normalise_table_row(
+ struct box *row,
+ const struct box *root,
struct columns *col_info,
html_content *c);
static bool calculate_table_row(struct columns *col_info,
unsigned int col_span, unsigned int row_span,
unsigned int *start_column, struct box *cell);
-static bool box_normalise_inline_container(struct box *cont, html_content *c);
+static bool box_normalise_inline_container(
+ struct box *cont,
+ const struct box *root,
+ html_content *c);
/**
* Ensure the box tree is correctly nested by adding and removing nodes.
*
* \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
+ * \param root root box of document
* \param c content of boxes
* \return true on success, false on memory exhaustion
*
@@ -100,7 +114,10 @@ static bool box_normalise_inline_container(struct box *cont, html_content *c);
* \endcode
*/
-bool box_normalise_block(struct box *block, html_content *c)
+bool box_normalise_block(
+ struct box *block,
+ const struct box *root,
+ html_content *c)
{
struct box *child;
struct box *next_child;
@@ -109,6 +126,9 @@ bool box_normalise_block(struct box *block, html_content *c)
nscss_select_ctx ctx;
assert(block != NULL);
+ assert(root != NULL);
+
+ ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type);
@@ -128,15 +148,15 @@ bool box_normalise_block(struct box *block, html_content *c)
switch (child->type) {
case BOX_BLOCK:
/* ok */
- if (box_normalise_block(child, c) == false)
+ if (box_normalise_block(child, root, c) == false)
return false;
break;
case BOX_INLINE_CONTAINER:
- if (box_normalise_inline_container(child, c) == false)
+ if (box_normalise_inline_container(child, root, c) == false)
return false;
break;
case BOX_TABLE:
- if (box_normalise_table(child, c) == false)
+ if (box_normalise_table(child, root, c) == false)
return false;
break;
case BOX_INLINE:
@@ -199,7 +219,7 @@ bool box_normalise_block(struct box *block, html_content *c)
block->last = table;
table->parent = block;
- if (box_normalise_table(table, c) == false)
+ if (box_normalise_table(table, root, c) == false)
return false;
break;
default:
@@ -211,7 +231,10 @@ bool box_normalise_block(struct box *block, html_content *c)
}
-bool box_normalise_table(struct box *table, html_content * c)
+bool box_normalise_table(
+ struct box *table,
+ const struct box *root,
+ html_content * c)
{
struct box *child;
struct box *next_child;
@@ -223,6 +246,8 @@ bool box_normalise_table(struct box *table, html_content * c)
assert(table != NULL);
assert(table->type == BOX_TABLE);
+ ctx.root_style = root->style;
+
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO, "table %p", table);
#endif
@@ -243,7 +268,7 @@ bool box_normalise_table(struct box *table, html_content * c)
switch (child->type) {
case BOX_TABLE_ROW_GROUP:
/* ok */
- if (box_normalise_table_row_group(child,
+ if (box_normalise_table_row_group(child, root,
&col_info, c) == false) {
free(col_info.spans);
return false;
@@ -308,7 +333,7 @@ bool box_normalise_table(struct box *table, html_content * c)
table->last = row_group;
row_group->parent = table;
- if (box_normalise_table_row_group(row_group,
+ if (box_normalise_table_row_group(row_group, root,
&col_info, c) == false) {
free(col_info.spans);
return false;
@@ -390,7 +415,7 @@ bool box_normalise_table(struct box *table, html_content * c)
table->rows = 1;
}
- if (box_normalise_table_spans(table, col_info.spans, c) == false) {
+ if (box_normalise_table_spans(table, root, col_info.spans, c) == false) {
free(col_info.spans);
return false;
}
@@ -413,12 +438,16 @@ bool box_normalise_table(struct box *table, html_content * c)
* Additionally, generate empty cells.
*
* \param table Table to process
+ * \param root root box of document
* \param spans Array of length table->columns for use in empty cell detection
* \param c Content containing table
* \return True on success, false on memory exhaustion.
*/
-bool box_normalise_table_spans(struct box *table, struct span_info *spans,
+bool box_normalise_table_spans(
+ struct box *table,
+ const struct box *root,
+ struct span_info *spans,
html_content *c)
{
struct box *table_row_group;
@@ -429,6 +458,8 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans,
unsigned int col;
nscss_select_ctx ctx;
+ ctx.root_style = root->style;
+
/* Clear span data */
memset(spans, 0, table->columns * sizeof(struct span_info));
@@ -572,7 +603,9 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans,
}
-bool box_normalise_table_row_group(struct box *row_group,
+bool box_normalise_table_row_group(
+ struct box *row_group,
+ const struct box *root,
struct columns *col_info,
html_content * c)
{
@@ -586,6 +619,8 @@ bool box_normalise_table_row_group(struct box *row_group,
assert(row_group != 0);
assert(row_group->type == BOX_TABLE_ROW_GROUP);
+ ctx.root_style = root->style;
+
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO, "row_group %p", row_group);
#endif
@@ -597,7 +632,7 @@ bool box_normalise_table_row_group(struct box *row_group,
case BOX_TABLE_ROW:
/* ok */
group_row_count++;
- if (box_normalise_table_row(child, col_info,
+ if (box_normalise_table_row(child, root, col_info,
c) == false)
return false;
break;
@@ -657,7 +692,7 @@ bool box_normalise_table_row_group(struct box *row_group,
row->parent = row_group;
group_row_count++;
- if (box_normalise_table_row(row, col_info,
+ if (box_normalise_table_row(row, root, col_info,
c) == false)
return false;
break;
@@ -722,7 +757,9 @@ bool box_normalise_table_row_group(struct box *row_group,
}
-bool box_normalise_table_row(struct box *row,
+bool box_normalise_table_row(
+ struct box *row,
+ const struct box *root,
struct columns *col_info,
html_content * c)
{
@@ -736,6 +773,8 @@ bool box_normalise_table_row(struct box *row,
assert(row != NULL);
assert(row->type == BOX_TABLE_ROW);
+ ctx.root_style = root->style;
+
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO, "row %p", row);
#endif
@@ -746,7 +785,7 @@ bool box_normalise_table_row(struct box *row,
switch (child->type) {
case BOX_TABLE_CELL:
/* ok */
- if (box_normalise_block(child, c) == false)
+ if (box_normalise_block(child, root, c) == false)
return false;
cell = child;
break;
@@ -805,7 +844,7 @@ bool box_normalise_table_row(struct box *row,
row->last = cell;
cell->parent = row;
- if (box_normalise_block(cell, c) == false)
+ if (box_normalise_block(cell, root, c) == false)
return false;
break;
case BOX_INLINE:
@@ -928,7 +967,10 @@ bool calculate_table_row(struct columns *col_info,
}
-bool box_normalise_inline_container(struct box *cont, html_content * c)
+bool box_normalise_inline_container(
+ struct box *cont,
+ const struct box *root,
+ html_content * c)
{
struct box *child;
struct box *next_child;
@@ -951,7 +993,7 @@ bool box_normalise_inline_container(struct box *cont, html_content * c)
break;
case BOX_INLINE_BLOCK:
/* ok */
- if (box_normalise_block(child, c) == false)
+ if (box_normalise_block(child, root, c) == false)
return false;
break;
case BOX_FLOAT_LEFT:
@@ -961,12 +1003,12 @@ bool box_normalise_inline_container(struct box *cont, html_content * c)
switch (child->children->type) {
case BOX_BLOCK:
- if (box_normalise_block(child->children,
+ if (box_normalise_block(child->children, root,
c) == false)
return false;
break;
case BOX_TABLE:
- if (box_normalise_table(child->children,
+ if (box_normalise_table(child->children, root,
c) == false)
return false;
break;
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d1c656b55f7c21b5fb9...
commit d1c656b55f7c21b5fb96bf5e1bd8fedaa55c4fc2
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
CSS: Add new libcss unit types to computed style dump.
diff --git a/content/handlers/css/dump.c b/content/handlers/css/dump.c
index 529bd4a..b12e1d9 100644
--- a/content/handlers/css/dump.c
+++ b/content/handlers/css/dump.c
@@ -113,6 +113,45 @@ static void dump_css_unit(FILE *stream, css_fixed val, css_unit unit)
case CSS_UNIT_KHZ:
fprintf(stream, "kHz");
break;
+ case CSS_UNIT_CAP:
+ fprintf(stream, "cap");
+ break;
+ case CSS_UNIT_CH:
+ fprintf(stream, "ch");
+ break;
+ case CSS_UNIT_IC:
+ fprintf(stream, "ic");
+ break;
+ case CSS_UNIT_REM:
+ fprintf(stream, "rem");
+ break;
+ case CSS_UNIT_LH:
+ fprintf(stream, "lh");
+ break;
+ case CSS_UNIT_RLH:
+ fprintf(stream, "rlh");
+ break;
+ case CSS_UNIT_VH:
+ fprintf(stream, "vh");
+ break;
+ case CSS_UNIT_VW:
+ fprintf(stream, "vw");
+ break;
+ case CSS_UNIT_VI:
+ fprintf(stream, "vi");
+ break;
+ case CSS_UNIT_VB:
+ fprintf(stream, "vb");
+ break;
+ case CSS_UNIT_VMIN:
+ fprintf(stream, "vmin");
+ break;
+ case CSS_UNIT_VMAX:
+ fprintf(stream, "vmax");
+ break;
+ case CSS_UNIT_Q:
+ fprintf(stream, "q");
+ break;
}
}
-----------------------------------------------------------------------
--
NetSurf Browser
5 years, 4 months
netsurf: branch master updated. release/3.7-37-g7bd1fb5
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/7bd1fb50c6415a21fae22...
...commit http://git.netsurf-browser.org/netsurf.git/commit/7bd1fb50c6415a21fae22f7...
...tree http://git.netsurf-browser.org/netsurf.git/tree/7bd1fb50c6415a21fae22f7bd...
The branch, master has been updated
via 7bd1fb50c6415a21fae22f7bd534894e02b512bf (commit)
from fdaad39a57029971f0663b402d6335527f7a6039 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=7bd1fb50c6415a21fae...
commit 7bd1fb50c6415a21fae22f7bd534894e02b512bf
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Utils: Filename: Squash warning: -Wformat-truncation=
We need to check the snprintf return value, or GCC7 whinges:
warning: ‘snprintf’ output may be truncated before the last
format character [-Wformat-truncation=]
diff --git a/utils/filename.c b/utils/filename.c
index 01a403f..f0e1bb0 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -272,15 +272,19 @@ bool filename_flush_directory(const char *folder, int depth)
parent = opendir(folder);
while ((entry = readdir(parent))) {
- struct stat statbuf;
+ int written;
+ struct stat statbuf;
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
@@ -383,16 +387,21 @@ bool filename_delete_recursive(char *folder)
parent = opendir(folder);
while ((entry = readdir(parent))) {
+ int written;
+
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
- NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
+ NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
strerror(errno));
continue;
}
-----------------------------------------------------------------------
Summary of changes:
utils/filename.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/utils/filename.c b/utils/filename.c
index 01a403f..f0e1bb0 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -272,15 +272,19 @@ bool filename_flush_directory(const char *folder, int depth)
parent = opendir(folder);
while ((entry = readdir(parent))) {
- struct stat statbuf;
+ int written;
+ struct stat statbuf;
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
@@ -383,16 +387,21 @@ bool filename_delete_recursive(char *folder)
parent = opendir(folder);
while ((entry = readdir(parent))) {
+ int written;
+
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
- NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
+ NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
strerror(errno));
continue;
}
--
NetSurf Browser
5 years, 5 months