Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14

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=fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14
commit fe0e7e9e9bf288a1051aeb1e808c728fbdeacf14
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    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,
-                                       &current_background_color, bg_box, ctx))
+                                       &current_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,
-                                               &current_background_color, ctx))
+                                               &current_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, &current_background_color, ctx))
+                               first, true, &current_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

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to