Gitweb links:

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

The branch, tlsa/flex has been created
        at  285b25d12e6ce3eaa7da99f3f959b0b3f4943b43 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=285b25d12e6ce3eaa7da99f3f959b0b3f4943b43
commit 285b25d12e6ce3eaa7da99f3f959b0b3f4943b43
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    WIP: flex

diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 8bb329b..e41cc1d 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -16,6 +16,7 @@ S_HTML := box_construct.c     \
        imagemap.c              \
        interaction.c           \
        layout.c                \
+       layout_flex.c           \
        object.c                \
        redraw.c                \
        redraw_border.c         \
diff --git a/content/handlers/html/box.h b/content/handlers/html/box.h
index 1059556..df2b99d 100644
--- a/content/handlers/html/box.h
+++ b/content/handlers/html/box.h
@@ -66,7 +66,9 @@ typedef enum {
        BOX_BR,
        BOX_TEXT,
        BOX_INLINE_END,
-       BOX_NONE
+       BOX_NONE,
+       BOX_FLEX,
+       BOX_INLINE_FLEX,
 } box_type;
 
 
diff --git a/content/handlers/html/box_construct.c 
b/content/handlers/html/box_construct.c
index 52e888e..245aab4 100644
--- a/content/handlers/html/box_construct.c
+++ b/content/handlers/html/box_construct.c
@@ -106,8 +106,8 @@ static const box_type box_map[] = {
        BOX_TABLE_CELL,      /* CSS_DISPLAY_TABLE_CELL */
        BOX_INLINE,          /* CSS_DISPLAY_TABLE_CAPTION */
        BOX_NONE,            /* CSS_DISPLAY_NONE */
-       BOX_BLOCK,           /* CSS_DISPLAY_FLEX */
-       BOX_INLINE_BLOCK,    /* CSS_DISPLAY_INLINE_FLEX */
+       BOX_FLEX,            /* CSS_DISPLAY_FLEX */
+       BOX_INLINE_FLEX,     /* CSS_DISPLAY_INLINE_FLEX */
 };
 
 
@@ -623,6 +623,7 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
                        (box->type == BOX_INLINE ||
                         box->type == BOX_BR ||
                         box->type == BOX_INLINE_BLOCK ||
+                        box->type == BOX_INLINE_FLEX ||
                         css_computed_float(box->style) == CSS_FLOAT_LEFT ||
                         css_computed_float(box->style) == CSS_FLOAT_RIGHT) &&
                        props.node_is_root == false) {
@@ -672,6 +673,7 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
                box->flags |= CONVERT_CHILDREN;
 
        if (box->type == BOX_INLINE || box->type == BOX_BR ||
+                       box->type == BOX_INLINE_FLEX ||
                        box->type == BOX_INLINE_BLOCK) {
                /* Inline container must exist, as we'll have
                 * created it above if it didn't */
diff --git a/content/handlers/html/box_inspect.c 
b/content/handlers/html/box_inspect.c
index b4b1394..73b0981 100644
--- a/content/handlers/html/box_inspect.c
+++ b/content/handlers/html/box_inspect.c
@@ -724,6 +724,14 @@ void box_dump(FILE *stream, struct box *box, unsigned int 
depth, bool style)
                fprintf(stream, "TEXT ");
                break;
 
+       case BOX_FLEX:
+               fprintf(stream, "FLEX ");
+               break;
+
+       case BOX_INLINE_FLEX:
+               fprintf(stream, "INLINE_FLEX ");
+               break;
+
        default:
                fprintf(stream, "Unknown box type ");
        }
diff --git a/content/handlers/html/box_inspect.h 
b/content/handlers/html/box_inspect.h
index b9161f1..a218326 100644
--- a/content/handlers/html/box_inspect.h
+++ b/content/handlers/html/box_inspect.h
@@ -139,5 +139,17 @@ static inline bool box_is_first_child(struct box *b)
        return (b->parent == NULL || b == b->parent->children);
 }
 
+static inline unsigned box_count_children(const struct box *b)
+{
+       const struct box *c = b->children;
+       unsigned count = 0;
+
+       while (c != NULL) {
+               count++;
+               c = c->next;
+       }
+
+       return count;
+}
 
 #endif
diff --git a/content/handlers/html/box_normalise.c 
b/content/handlers/html/box_normalise.c
index 1b6a345..8f25b03 100644
--- a/content/handlers/html/box_normalise.c
+++ b/content/handlers/html/box_normalise.c
@@ -177,6 +177,7 @@ box_normalise_table_row(struct box *row,
                                return false;
                        cell = child;
                        break;
+               case BOX_FLEX:
                case BOX_BLOCK:
                case BOX_INLINE_CONTAINER:
                case BOX_TABLE:
@@ -211,6 +212,7 @@ box_normalise_table_row(struct box *row,
                        cell->prev = child->prev;
 
                        while (child != NULL && (
+                                       child->type == BOX_FLEX ||
                                        child->type == BOX_BLOCK ||
                                        child->type == BOX_INLINE_CONTAINER ||
                                        child->type == BOX_TABLE ||
@@ -238,6 +240,7 @@ box_normalise_table_row(struct box *row,
                        break;
                case BOX_INLINE:
                case BOX_INLINE_END:
+               case BOX_INLINE_FLEX:
                case BOX_INLINE_BLOCK:
                case BOX_FLOAT_LEFT:
                case BOX_FLOAT_RIGHT:
@@ -314,6 +317,7 @@ box_normalise_table_row_group(struct box *row_group,
                                        c) == false)
                                return false;
                        break;
+               case BOX_FLEX:
                case BOX_BLOCK:
                case BOX_INLINE_CONTAINER:
                case BOX_TABLE:
@@ -348,6 +352,7 @@ box_normalise_table_row_group(struct box *row_group,
                        row->prev = child->prev;
 
                        while (child != NULL && (
+                                       child->type == BOX_FLEX ||
                                        child->type == BOX_BLOCK ||
                                        child->type == BOX_INLINE_CONTAINER ||
                                        child->type == BOX_TABLE ||
@@ -377,6 +382,7 @@ box_normalise_table_row_group(struct box *row_group,
                        break;
                case BOX_INLINE:
                case BOX_INLINE_END:
+               case BOX_INLINE_FLEX:
                case BOX_INLINE_BLOCK:
                case BOX_FLOAT_LEFT:
                case BOX_FLOAT_RIGHT:
@@ -648,6 +654,7 @@ box_normalise_table(struct box *table, const struct box 
*root, html_content * c)
                                return false;
                        }
                        break;
+               case BOX_FLEX:
                case BOX_BLOCK:
                case BOX_INLINE_CONTAINER:
                case BOX_TABLE:
@@ -686,6 +693,7 @@ box_normalise_table(struct box *table, const struct box 
*root, html_content * c)
                        row_group->prev = child->prev;
 
                        while (child != NULL && (
+                                       child->type == BOX_FLEX ||
                                        child->type == BOX_BLOCK ||
                                        child->type == BOX_INLINE_CONTAINER ||
                                        child->type == BOX_TABLE ||
@@ -716,6 +724,7 @@ box_normalise_table(struct box *table, const struct box 
*root, html_content * c)
                        break;
                case BOX_INLINE:
                case BOX_INLINE_END:
+               case BOX_INLINE_FLEX:
                case BOX_INLINE_BLOCK:
                case BOX_FLOAT_LEFT:
                case BOX_FLOAT_RIGHT:
@@ -806,6 +815,181 @@ box_normalise_table(struct box *table, const struct box 
*root, html_content * c)
        return true;
 }
 
+static bool box_normalise_flex(
+               struct box *flex_container,
+               const struct box *root,
+               html_content *c)
+{
+       struct box *child;
+       struct box *next_child;
+       struct box *implied_flex_item;
+       css_computed_style *style;
+       nscss_select_ctx ctx;
+
+       assert(flex_container != NULL);
+       assert(root != NULL);
+
+       ctx.root_style = root->style;
+
+#ifdef BOX_NORMALISE_DEBUG
+       NSLOG(netsurf, INFO, "flex_container %p, flex_container->type %u",
+                       flex_container, flex_container->type);
+#endif
+
+       assert(flex_container->type == BOX_FLEX ||
+              flex_container->type == BOX_INLINE_FLEX);
+
+       for (child = flex_container->children; child != NULL; child = 
next_child) {
+#ifdef BOX_NORMALISE_DEBUG
+               NSLOG(netsurf, INFO, "child %p, child->type = %d",
+                               child, child->type);
+#endif
+
+               next_child = child->next;       /* child may be destroyed */
+
+               switch (child->type) {
+               case BOX_FLEX:
+                       /* ok */
+                       if (box_normalise_flex(child, root, c) == false)
+                               return false;
+                       break;
+               case BOX_BLOCK:
+                       /* ok */
+                       if (box_normalise_block(child, root, c) == false)
+                               return false;
+                       break;
+               case BOX_INLINE_CONTAINER:
+                       /* insert implied flex item */
+                       assert(flex_container->style != NULL);
+
+                       ctx.ctx = c->select_ctx;
+                       ctx.quirks = (c->quirks == 
DOM_DOCUMENT_QUIRKS_MODE_FULL);
+                       ctx.base_url = c->base_url;
+                       ctx.universal = c->universal;
+
+                       style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+                                       flex_container->style);
+                       if (style == NULL)
+                               return false;
+
+                       implied_flex_item = box_create(NULL, style, true,
+                                       flex_container->href,
+                                       flex_container->target,
+                                       NULL, NULL, c->bctx);
+                       if (implied_flex_item == NULL) {
+                               css_computed_style_destroy(style);
+                               return false;
+                       }
+                       implied_flex_item->type = BOX_BLOCK;
+
+                       if (child->prev == NULL)
+                               flex_container->children = implied_flex_item;
+                       else
+                               child->prev->next = implied_flex_item;
+
+                       implied_flex_item->prev = child->prev;
+
+                       while (child != NULL &&
+                                       child->type == BOX_INLINE_CONTAINER) {
+                               box_add_child(implied_flex_item, child);
+
+                               next_child = child->next;
+                               child->next = NULL;
+                               child = next_child;
+                       }
+
+                       implied_flex_item->last->next = NULL;
+                       implied_flex_item->next = next_child = child;
+                       if (implied_flex_item->next != NULL)
+                               implied_flex_item->next->prev = 
implied_flex_item;
+                       else
+                               flex_container->last = implied_flex_item;
+                       implied_flex_item->parent = flex_container;
+
+                       if (box_normalise_block(implied_flex_item,
+                                       root, c) == false)
+                               return false;
+                       break;
+
+               case BOX_TABLE:
+                       if (box_normalise_table(child, root, c) == false)
+                               return false;
+                       break;
+               case BOX_INLINE:
+               case BOX_INLINE_END:
+               case BOX_INLINE_FLEX:
+               case BOX_INLINE_BLOCK:
+               case BOX_FLOAT_LEFT:
+               case BOX_FLOAT_RIGHT:
+               case BOX_BR:
+               case BOX_TEXT:
+                       /* should have been wrapped in inline
+                          container by convert_xml_to_box() */
+                       assert(0);
+                       break;
+               case BOX_TABLE_ROW_GROUP:
+               case BOX_TABLE_ROW:
+               case BOX_TABLE_CELL:
+                       /* insert implied table */
+                       assert(flex_container->style != NULL);
+
+                       ctx.ctx = c->select_ctx;
+                       ctx.quirks = (c->quirks == 
DOM_DOCUMENT_QUIRKS_MODE_FULL);
+                       ctx.base_url = c->base_url;
+                       ctx.universal = c->universal;
+
+                       style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+                                       flex_container->style);
+                       if (style == NULL)
+                               return false;
+
+                       implied_flex_item = box_create(NULL, style, true,
+                                       flex_container->href,
+                                       flex_container->target,
+                                       NULL, NULL, c->bctx);
+                       if (implied_flex_item == NULL) {
+                               css_computed_style_destroy(style);
+                               return false;
+                       }
+                       implied_flex_item->type = BOX_TABLE;
+
+                       if (child->prev == NULL)
+                               flex_container->children = implied_flex_item;
+                       else
+                               child->prev->next = implied_flex_item;
+
+                       implied_flex_item->prev = child->prev;
+
+                       while (child != NULL && (
+                                       child->type == BOX_TABLE_ROW_GROUP ||
+                                       child->type == BOX_TABLE_ROW ||
+                                       child->type == BOX_TABLE_CELL)) {
+                               box_add_child(implied_flex_item, child);
+
+                               next_child = child->next;
+                               child->next = NULL;
+                               child = next_child;
+                       }
+
+                       implied_flex_item->last->next = NULL;
+                       implied_flex_item->next = next_child = child;
+                       if (implied_flex_item->next != NULL)
+                               implied_flex_item->next->prev = 
implied_flex_item;
+                       else
+                               flex_container->last = implied_flex_item;
+                       implied_flex_item->parent = flex_container;
+
+                       if (box_normalise_table(implied_flex_item,
+                                       root, c) == false)
+                               return false;
+                       break;
+               default:
+                       assert(0);
+               }
+       }
+
+       return true;
+}
 
 static bool
 box_normalise_inline_container(struct box *cont,
@@ -836,6 +1020,11 @@ box_normalise_inline_container(struct box *cont,
                        if (box_normalise_block(child, root, c) == false)
                                return false;
                        break;
+               case BOX_INLINE_FLEX:
+                       /* ok */
+                       if (box_normalise_flex(child, root, c) == false)
+                               return false;
+                       break;
                case BOX_FLOAT_LEFT:
                case BOX_FLOAT_RIGHT:
                        /* ok */
@@ -852,6 +1041,11 @@ box_normalise_inline_container(struct box *cont,
                                                c) == false)
                                        return false;
                                break;
+                       case BOX_FLEX:
+                               if (box_normalise_flex(child->children, root,
+                                               c) == false)
+                                       return false;
+                               break;
                        default:
                                assert(0);
                        }
@@ -870,6 +1064,7 @@ box_normalise_inline_container(struct box *cont,
                                box_free(child);
                        }
                        break;
+               case BOX_FLEX:
                case BOX_BLOCK:
                case BOX_INLINE_CONTAINER:
                case BOX_TABLE:
@@ -888,7 +1083,6 @@ box_normalise_inline_container(struct box *cont,
        return true;
 }
 
-
 /* Exported function documented in html/box_normalise.h */
 bool
 box_normalise_block(struct box *block, const struct box *root, html_content *c)
@@ -920,6 +1114,11 @@ box_normalise_block(struct box *block, const struct box 
*root, html_content *c)
                next_child = child->next;       /* child may be destroyed */
 
                switch (child->type) {
+               case BOX_FLEX:
+                       /* ok */
+                       if (box_normalise_flex(child, root, c) == false)
+                               return false;
+                       break;
                case BOX_BLOCK:
                        /* ok */
                        if (box_normalise_block(child, root, c) == false)
@@ -935,6 +1134,7 @@ box_normalise_block(struct box *block, const struct box 
*root, html_content *c)
                        break;
                case BOX_INLINE:
                case BOX_INLINE_END:
+               case BOX_INLINE_FLEX:
                case BOX_INLINE_BLOCK:
                case BOX_FLOAT_LEFT:
                case BOX_FLOAT_RIGHT:
diff --git a/content/handlers/html/box_normalise.h 
b/content/handlers/html/box_normalise.h
index 591feab..377cd90 100644
--- a/content/handlers/html/box_normalise.h
+++ b/content/handlers/html/box_normalise.h
@@ -50,14 +50,15 @@
  * The tree is modified to satisfy the following:
  * \code
  * parent               permitted child nodes
- * BLOCK, INLINE_BLOCK  BLOCK, INLINE_CONTAINER, TABLE
- * INLINE_CONTAINER     INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT
+ * BLOCK, INLINE_BLOCK  BLOCK, INLINE_CONTAINER, TABLE, FLEX
+ * FLEX, INLINE_FLEX    BLOCK, INLINE_CONTAINER, TABLE, FLEX
+ * INLINE_CONTAINER     INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, 
TEXT, INLINE_FLEX
  * INLINE, TEXT         none
  * TABLE                at least 1 TABLE_ROW_GROUP
  * TABLE_ROW_GROUP      at least 1 TABLE_ROW
  * TABLE_ROW            at least 1 TABLE_CELL
- * TABLE_CELL           BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
- * FLOAT_(LEFT|RIGHT)   exactly 1 BLOCK or TABLE
+ * TABLE_CELL           BLOCK, INLINE_CONTAINER, TABLE, FLEX (same as BLOCK)
+ * FLOAT_(LEFT|RIGHT)   exactly 1 BLOCK, TABLE or FLEX
  * \endcode
  */
 bool box_normalise_block(struct box *block, const struct box *root, struct 
html_content *c);
diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index cb5be5d..bf8f68c 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -67,13 +67,9 @@
 #include "html/font.h"
 #include "html/form_internal.h"
 #include "html/layout.h"
+#include "html/layout_internal.h"
 #include "html/table.h"
 
-#define AUTO INT_MIN
-
-/* Fixed point percentage (a) of an integer (b), to an integer */
-#define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100)))
-
 typedef uint8_t (*css_len_func)(
                const css_computed_style *style,
                css_fixed *length, css_unit *unit);
@@ -84,7 +80,7 @@ typedef uint8_t (*css_border_color_func)(
                css_color *color);
 
 /** Array of per-side access functions for computed style margins. */
-static const css_len_func margin_funcs[4] = {
+const css_len_func margin_funcs[4] = {
        [TOP]    = css_computed_margin_top,
        [RIGHT]  = css_computed_margin_right,
        [BOTTOM] = css_computed_margin_bottom,
@@ -92,7 +88,7 @@ static const css_len_func margin_funcs[4] = {
 };
 
 /** Array of per-side access functions for computed style paddings. */
-static const css_len_func padding_funcs[4] = {
+const css_len_func padding_funcs[4] = {
        [TOP]    = css_computed_padding_top,
        [RIGHT]  = css_computed_padding_right,
        [BOTTOM] = css_computed_padding_bottom,
@@ -100,7 +96,7 @@ static const css_len_func padding_funcs[4] = {
 };
 
 /** Array of per-side access functions for computed style border_widths. */
-static const css_len_func border_width_funcs[4] = {
+const css_len_func border_width_funcs[4] = {
        [TOP]    = css_computed_border_top_width,
        [RIGHT]  = css_computed_border_right_width,
        [BOTTOM] = css_computed_border_bottom_width,
@@ -108,67 +104,15 @@ static const css_len_func border_width_funcs[4] = {
 };
 
 /** Array of per-side access functions for computed style border styles. */
-static const css_border_style_func border_style_funcs[4] = {
+const css_border_style_func border_style_funcs[4] = {
        [TOP]    = css_computed_border_top_style,
        [RIGHT]  = css_computed_border_right_style,
        [BOTTOM] = css_computed_border_bottom_style,
        [LEFT]   = css_computed_border_left_style,
 };
 
-/** Layout helper: Check for CSS border on given side. */
-static inline bool lh__have_border(
-               enum box_side side,
-               const css_computed_style *style)
-{
-       return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
-}
-
-/** Layout helper: Check whether box is a float. */
-static inline bool lh__box_is_float_box(const struct box *b)
-{
-       return b->type == BOX_FLOAT_LEFT ||
-              b->type == BOX_FLOAT_RIGHT;
-}
-
-/** Layout helper: Check whether box takes part in inline flow. */
-static inline bool lh__box_is_inline_flow(const struct box *b)
-{
-       return b->type == BOX_INLINE ||
-              b->type == BOX_INLINE_BLOCK ||
-              b->type == BOX_TEXT ||
-              b->type == BOX_INLINE_END;
-}
-
-/** Layout helper: Check whether box is inline level. (Includes BR.) */
-static inline bool lh__box_is_inline_level(const struct box *b)
-{
-       return lh__box_is_inline_flow(b) ||
-              b->type == BOX_BR;
-}
-
-/** Layout helper: Check whether box is inline level. (Includes BR, floats.) */
-static inline bool lh__box_is_inline_content(const struct box *b)
-{
-       return lh__box_is_float_box(b) ||
-              lh__box_is_inline_level(b);
-}
-
-/** Layout helper: Check whether box is an object. */
-static inline bool lh__box_is_object(const struct box *b)
-{
-       return b->object ||
-              (b->flags & (IFRAME | REPLACE_DIM));
-}
-
-/** Layout helper: Check whether box is replaced. */
-static inline bool lh__box_is_replace(const struct box *b)
-{
-       return b->gadget ||
-              lh__box_is_object(b);
-}
-
 /** Array of per-side access functions for computed style border colors. */
-static const css_border_color_func border_color_funcs[4] = {
+const css_border_color_func border_color_funcs[4] = {
        [TOP]    = css_computed_border_top_color,
        [RIGHT]  = css_computed_border_right_color,
        [BOTTOM] = css_computed_border_bottom_color,
@@ -176,10 +120,6 @@ static const css_border_color_func border_color_funcs[4] = 
{
 };
 
 /* 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,
@@ -315,74 +255,6 @@ static int layout_text_indent(
 
 
 /**
- * Determine width of margin, borders, and padding on one side of a box.
- *
- * \param unit_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
- * \param border   whether border width is required
- * \param padding  whether padding width is required
- * \param fixed    increased by sum of fixed margin, border, and padding
- * \param frac     increased by sum of fractional margin and padding
- */
-static void
-calculate_mbp_width(const css_unit_ctx *unit_len_ctx,
-                   const css_computed_style *style,
-                   unsigned int side,
-                   bool margin,
-                   bool border,
-                   bool padding,
-                   int *fixed,
-                   float *frac)
-{
-       css_fixed value = 0;
-       css_unit unit = CSS_UNIT_PX;
-
-       assert(style);
-
-       /* margin */
-       if (margin) {
-               enum css_margin_e type;
-
-               type = margin_funcs[side](style, &value, &unit);
-               if (type == CSS_MARGIN_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               *frac += FIXTOINT(FDIV(value, F_100));
-                       } else {
-                               *fixed += FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               }
-       }
-
-       /* border */
-       if (border) {
-               if (lh__have_border(side, style)) {
-                       border_width_funcs[side](style, &value, &unit);
-
-                       *fixed += FIXTOINT(css_unit_len2device_px(
-                                       style, unit_len_ctx,
-                                       value, unit));
-               }
-       }
-
-       /* padding */
-       if (padding) {
-               padding_funcs[side](style, &value, &unit);
-               if (unit == CSS_UNIT_PCT) {
-                       *frac += FIXTOINT(FDIV(value, F_100));
-               } else {
-                       *fixed += FIXTOINT(css_unit_len2device_px(
-                                       style, unit_len_ctx,
-                                       value, unit));
-               }
-       }
-}
-
-
-/**
  * Calculate minimum and maximum width of a table.
  *
  * \param table box of type TABLE
@@ -650,11 +522,11 @@ layout_minmax_line(struct box *first,
 
                if (lh__box_is_float_box(b)) {
                        assert(b->children);
-                       if (b->children->type == BOX_BLOCK)
-                               layout_minmax_block(b->children, font_func,
+                       if (b->children->type == BOX_TABLE)
+                               layout_minmax_table(b->children, font_func,
                                                content);
                        else
-                               layout_minmax_table(b->children, font_func,
+                               layout_minmax_block(b->children, font_func,
                                                content);
                        b->min_width = b->children->min_width;
                        b->max_width = b->children->max_width;
@@ -664,7 +536,7 @@ layout_minmax_line(struct box *first,
                        continue;
                }
 
-               if (b->type == BOX_INLINE_BLOCK) {
+               if (b->type == BOX_INLINE_BLOCK || b->type == BOX_INLINE_FLEX) {
                        layout_minmax_block(b, font_func, content);
                        if (min < b->min_width)
                                min = b->min_width;
@@ -997,7 +869,6 @@ layout_minmax_inline_container(struct box *inline_container,
                        inline_container->max_width);
 }
 
-
 /**
  * Calculate minimum and maximum width of a block.
  *
@@ -1026,6 +897,8 @@ static void layout_minmax_block(
        bool child_has_height = false;
 
        assert(block->type == BOX_BLOCK ||
+                       block->type == BOX_FLEX ||
+                       block->type == BOX_INLINE_FLEX ||
                        block->type == BOX_INLINE_BLOCK ||
                        block->type == BOX_TABLE_CELL);
 
@@ -1041,7 +914,8 @@ static void layout_minmax_block(
 
        /* set whether the minimum width is of any interest for this box */
        if (((block->parent && lh__box_is_float_box(block->parent)) ||
-                       block->type == BOX_INLINE_BLOCK) &&
+                       block->type == BOX_INLINE_BLOCK ||
+                       block->type == BOX_INLINE_FLEX) &&
                        wtype != CSS_WIDTH_SET) {
                /* box shrinks to fit; need minimum width */
                block->flags |= NEED_MIN;
@@ -1052,6 +926,9 @@ static void layout_minmax_block(
                        wtype != CSS_WIDTH_SET) {
                /* box inside shrink-to-fit context; need minimum width */
                block->flags |= NEED_MIN;
+       } else if (block->parent && (block->parent->type == BOX_FLEX)) {
+               /* box is flex item */
+               block->flags |= NEED_MIN;
        }
 
        if (block->gadget && (block->gadget->type == GADGET_TEXTBOX ||
@@ -1101,6 +978,7 @@ static void layout_minmax_block(
                /* recurse through children */
                for (child = block->children; child; child = child->next) {
                        switch (child->type) {
+                       case BOX_FLEX:
                        case BOX_BLOCK:
                                layout_minmax_block(child, font_func,
                                                content);
@@ -1142,10 +1020,19 @@ static void layout_minmax_block(
                                continue;
                        }
 
-                       if (min < child->min_width)
-                               min = child->min_width;
-                       if (max < child->max_width)
-                               max = child->max_width;
+                       if (lh__box_is_flex_container(block) &&
+                                       block->style != NULL &&
+                                       css_computed_flex_wrap(block->style) ==
+                                       CSS_FLEX_WRAP_NOWRAP) {
+                               min += child->min_width;
+                               max += child->max_width;
+
+                       } else {
+                               if (min < child->min_width)
+                                       min = child->min_width;
+                               if (max < child->max_width)
+                                       max = child->max_width;
+                       }
 
                        if (child_has_height)
                                block->flags |= HAS_HEIGHT;
@@ -1227,375 +1114,6 @@ static void layout_minmax_block(
 
 
 /**
- * Adjust a specified width or height for the box-sizing property.
- *
- * This turns the specified dimension into a content-box dimension.
- *
- * \param  unit_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,
- *                             else set false for a height
- * \param  dimension       current value for given width/height dimension.
- *                             updated to new value after consideration of
- *                             gadget properties.
- */
-static void layout_handle_box_sizing(
-               const css_unit_ctx *unit_len_ctx,
-               const struct box *box,
-               int available_width,
-               bool setwidth,
-               int *dimension)
-{
-       enum css_box_sizing_e bs;
-
-       assert(box && box->style);
-
-       bs = css_computed_box_sizing(box->style);
-
-       if (bs == CSS_BOX_SIZING_BORDER_BOX) {
-               int orig = *dimension;
-               int fixed = 0;
-               float frac = 0;
-
-               calculate_mbp_width(unit_len_ctx, box->style,
-                               setwidth ? LEFT : TOP,
-                               false, true, true, &fixed, &frac);
-               calculate_mbp_width(unit_len_ctx, box->style,
-                               setwidth ? RIGHT : BOTTOM,
-                               false, true, true, &fixed, &frac);
-               orig -= frac * available_width + fixed;
-               *dimension = orig > 0 ? orig : 0;
-       }
-}
-
-
-/**
- * Calculate width, height, and thickness of margins, paddings, and borders.
- *
- * \param  unit_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
- * \param  style           style giving width, height, margins, paddings,
- *                          and borders
- * \param  width            updated to width, may be NULL
- * \param  height           updated to height, may be NULL
- * \param  max_width        updated to max-width, may be NULL
- * \param  min_width        updated to min-width, may be NULL
- * \param  max_height       updated to max-height, may be NULL
- * \param  min_height       updated to min-height, may be NULL
- * \param  margin          filled with margins, may be NULL
- * \param  padding         filled with paddings, may be NULL
- * \param  border          filled with border widths, may be NULL
- */
-static void
-layout_find_dimensions(const css_unit_ctx *unit_len_ctx,
-                      int available_width,
-                      int viewport_height,
-                      const struct box *box,
-                      const css_computed_style *style,
-                      int *width,
-                      int *height,
-                      int *max_width,
-                      int *min_width,
-                      int *max_height,
-                      int *min_height,
-                      int margin[4],
-                      int padding[4],
-                      struct box_border border[4])
-{
-       struct box *containing_block = NULL;
-       unsigned int i;
-
-       if (width) {
-               enum css_width_e wtype;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               wtype = css_computed_width(style, &value, &unit);
-
-               if (wtype == CSS_WIDTH_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               *width = FPCT_OF_INT_TOINT(
-                                               value, available_width);
-                       } else {
-                               *width = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       *width = AUTO;
-               }
-
-               if (*width != AUTO) {
-                       layout_handle_box_sizing(unit_len_ctx, box, 
available_width,
-                                       true, width);
-               }
-       }
-
-       if (height) {
-               enum css_height_e htype;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               htype = css_computed_height(style, &value, &unit);
-
-               if (htype == CSS_HEIGHT_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               enum css_height_e cbhtype;
-
-                               if (css_computed_position(box->style) ==
-                                               CSS_POSITION_ABSOLUTE &&
-                                               box->parent) {
-                                       /* Box is absolutely positioned */
-                                       assert(box->float_container);
-                                       containing_block = box->float_container;
-                               } else if (box->float_container &&
-                                       css_computed_position(box->style) !=
-                                               CSS_POSITION_ABSOLUTE &&
-                                       (css_computed_float(box->style) ==
-                                               CSS_FLOAT_LEFT ||
-                                        css_computed_float(box->style) ==
-                                               CSS_FLOAT_RIGHT)) {
-                                       /* Box is a float */
-                                       assert(box->parent &&
-                                               box->parent->parent &&
-                                               box->parent->parent->parent);
-
-                                       containing_block =
-                                               box->parent->parent->parent;
-                               } else if (box->parent && box->parent->type !=
-                                               BOX_INLINE_CONTAINER) {
-                                       /* Box is a block level element */
-                                       containing_block = box->parent;
-                               } else if (box->parent && box->parent->type ==
-                                               BOX_INLINE_CONTAINER) {
-                                       /* Box is an inline block */
-                                       assert(box->parent->parent);
-                                       containing_block = box->parent->parent;
-                               }
-
-                               if (containing_block) {
-                                       css_fixed f = 0;
-                                       css_unit u = CSS_UNIT_PX;
-
-                                       cbhtype = css_computed_height(
-                                                       containing_block->style,
-                                                       &f, &u);
-                               }
-
-                               if (containing_block &&
-                                       containing_block->height != AUTO &&
-                                       (css_computed_position(box->style) ==
-                                                       CSS_POSITION_ABSOLUTE ||
-                                               cbhtype == CSS_HEIGHT_SET)) {
-                                       /* Box is absolutely positioned or its
-                                        * containing block has a valid
-                                        * specified height.
-                                        * (CSS 2.1 Section 10.5) */
-                                       *height = FPCT_OF_INT_TOINT(value,
-                                               containing_block->height);
-                               } else if ((!box->parent ||
-                                               !box->parent->parent) &&
-                                               viewport_height >= 0) {
-                                       /* If root element or it's child
-                                        * (HTML or BODY) */
-                                       *height = FPCT_OF_INT_TOINT(value,
-                                                       viewport_height);
-                               } else {
-                                       /* precentage height not permissible
-                                        * treat height as auto */
-                                       *height = AUTO;
-                               }
-                       } else {
-                               *height = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       *height = AUTO;
-               }
-
-               if (*height != AUTO) {
-                       layout_handle_box_sizing(unit_len_ctx, box, 
available_width,
-                                       false, height);
-               }
-       }
-
-       if (max_width) {
-               enum css_max_width_e type;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               type = css_computed_max_width(style, &value, &unit);
-
-               if (type == CSS_MAX_WIDTH_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               *max_width = FPCT_OF_INT_TOINT(value,
-                                               available_width);
-                       } else {
-                               *max_width = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       /* Inadmissible */
-                       *max_width = -1;
-               }
-
-               if (*max_width != -1) {
-                       layout_handle_box_sizing(unit_len_ctx, box, 
available_width,
-                                       true, max_width);
-               }
-       }
-
-       if (min_width) {
-               enum css_min_width_e type;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               type = ns_computed_min_width(style, &value, &unit);
-
-               if (type == CSS_MIN_WIDTH_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               *min_width = FPCT_OF_INT_TOINT(value,
-                                               available_width);
-                       } else {
-                               *min_width = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       /* Inadmissible */
-                       *min_width = 0;
-               }
-
-               if (*min_width != 0) {
-                       layout_handle_box_sizing(unit_len_ctx, box, 
available_width,
-                                       true, min_width);
-               }
-       }
-
-       if (max_height) {
-               enum css_max_height_e type;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               type = css_computed_max_height(style, &value, &unit);
-
-               if (type == CSS_MAX_HEIGHT_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               /* TODO: handle percentage */
-                               *max_height = -1;
-                       } else {
-                               *max_height = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       /* Inadmissible */
-                       *max_height = -1;
-               }
-       }
-
-       if (min_height) {
-               enum css_min_height_e type;
-               css_fixed value = 0;
-               css_unit unit = CSS_UNIT_PX;
-
-               type = ns_computed_min_height(style, &value, &unit);
-
-               if (type == CSS_MIN_HEIGHT_SET) {
-                       if (unit == CSS_UNIT_PCT) {
-                               /* TODO: handle percentage */
-                               *min_height = 0;
-                       } else {
-                               *min_height = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               } else {
-                       /* Inadmissible */
-                       *min_height = 0;
-               }
-       }
-
-       for (i = 0; i != 4; i++) {
-               if (margin) {
-                       enum css_margin_e type = CSS_MARGIN_AUTO;
-                       css_fixed value = 0;
-                       css_unit unit = CSS_UNIT_PX;
-
-                       type = margin_funcs[i](style, &value, &unit);
-
-                       if (type == CSS_MARGIN_SET) {
-                               if (unit == CSS_UNIT_PCT) {
-                                       margin[i] = FPCT_OF_INT_TOINT(value,
-                                                       available_width);
-                               } else {
-                                       margin[i] = 
FIXTOINT(css_unit_len2device_px(
-                                                       style, unit_len_ctx,
-                                                       value, unit));
-                               }
-                       } else {
-                               margin[i] = AUTO;
-                       }
-               }
-
-               if (padding) {
-                       css_fixed value = 0;
-                       css_unit unit = CSS_UNIT_PX;
-
-                       padding_funcs[i](style, &value, &unit);
-
-                       if (unit == CSS_UNIT_PCT) {
-                               padding[i] = FPCT_OF_INT_TOINT(value,
-                                               available_width);
-                       } else {
-                               padding[i] = FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-                       }
-               }
-
-               /* Table cell borders are populated in table.c */
-               if (border && box->type != BOX_TABLE_CELL) {
-                       enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE;
-                       css_color color = 0;
-                       css_fixed value = 0;
-                       css_unit unit = CSS_UNIT_PX;
-
-                       border_width_funcs[i](style, &value, &unit);
-                       bstyle = border_style_funcs[i](style);
-                       border_color_funcs[i](style, &color);
-
-                       border[i].style = bstyle;
-                       border[i].c = color;
-
-                       if (bstyle == CSS_BORDER_STYLE_HIDDEN ||
-                                       bstyle == CSS_BORDER_STYLE_NONE)
-                               /* spec unclear: following Mozilla */
-                               border[i].width = 0;
-                       else
-                               border[i].width = 
FIXTOINT(css_unit_len2device_px(
-                                               style, unit_len_ctx,
-                                               value, unit));
-
-                       /* Special case for border-collapse: make all borders
-                        * on table/table-row-group/table-row zero width. */
-                       if (css_computed_border_collapse(style) ==
-                                       CSS_BORDER_COLLAPSE_COLLAPSE &&
-                                       (box->type == BOX_TABLE ||
-                                        box->type == BOX_TABLE_ROW_GROUP ||
-                                        box->type == BOX_TABLE_ROW))
-                               border[i].width = 0;
-               }
-       }
-}
-
-
-/**
  * Find next block that current margin collapses to.
  *
  * \param  unit_len_ctx  Length conversion context
@@ -2058,15 +1576,10 @@ static void layout_move_children(struct box *box, int 
x, int y)
 }
 
 
-/**
- * Layout a table.
- *
- * \param  table           table to layout
- * \param  available_width  width of containing block
- * \param  content        memory pool for any new boxes
- * \return  true on success, false on memory exhaustion
- */
-static bool layout_table(struct box *table, int available_width,
+/* Documented in layout_internal.h */
+bool layout_table(
+               struct box *table,
+               int available_width,
                html_content *content)
 {
        unsigned int columns = table->columns;  /* total columns */
@@ -3052,8 +2565,11 @@ layout_float_find_dimensions(
  */
 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);
+       assert(b->type == BOX_TABLE ||
+              b->type == BOX_BLOCK ||
+              b->type == BOX_INLINE_BLOCK ||
+              b->type == BOX_FLEX ||
+              b->type == BOX_INLINE_FLEX);
        layout_float_find_dimensions(&content->unit_len_ctx, width, b->style, 
b);
        if (b->type == BOX_TABLE) {
                if (!layout_table(b, width, content))
@@ -3275,7 +2791,8 @@ layout_line(struct box *first,
 
                x += space_after;
 
-               if (b->type == BOX_INLINE_BLOCK) {
+               if (b->type == BOX_INLINE_BLOCK ||
+                   b->type == BOX_INLINE_FLEX) {
                        if (b->max_width != UNKNOWN_WIDTH)
                                if (!layout_float(b, *width, content))
                                        return false;
@@ -3977,21 +3494,11 @@ static bool layout_inline_container(struct box 
*inline_container, int width,
 }
 
 
-/**
- * Layout a block formatting context.
- *
- * \param  block           BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
- * \param  viewport_height  Height of viewport in pixels or -ve if unknown
- * \param  content         Memory pool for any new boxes
- * \return  true on success, false on memory exhaustion
- *
- * This function carries out layout of a block and its children, as described
- * in CSS 2.1 9.4.1.
- */
-static bool
-layout_block_context(struct box *block,
-                    int viewport_height,
-                    html_content *content)
+/* Documented in layout_intertnal.h */
+bool layout_block_context(
+               struct box *block,
+               int viewport_height,
+               html_content *content)
 {
        struct box *box;
        int cx, cy;  /**< current coordinates */
@@ -4006,7 +3513,9 @@ layout_block_context(struct box *block,
 
        assert(block->type == BOX_BLOCK ||
                        block->type == BOX_INLINE_BLOCK ||
-                       block->type == BOX_TABLE_CELL);
+                       block->type == BOX_TABLE_CELL ||
+                       block->type == BOX_FLEX ||
+                       block->type == BOX_INLINE_FLEX);
        assert(block->width != UNKNOWN_WIDTH);
        assert(block->width != AUTO);
 
@@ -4075,7 +3584,9 @@ layout_block_context(struct box *block,
                enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
                enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
 
-               assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
+               assert(box->type == BOX_BLOCK ||
+                               box->type == BOX_FLEX ||
+                               box->type == BOX_TABLE ||
                                box->type == BOX_INLINE_CONTAINER);
 
                /* Tables are laid out before being positioned, because the
@@ -4159,7 +3670,7 @@ layout_block_context(struct box *block,
                                layout_block_add_scrollbar(box, RIGHT);
                                layout_block_add_scrollbar(box, BOTTOM);
                        }
-               } else if (box->type == BOX_TABLE) {
+               } else if (box->type == BOX_TABLE || box->type == BOX_FLEX) {
                        if (box->style != NULL) {
                                enum css_width_e wtype;
                                css_fixed width = 0;
@@ -4192,11 +3703,21 @@ layout_block_context(struct box *block,
                                                x1;
                                }
                        }
-                       if (!layout_table(box, box->parent->width - lm - rm,
-                                       content))
-                               return false;
-                       layout_solve_width(box, box->parent->width, box->width,
-                                       lm, rm, -1, -1);
+                       if (box->type == BOX_TABLE) {
+                               if (!layout_table(box,
+                                               box->parent->width - lm - rm,
+                                               content))
+                                       return false;
+                               layout_solve_width(box,
+                                               box->parent->width, box->width,
+                                               lm, rm, -1, -1);
+                       } else {
+                               if (!layout_flex(box,
+                                               box->parent->width - lm - rm,
+                                               content)) {
+                                       return false;
+                               }
+                       }
                }
 
                /* Position box: horizontal. */
@@ -4212,6 +3733,7 @@ layout_block_context(struct box *block,
 
                /* Vertical margin */
                if (((box->type == BOX_BLOCK && (box->flags & HAS_HEIGHT)) ||
+                    box->type == BOX_FLEX ||
                     box->type == BOX_TABLE ||
                     (box->type == BOX_INLINE_CONTAINER &&
                      !box_is_first_child(box)) ||
@@ -5037,7 +4559,9 @@ layout_absolute(struct box *box,
        int space;
 
        assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
-                       box->type == BOX_INLINE_BLOCK);
+                       box->type == BOX_INLINE_BLOCK ||
+                       box->type == BOX_FLEX ||
+                       box->type == BOX_INLINE_FLEX);
 
        /* The static position is where the box would be if it was not
         * absolutely positioned. The x and y are filled in by
@@ -5272,6 +4796,9 @@ layout_absolute(struct box *box,
                box->float_container = NULL;
                layout_solve_width(box, box->parent->width, box->width, 0, 0,
                                -1, -1);
+       } else if (box->type == BOX_FLEX || box->type == BOX_INLINE_FLEX) {
+               if (!layout_flex(box, width, content))
+                       return false;
        }
 
        /* 10.6.4 */
@@ -5408,7 +4935,9 @@ layout_position_absolute(struct box *box,
 
        for (c = box->children; c; c = c->next) {
                if ((c->type == BOX_BLOCK || c->type == BOX_TABLE ||
-                               c->type == BOX_INLINE_BLOCK) &&
+                               c->type == BOX_INLINE_BLOCK ||
+                               c->type == BOX_FLEX ||
+                               c->type == BOX_INLINE_FLEX) &&
                                (css_computed_position(c->style) ==
                                                CSS_POSITION_ABSOLUTE ||
                                 css_computed_position(c->style) ==
@@ -5762,6 +5291,15 @@ static void layout_calculate_descendant_bboxes(
 {
        struct box *child;
 
+if (box->width == UNKNOWN_WIDTH) {
+       struct box *a = box;
+       while (a->parent) {
+               a = a->parent;
+       }
+       printf("box %p width: %i\n", box, box->width);
+       box_dump(stdout, a, 0, true);
+}
+
        assert(box->width != UNKNOWN_WIDTH);
        assert(box->height != AUTO);
        /* assert((box->width >= 0) && (box->height >= 0)); */
@@ -5897,6 +5435,7 @@ bool layout_document(html_content *content, int width, 
int height)
        layout_position_absolute(doc, doc, 0, 0, content);
        layout_position_relative(&content->unit_len_ctx, doc, doc, 0, 0);
 
+//     box_dump(stderr, doc, 0, false);
        layout_calculate_descendant_bboxes(&content->unit_len_ctx, doc);
 
        return ret;
diff --git a/content/handlers/html/layout_flex.c 
b/content/handlers/html/layout_flex.c
new file mode 100644
index 0000000..2cc232f
--- /dev/null
+++ b/content/handlers/html/layout_flex.c
@@ -0,0 +1,664 @@
+/*
+ * Copyright 2022 Michael Drake <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML layout implementation: display: flex.
+ *
+ * Layout is carried out in two stages:
+ *
+ * 1. + calculation of minimum / maximum box widths, and
+ *    + determination of whether block level boxes will have >zero height
+ *
+ * 2. + layout (position and dimensions)
+ *
+ * In most cases the functions for the two stages are a corresponding pair
+ * layout_minmax_X() and layout_X().
+ */
+
+#include <string.h>
+
+#include "utils/utils.h"
+
+#include "html/box.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "html/box_inspect.h"
+#include "html/layout_internal.h"
+
+struct flex_item_data {
+       enum css_flex_basis_e basis;
+       css_fixed basis_length;
+       css_unit basis_unit;
+       struct box *box;
+
+       css_fixed shrink;
+       css_fixed grow;
+
+       int min_width;
+       int max_width;
+       int min_height;
+       int max_height;
+
+       int target_main_size;
+       int base_size;
+       int main_size;
+       size_t line;
+
+       bool freeze;
+       bool min_violation;
+       bool max_violation;
+};
+
+struct flex_line_data {
+       int height;
+
+       int main_size;
+
+       size_t first;
+       size_t count;
+       size_t frozen;
+};
+
+struct flex_ctx {
+       int height;
+       html_content *content;
+       const struct box *flex;
+       const css_unit_ctx *unit_len_ctx;
+
+       enum css_flex_wrap_e wrap;
+
+       struct flex_items {
+               size_t count;
+               struct flex_item_data *data;
+       } item;
+
+       struct flex_lines {
+               size_t count;
+               size_t alloc;
+               struct flex_line_data *data;
+       } line;
+};
+
+static void layout_flex_ctx__destroy(struct flex_ctx *ctx)
+{
+       if (ctx != NULL) {
+               free(ctx->item.data);
+               free(ctx->line.data);
+               free(ctx);
+       }
+}
+
+static struct flex_ctx *layout_flex_ctx__create(
+               html_content *content,
+               const struct box *flex)
+{
+       struct flex_ctx *ctx;
+
+       ctx = calloc(1, sizeof(*ctx));
+       if (ctx == NULL) {
+               return NULL;
+       }
+       ctx->line.alloc = 1;
+
+       ctx->item.count = box_count_children(flex);
+       ctx->item.data = calloc(ctx->item.count, sizeof(*ctx->item.data));
+       if (ctx->item.data == NULL) {
+               layout_flex_ctx__destroy(ctx);
+               return NULL;
+       }
+
+       ctx->line.alloc = 1;
+       ctx->line.data = calloc(ctx->line.alloc, sizeof(*ctx->line.data));
+       if (ctx->line.data == NULL) {
+               layout_flex_ctx__destroy(ctx);
+               return NULL;
+       }
+
+       ctx->flex = flex;
+       ctx->content = content;
+       ctx->unit_len_ctx = &content->unit_len_ctx;
+       ctx->wrap = css_computed_flex_wrap(flex->style);
+
+       return ctx;
+}
+
+static inline void layout_flex__base_and_main_sizes(
+               const struct flex_ctx *ctx,
+               struct flex_item_data *item,
+               int available_width)
+{
+       struct box *b = item->box;
+       int delta_outer_width = lh__delta_outer_width(b);
+
+       if (item->basis == CSS_FLEX_BASIS_SET) {
+               if (item->basis_unit == CSS_UNIT_PCT) {
+                       item->base_size = FPCT_OF_INT_TOINT(
+                                       item->basis_length,
+                                       available_width);
+               } else {
+                       item->base_size = FIXTOINT(css_unit_len2device_px(
+                                       b->style, ctx->unit_len_ctx,
+                                       item->basis_length,
+                                       item->basis_unit));
+               }
+
+       } else if (item->basis == CSS_FLEX_BASIS_AUTO) {
+               item->base_size = b->width;
+       } else {
+               item->base_size = AUTO;
+       }
+
+       if (item->base_size != AUTO) {
+               layout_handle_box_sizing(ctx->unit_len_ctx, b,
+                               available_width, true,
+                               &item->base_size);
+       } else {
+               item->base_size = b->max_width;
+       }
+
+       item->base_size += delta_outer_width;
+
+       fprintf(stderr, "base_size: %i\n", item->base_size);
+       item->base_size = max(min(item->base_size, available_width),
+                       b->min_width + delta_outer_width);
+
+       item->target_main_size = item->base_size;
+       item->main_size = item->base_size;
+
+       fprintf(stderr, "main_size: %i\n", item->main_size);
+
+       if (item->max_width > 0 &&
+           item->main_size > item->max_width + delta_outer_width) {
+               item->main_size = item->max_width + delta_outer_width;
+       }
+
+       if (item->main_size < item->min_width + delta_outer_width) {
+               item->main_size = item->min_width + delta_outer_width;
+       }
+       fprintf(stderr, "main_size: %i\n", item->main_size);
+}
+
+static void layout_flex_ctx__populate_item_data(
+               const struct flex_ctx *ctx,
+               const struct box *flex,
+               int available_width)
+{
+       size_t i = 0;
+
+       for (struct box *b = flex->children; b != NULL; b = b->next) {
+               struct flex_item_data *item = &ctx->item.data[i++];
+
+               layout_find_dimensions(ctx->unit_len_ctx, available_width, -1,
+                               b, b->style, &b->width, &b->height,
+                               &item->max_width, &item->min_width,
+                               &item->max_height, &item->min_height,
+                               b->margin, b->padding, b->border);
+
+               item->box = b;
+               item->basis = css_computed_flex_basis(b->style,
+                               &item->basis_length, &item->basis_unit);
+
+               css_computed_flex_shrink(b->style, &item->shrink);
+               css_computed_flex_grow(b->style, &item->grow);
+
+               layout_flex__base_and_main_sizes(ctx, item, available_width);
+       }
+}
+
+static bool layout_flex_ctx__ensure_line(struct flex_ctx *ctx)
+{
+       struct flex_line_data *temp;
+       size_t line_alloc = ctx->line.alloc * 2;
+
+       fprintf(stderr, "Ensure line start: count: %zu, alloc: %zu\n",
+                       ctx->line.count, ctx->line.alloc);
+
+       if (ctx->line.alloc > ctx->line.count) {
+               return true;
+       }
+
+       temp = realloc(ctx->line.data, sizeof(*ctx->line.data) * line_alloc);
+       if (temp == NULL) {
+               return false;
+       }
+       ctx->line.data = temp;
+
+       fprintf(stderr, "Ensure line   end: count: %zu, alloc: %zu\n",
+                       ctx->line.count, line_alloc);
+
+       memset(ctx->line.data + ctx->line.alloc, 0,
+              sizeof(*ctx->line.data) * (line_alloc - ctx->line.alloc));
+       ctx->line.alloc = line_alloc;
+
+       return true;
+}
+
+static size_t layout_flex__fit_to_line(struct flex_ctx *ctx,
+               size_t item_index, int available_width, html_content *content)
+{
+       struct flex_line_data *line;
+       int used_width = 0;
+
+       if (!layout_flex_ctx__ensure_line(ctx)) {
+               return 0;
+       }
+
+       line = &ctx->line.data[ctx->line.count];
+       line->first = item_index;
+
+       while (item_index < ctx->item.count) {
+               struct flex_item_data *item = &ctx->item.data[item_index];
+               struct box *b = item->box;
+               int width = b->max_width;
+
+               width += lh__delta_outer_width(b);
+
+               if (lh__box_is_absolute(item->box) ||
+                   width == 0 ||
+                   width + used_width <= available_width ||
+                   line->count == 0) {
+                       line->main_size += item->main_size;
+                       item->line = ctx->line.count;
+                       used_width += width;
+                       line->count++;
+                       item_index++;
+               } else {
+                       break;
+               }
+       }
+
+       if (line->count > 0) {
+               ctx->line.count++;
+       }
+
+       return line->count;
+}
+
+static inline void layout_flex__item_freeze(
+               struct flex_line_data *line,
+               struct flex_item_data *item)
+{
+       item->freeze = true;
+       line->frozen++;
+       fprintf(stderr, "    frozen: block: %p: width: %i\n",
+                       item->box, item->target_main_size);
+}
+
+/** 9.7. Resolving Flexible Lengths */
+static bool layout_flex__resolve_line(
+               struct flex_ctx *ctx,
+               int available_width,
+               size_t line_index)
+{
+       struct flex_line_data *line = &ctx->line.data[line_index];
+       bool grow = (line->main_size < available_width);
+       int initial_free_space = available_width;
+       size_t item_count = line->first + line->count;
+       int x = 0;
+
+       fprintf(stderr, "  Line main_size: %i, available_width: %i\n",
+                       line->main_size, available_width);
+
+       for (size_t i = line->first; i < item_count; i++) {
+               struct flex_item_data *item = &ctx->item.data[i];
+
+               /* 3. Size inflexible items */
+               if (grow) {
+                       if (item->grow == 0 ||
+                           item->base_size > item->main_size) {
+                               fprintf(stderr, "    Grow: %f\n", 
FIXTOFLT(item->grow));
+                               fprintf(stderr, "    Base size: %i, Main size: 
%i\n",
+                                               item->base_size, 
item->main_size);
+                               item->target_main_size = item->main_size;
+                               fprintf(stderr, "    Grow freeze\n");
+                               layout_flex__item_freeze(line, item);
+                       }
+               } else {
+                       if (item->shrink == 0 ||
+                           item->base_size < item->main_size) {
+                               item->target_main_size = item->main_size;
+                               layout_flex__item_freeze(line, item);
+                       }
+               }
+
+               /* 4. Calculate initial free space */
+               if (item->freeze) {
+                       initial_free_space -= item->target_main_size;
+               } else {
+                       initial_free_space -= item->base_size;
+               }
+       }
+
+       /* 5. Loop */
+       while (line->frozen < line->count) {
+               int remaining_free_space = available_width;
+               css_fixed unfrozen_factor_sum = 0;
+
+               fprintf(stderr, "  Flex resolver pass\n");
+
+               /* b */
+               for (size_t i = line->first; i < item_count; i++) {
+                       struct flex_item_data *item = &ctx->item.data[i];
+
+                       if (item->freeze) {
+                               remaining_free_space -= item->target_main_size;
+                       } else {
+                               remaining_free_space -= item->base_size;
+
+                               unfrozen_factor_sum += grow ?
+                                               item->grow : item->shrink;
+                       }
+               }
+               fprintf(stderr, "    Remaining free space: %i\n", 
remaining_free_space);
+
+               if (unfrozen_factor_sum < F_1) {
+                       int free_space = FIXTOINT(FMUL(
+                                       INTTOFIX(initial_free_space),
+                                       unfrozen_factor_sum));
+
+                       if (free_space < remaining_free_space) {
+                               remaining_free_space = free_space;
+                       }
+                       fprintf(stderr, "    Remaining free space: %i\n", 
remaining_free_space);
+               }
+
+               /* c */
+               if (remaining_free_space != 0) {
+                       if (grow) {
+                               for (size_t i = line->first; i < item_count; 
i++) {
+                                       struct flex_item_data *item = 
&ctx->item.data[i];
+                                       css_fixed ratio;
+
+                                       if (item->freeze) {
+                                               continue;
+                                       }
+
+                                       ratio = FDIV(item->grow, 
unfrozen_factor_sum);
+
+                                       item->target_main_size = 
item->base_size +
+                                                       FIXTOINT(FMUL(
+                                                       
INTTOFIX(remaining_free_space),
+                                                       ratio));
+                               }
+                       } else {
+                               css_fixed scaled_shrink_factor_sum = 0;
+
+                               for (size_t i = line->first; i < item_count; 
i++) {
+                                       struct flex_item_data *item = 
&ctx->item.data[i];
+                                       css_fixed scaled_shrink_factor;
+
+                                       if (item->freeze) {
+                                               continue;
+                                       }
+
+                                       scaled_shrink_factor = FMUL(
+                                                       item->shrink,
+                                                       
INTTOFIX(item->base_size));
+                                       scaled_shrink_factor_sum += 
scaled_shrink_factor;
+                               }
+
+                               for (size_t i = line->first; i < item_count; 
i++) {
+                                       struct flex_item_data *item = 
&ctx->item.data[i];
+                                       css_fixed scaled_shrink_factor;
+                                       css_fixed ratio;
+
+                                       if (item->freeze) {
+                                               continue;
+                                       }
+
+                                       scaled_shrink_factor = FMUL(
+                                                       item->shrink,
+                                                       
INTTOFIX(item->base_size));
+                                       ratio = FDIV(scaled_shrink_factor,
+                                                    scaled_shrink_factor_sum);
+
+                                       item->target_main_size = 
item->base_size -
+                                                       FIXTOINT(FMUL(
+                                                       
INTTOFIX(abs(remaining_free_space)),
+                                                       ratio));
+                               }
+                       }
+               }
+
+               /* d */
+               int total_violation = 0;
+               for (size_t i = line->first; i < item_count; i++) {
+                       struct flex_item_data *item = &ctx->item.data[i];
+                       int target_main_size = item->target_main_size;
+
+                       if (item->freeze) {
+                               continue;
+                       }
+
+                       if (item->max_width > 0 &&
+                           target_main_size > item->max_width) {
+                               target_main_size = item->max_width;
+                               item->max_violation = true;
+                       }
+
+                       if (target_main_size < item->min_width) {
+                               target_main_size = item->min_width;
+                               item->min_violation = true;
+                       }
+
+                       if (target_main_size < item->box->min_width) {
+                               target_main_size = item->box->min_width;
+                               item->min_violation = true;
+                       }
+
+                       if (target_main_size < 0) {
+                               target_main_size = 0;
+                               item->min_violation = true;
+                       }
+
+                       total_violation += target_main_size - 
item->target_main_size;
+                       item->target_main_size = target_main_size;
+               }
+
+               /* e */
+               for (size_t i = line->first; i < item_count; i++) {
+                       struct flex_item_data *item = &ctx->item.data[i];
+
+                       if (total_violation == 0 ||
+                           (total_violation > 0 && item->min_violation) ||
+                           (total_violation < 0 && item->max_violation)) {
+                               layout_flex__item_freeze(line, item);
+                       }
+               }
+       }
+
+       for (size_t i = line->first; i < line->first + line->count; i++) {
+               fprintf(stderr, "    Item: %zu\n", i);
+               struct flex_item_data *item = &ctx->item.data[i];
+               struct box *b = item->box;
+               bool success = false;
+               int height;
+
+               b->width = item->target_main_size - lh__delta_outer_width(b);
+
+               switch (b->type) {
+               case BOX_BLOCK:
+                       fprintf(stderr, "      flex item: block: %p: width: 
%i\n", b, b->width);
+                       success = layout_block_context(b, -1,
+                                       ctx->content);
+                       break;
+               case BOX_TABLE:
+                       success = layout_table(b, available_width,
+                                       ctx->content);
+                       break;
+               case BOX_FLEX:
+                       success = layout_flex(b, available_width,
+                                       ctx->content);
+                       break;
+               default:
+                       assert(0 && "Bad flex item back type");
+                       success = false;
+                       break;
+               }
+               if (!success) {
+                       fprintf(stderr, "flex item: layout of %p failed\n", b);
+                       return false;
+               }
+
+               height = b->height + lh__delta_outer_height(b);
+
+               b->y = ctx->height + b->margin[TOP] + b->border[TOP].width + 
b->padding[TOP];
+               if (line->height < height) {
+                       line->height = height;
+               }
+
+               b->x = x + b->margin[LEFT] + b->border[LEFT].width + 
b->padding[LEFT];
+               x += b->width + lh__delta_outer_width(b);
+       }
+
+       return true;
+}
+
+/**
+ * Layout a flex container.
+ *
+ * \param[in] flex             table to layout
+ * \param[in] available_width  width of containing block
+ * \param[in] content          memory pool for any new boxes
+ * \return  true on success, false on memory exhaustion
+ */
+bool layout_flex(struct box *flex, int available_width,
+               html_content *content)
+{
+       int max_width, min_width, max_height, min_height;
+       struct flex_ctx *ctx;
+       bool success = false;
+
+       fprintf(stderr, "layout_flex: box: %p\n", flex);
+
+       ctx = layout_flex_ctx__create(content, flex);
+       if (ctx == NULL) {
+               return false;
+       }
+
+       layout_flex_ctx__populate_item_data(ctx, flex, available_width);
+
+       layout_find_dimensions(
+                       ctx->unit_len_ctx, available_width, -1,
+                       flex, flex->style, &flex->width, &flex->height,
+                       &max_width, &min_width, &max_height, &min_height,
+                       flex->margin, flex->padding, flex->border);
+
+       if (flex->width == AUTO) {
+               int w = available_width;
+               int fixed = 0;
+               float frac = 0;
+
+               calculate_mbp_width(ctx->unit_len_ctx, flex->style, LEFT,
+                               true, true, true, &fixed, &frac);
+               calculate_mbp_width(ctx->unit_len_ctx, flex->style, RIGHT,
+                               true, true, true, &fixed, &frac);
+
+               w -= frac * available_width + fixed;
+               flex->width = w > 0 ? w : 0;
+       }
+
+       if (flex->width == AUTO) {
+               flex->width = available_width;
+       }
+
+       available_width -= flex->margin[LEFT] +
+                          flex->margin[RIGHT] +
+                          flex->border[LEFT].width +
+                          flex->border[RIGHT].width +
+                          flex->padding[LEFT] +
+                          flex->padding[RIGHT];
+
+       /* Place items onto lines. */
+       if (ctx->wrap == CSS_FLEX_WRAP_NOWRAP) {
+               fprintf(stderr, "Flex Wrap: nowrap\n");
+               struct flex_line_data *line = ctx->line.data;
+
+               for (size_t i = 0; i < ctx->item.count; i++) {
+                       struct flex_item_data *item = &ctx->item.data[i];
+                       struct box *b = item->box;
+
+                       if (!lh__box_is_absolute(b)) {
+                               line->main_size += item->main_size;
+                       }
+               }
+
+               line->first = 0;
+               line->count = ctx->item.count;
+               ctx->line.count = 1;
+       } else {
+               fprintf(stderr, "Flex Wrap: wrap\n");
+               size_t fitted = 0;
+               size_t pos = 0;
+
+               do {
+                       fitted = layout_flex__fit_to_line(ctx, pos,
+                                       available_width, content);
+                       pos += fitted;
+                       fprintf(stderr, "  pos: %zu, fitted: %zu\n",
+                                       pos, fitted);
+               } while (fitted != 0 && pos != ctx->item.count);
+
+               if (fitted == 0) {
+                       fprintf(stderr, "  Failed to fit any flex items\n");
+                       goto cleanup;
+               }
+       }
+
+       /* Layout children */
+       for (size_t i = 0; i < ctx->line.count; i++) {
+               fprintf(stderr, "  Line %zu: First: %zu, Count: %zu\n", i,
+                               ctx->line.data[i].first,
+                               ctx->line.data[i].count);
+               success = layout_flex__resolve_line(ctx,
+                               available_width, i);
+               if (!success) {
+                       goto cleanup;
+               }
+
+               ctx->height += ctx->line.data[i].height;
+       }
+
+       if (flex->height == AUTO) {
+               flex->height = ctx->height;
+       }
+
+       if (max_width >= 0 && flex->width > max_width) {
+               flex->width = max_width;
+       }
+       if (min_width >  0 && flex->width < min_width) {
+               flex->width = min_width;
+       }
+
+       if (flex->height != AUTO) {
+               if (max_height >= 0 && flex->height > max_height) {
+                       flex->height = max_height;
+               }
+               if (min_height >  0 && flex->height < min_height) {
+                       flex->height = min_height;
+               }
+       }
+
+       success = true;
+
+cleanup:
+       layout_flex_ctx__destroy(ctx);
+       fprintf(stderr, "Flex layout: %s\n\n", success ? "success" : "failure");
+       return success;
+}
diff --git a/content/handlers/html/layout_internal.h 
b/content/handlers/html/layout_internal.h
new file mode 100644
index 0000000..86feda7
--- /dev/null
+++ b/content/handlers/html/layout_internal.h
@@ -0,0 +1,642 @@
+/*
+ * Copyright 2003 James Bursa <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * interface to HTML layout.
+ *
+ * The main interface to the layout code is layout_document(), which takes a
+ * normalized box tree and assigns coordinates and dimensions to the boxes, and
+ * also adds boxes to the tree (eg. when formatting lines of text).
+ */
+
+#ifndef NETSURF_HTML_LAYOUT_INTERNAL_H
+#define NETSURF_HTML_LAYOUT_INTERNAL_H
+
+struct box;
+struct html_content;
+struct gui_layout_table;
+
+#define AUTO INT_MIN
+
+/* Fixed point percentage (a) of an integer (b), to an integer */
+#define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100)))
+
+/**
+ * Layout a block formatting context.
+ *
+ * \param  block            BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
+ * \param  viewport_height  Height of viewport in pixels or -ve if unknown
+ * \param  content          Memory pool for any new boxes
+ * \return  true on success, false on memory exhaustion
+ *
+ * This function carries out layout of a block and its children, as described
+ * in CSS 2.1 9.4.1.
+ */
+bool layout_block_context(
+               struct box *block,
+               int viewport_height,
+               html_content *content);
+
+/**
+ * Layout a table.
+ *
+ * \param  table            table to layout
+ * \param  available_width  width of containing block
+ * \param  content          memory pool for any new boxes
+ * \return  true on success, false on memory exhaustion
+ */
+bool layout_table(
+               struct box *table,
+               int available_width,
+               html_content *content);
+
+/**
+ * Layout a flex container.
+ *
+ * \param[in] flex             table to layout
+ * \param[in] available_width  width of containing block
+ * \param[in] content          memory pool for any new boxes
+ * \return  true on success, false on memory exhaustion
+ */
+bool layout_flex(
+               struct box *flex,
+               int available_width,
+               html_content *content);
+
+typedef uint8_t (*css_len_func)(
+               const css_computed_style *style,
+               css_fixed *length, css_unit *unit);
+typedef uint8_t (*css_border_style_func)(
+               const css_computed_style *style);
+typedef uint8_t (*css_border_color_func)(
+               const css_computed_style *style,
+               css_color *color);
+
+/** Array of per-side access functions for computed style margins. */
+extern const css_len_func margin_funcs[4];
+
+/** Array of per-side access functions for computed style paddings. */
+extern const css_len_func padding_funcs[4];
+
+/** Array of per-side access functions for computed style border_widths. */
+extern const css_len_func border_width_funcs[4];
+
+/** Array of per-side access functions for computed style border styles. */
+extern const css_border_style_func border_style_funcs[4];
+
+/** Array of per-side access functions for computed style border colors. */
+extern const css_border_color_func border_color_funcs[4];
+
+/** Layout helper: Check whether box is a float. */
+static inline bool lh__box_is_float_box(const struct box *b)
+{
+       return b->type == BOX_FLOAT_LEFT ||
+              b->type == BOX_FLOAT_RIGHT;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_inline_flow(const struct box *b)
+{
+       return b->type == BOX_INLINE ||
+              b->type == BOX_INLINE_FLEX ||
+              b->type == BOX_INLINE_BLOCK ||
+              b->type == BOX_TEXT ||
+              b->type == BOX_INLINE_END;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_flex_container(const struct box *b)
+{
+       return b->type == BOX_FLEX ||
+              b->type == BOX_INLINE_FLEX;
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR.) */
+static inline bool lh__box_is_inline_level(const struct box *b)
+{
+       return lh__box_is_inline_flow(b) ||
+              b->type == BOX_BR;
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR, floats.) */
+static inline bool lh__box_is_inline_content(const struct box *b)
+{
+       return lh__box_is_float_box(b) ||
+              lh__box_is_inline_level(b);
+}
+
+/** Layout helper: Check whether box is an object. */
+static inline bool lh__box_is_object(const struct box *b)
+{
+       return b->object ||
+              (b->flags & (IFRAME | REPLACE_DIM));
+}
+
+/** Layout helper: Check whether box is replaced. */
+static inline bool lh__box_is_replace(const struct box *b)
+{
+       return b->gadget ||
+              lh__box_is_object(b);
+}
+
+/** Layout helper: Check for CSS border on given side. */
+static inline bool lh__have_border(
+               enum box_side side,
+               const css_computed_style *style)
+{
+       return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
+}
+
+static inline bool lh__box_is_absolute(const struct box *b)
+{
+       return css_computed_position(b->style) == CSS_POSITION_ABSOLUTE;
+}
+
+static inline bool layout_flex__main_is_horizontal(struct box *flex)
+{
+       const css_computed_style *style = flex->style;
+
+       assert(style != NULL);
+
+       switch (css_computed_flex_direction(style)) {
+       default:                        /* Fallthrough. */
+       case CSS_FLEX_DIRECTION_ROW:    /* Fallthrough. */
+       case CSS_FLEX_DIRECTION_ROW_REVERSE:
+               return true;
+       case CSS_FLEX_DIRECTION_COLUMN: /* Fallthrough. */
+       case CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+               return false;
+       }
+}
+
+static inline int lh__delta_outer_height(const struct box *b)
+{
+       return b->margin[TOP] +
+              b->margin[BOTTOM] +
+              b->border[TOP].width +
+              b->border[BOTTOM].width +
+              b->padding[TOP] +
+              b->padding[BOTTOM];
+}
+
+static inline int lh__delta_outer_width(const struct box *b)
+{
+       return b->margin[LEFT] +
+              b->margin[RIGHT] +
+              b->border[LEFT].width +
+              b->border[RIGHT].width +
+              b->padding[LEFT] +
+              b->padding[RIGHT];
+}
+
+/**
+ * Determine width of margin, borders, and padding on one side of a box.
+ *
+ * \param unit_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
+ * \param border   whether border width is required
+ * \param padding  whether padding width is required
+ * \param fixed    increased by sum of fixed margin, border, and padding
+ * \param frac     increased by sum of fractional margin and padding
+ */
+static inline void calculate_mbp_width(
+               const css_unit_ctx *unit_len_ctx,
+               const css_computed_style *style,
+               unsigned int side,
+               bool margin,
+               bool border,
+               bool padding,
+               int *fixed,
+               float *frac)
+{
+       css_fixed value = 0;
+       css_unit unit = CSS_UNIT_PX;
+
+       assert(style);
+
+       /* margin */
+       if (margin) {
+               enum css_margin_e type;
+
+               type = margin_funcs[side](style, &value, &unit);
+               if (type == CSS_MARGIN_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               *frac += FIXTOINT(FDIV(value, F_100));
+                       } else {
+                               *fixed += FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               }
+       }
+
+       /* border */
+       if (border) {
+               if (lh__have_border(side, style)) {
+                       border_width_funcs[side](style, &value, &unit);
+
+                       *fixed += FIXTOINT(css_unit_len2device_px(
+                                       style, unit_len_ctx,
+                                       value, unit));
+               }
+       }
+
+       /* padding */
+       if (padding) {
+               padding_funcs[side](style, &value, &unit);
+               if (unit == CSS_UNIT_PCT) {
+                       *frac += FIXTOINT(FDIV(value, F_100));
+               } else {
+                       *fixed += FIXTOINT(css_unit_len2device_px(
+                                       style, unit_len_ctx,
+                                       value, unit));
+               }
+       }
+}
+
+/**
+ * Adjust a specified width or height for the box-sizing property.
+ *
+ * This turns the specified dimension into a content-box dimension.
+ *
+ * \param  unit_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,
+ *                             else set false for a height
+ * \param  dimension       current value for given width/height dimension.
+ *                             updated to new value after consideration of
+ *                             gadget properties.
+ */
+static inline void layout_handle_box_sizing(
+               const css_unit_ctx *unit_len_ctx,
+               const struct box *box,
+               int available_width,
+               bool setwidth,
+               int *dimension)
+{
+       enum css_box_sizing_e bs;
+
+       assert(box && box->style);
+
+       bs = css_computed_box_sizing(box->style);
+
+       if (bs == CSS_BOX_SIZING_BORDER_BOX) {
+               int orig = *dimension;
+               int fixed = 0;
+               float frac = 0;
+
+               calculate_mbp_width(unit_len_ctx, box->style,
+                               setwidth ? LEFT : TOP,
+                               false, true, true, &fixed, &frac);
+               calculate_mbp_width(unit_len_ctx, box->style,
+                               setwidth ? RIGHT : BOTTOM,
+                               false, true, true, &fixed, &frac);
+               orig -= frac * available_width + fixed;
+               *dimension = orig > 0 ? orig : 0;
+       }
+}
+
+/**
+ * Calculate width, height, and thickness of margins, paddings, and borders.
+ *
+ * \param  unit_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
+ * \param  style            style giving width, height, margins, paddings,
+ *                          and borders
+ * \param  width            updated to width, may be NULL
+ * \param  height           updated to height, may be NULL
+ * \param  max_width        updated to max-width, may be NULL
+ * \param  min_width        updated to min-width, may be NULL
+ * \param  max_height       updated to max-height, may be NULL
+ * \param  min_height       updated to min-height, may be NULL
+ * \param  margin           filled with margins, may be NULL
+ * \param  padding          filled with paddings, may be NULL
+ * \param  border           filled with border widths, may be NULL
+ */
+static inline void layout_find_dimensions(
+               const css_unit_ctx *unit_len_ctx,
+               int available_width,
+               int viewport_height,
+               const struct box *box,
+               const css_computed_style *style,
+               int *width,
+               int *height,
+               int *max_width,
+               int *min_width,
+               int *max_height,
+               int *min_height,
+               int margin[4],
+               int padding[4],
+               struct box_border border[4])
+{
+       struct box *containing_block = NULL;
+       unsigned int i;
+
+       if (width) {
+               enum css_width_e wtype;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               wtype = css_computed_width(style, &value, &unit);
+
+               if (wtype == CSS_WIDTH_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               *width = FPCT_OF_INT_TOINT(
+                                               value, available_width);
+                       } else {
+                               *width = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       *width = AUTO;
+               }
+
+               if (*width != AUTO) {
+                       layout_handle_box_sizing(unit_len_ctx, box,
+                                       available_width, true, width);
+               }
+       }
+
+       if (height) {
+               enum css_height_e htype;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               htype = css_computed_height(style, &value, &unit);
+
+               if (htype == CSS_HEIGHT_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               enum css_height_e cbhtype;
+
+                               if (css_computed_position(box->style) ==
+                                               CSS_POSITION_ABSOLUTE &&
+                                               box->parent) {
+                                       /* Box is absolutely positioned */
+                                       assert(box->float_container);
+                                       containing_block = box->float_container;
+                               } else if (box->float_container &&
+                                       css_computed_position(box->style) !=
+                                               CSS_POSITION_ABSOLUTE &&
+                                       (css_computed_float(box->style) ==
+                                               CSS_FLOAT_LEFT ||
+                                        css_computed_float(box->style) ==
+                                               CSS_FLOAT_RIGHT)) {
+                                       /* Box is a float */
+                                       assert(box->parent &&
+                                               box->parent->parent &&
+                                               box->parent->parent->parent);
+
+                                       containing_block =
+                                               box->parent->parent->parent;
+                               } else if (box->parent && box->parent->type !=
+                                               BOX_INLINE_CONTAINER) {
+                                       /* Box is a block level element */
+                                       containing_block = box->parent;
+                               } else if (box->parent && box->parent->type ==
+                                               BOX_INLINE_CONTAINER) {
+                                       /* Box is an inline block */
+                                       assert(box->parent->parent);
+                                       containing_block = box->parent->parent;
+                               }
+
+                               if (containing_block) {
+                                       css_fixed f = 0;
+                                       css_unit u = CSS_UNIT_PX;
+
+                                       cbhtype = css_computed_height(
+                                                       containing_block->style,
+                                                       &f, &u);
+                               }
+
+                               if (containing_block &&
+                                       containing_block->height != AUTO &&
+                                       (css_computed_position(box->style) ==
+                                                       CSS_POSITION_ABSOLUTE ||
+                                               cbhtype == CSS_HEIGHT_SET)) {
+                                       /* Box is absolutely positioned or its
+                                        * containing block has a valid
+                                        * specified height.
+                                        * (CSS 2.1 Section 10.5) */
+                                       *height = FPCT_OF_INT_TOINT(value,
+                                               containing_block->height);
+                               } else if ((!box->parent ||
+                                               !box->parent->parent) &&
+                                               viewport_height >= 0) {
+                                       /* If root element or it's child
+                                        * (HTML or BODY) */
+                                       *height = FPCT_OF_INT_TOINT(value,
+                                                       viewport_height);
+                               } else {
+                                       /* precentage height not permissible
+                                        * treat height as auto */
+                                       *height = AUTO;
+                               }
+                       } else {
+                               *height = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       *height = AUTO;
+               }
+
+               if (*height != AUTO) {
+                       layout_handle_box_sizing(unit_len_ctx, box,
+                                       available_width, false, height);
+               }
+       }
+
+       if (max_width) {
+               enum css_max_width_e type;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               type = css_computed_max_width(style, &value, &unit);
+
+               if (type == CSS_MAX_WIDTH_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               *max_width = FPCT_OF_INT_TOINT(value,
+                                               available_width);
+                       } else {
+                               *max_width = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       /* Inadmissible */
+                       *max_width = -1;
+               }
+
+               if (*max_width != -1) {
+                       layout_handle_box_sizing(unit_len_ctx, box,
+                                       available_width, true, max_width);
+               }
+       }
+
+       if (min_width) {
+               enum css_min_width_e type;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               type = ns_computed_min_width(style, &value, &unit);
+
+               if (type == CSS_MIN_WIDTH_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               *min_width = FPCT_OF_INT_TOINT(value,
+                                               available_width);
+                       } else {
+                               *min_width = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       /* Inadmissible */
+                       *min_width = 0;
+               }
+
+               if (*min_width != 0) {
+                       layout_handle_box_sizing(unit_len_ctx, box,
+                                       available_width, true, min_width);
+               }
+       }
+
+       if (max_height) {
+               enum css_max_height_e type;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               type = css_computed_max_height(style, &value, &unit);
+
+               if (type == CSS_MAX_HEIGHT_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               /* TODO: handle percentage */
+                               *max_height = -1;
+                       } else {
+                               *max_height = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       /* Inadmissible */
+                       *max_height = -1;
+               }
+       }
+
+       if (min_height) {
+               enum css_min_height_e type;
+               css_fixed value = 0;
+               css_unit unit = CSS_UNIT_PX;
+
+               type = ns_computed_min_height(style, &value, &unit);
+
+               if (type == CSS_MIN_HEIGHT_SET) {
+                       if (unit == CSS_UNIT_PCT) {
+                               /* TODO: handle percentage */
+                               *min_height = 0;
+                       } else {
+                               *min_height = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               } else {
+                       /* Inadmissible */
+                       *min_height = 0;
+               }
+       }
+
+       for (i = 0; i != 4; i++) {
+               if (margin) {
+                       enum css_margin_e type = CSS_MARGIN_AUTO;
+                       css_fixed value = 0;
+                       css_unit unit = CSS_UNIT_PX;
+
+                       type = margin_funcs[i](style, &value, &unit);
+
+                       if (type == CSS_MARGIN_SET) {
+                               if (unit == CSS_UNIT_PCT) {
+                                       margin[i] = FPCT_OF_INT_TOINT(value,
+                                                       available_width);
+                               } else {
+                                       margin[i] = 
FIXTOINT(css_unit_len2device_px(
+                                                       style, unit_len_ctx,
+                                                       value, unit));
+                               }
+                       } else {
+                               margin[i] = AUTO;
+                       }
+               }
+
+               if (padding) {
+                       css_fixed value = 0;
+                       css_unit unit = CSS_UNIT_PX;
+
+                       padding_funcs[i](style, &value, &unit);
+
+                       if (unit == CSS_UNIT_PCT) {
+                               padding[i] = FPCT_OF_INT_TOINT(value,
+                                               available_width);
+                       } else {
+                               padding[i] = FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+                       }
+               }
+
+               /* Table cell borders are populated in table.c */
+               if (border && box->type != BOX_TABLE_CELL) {
+                       enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE;
+                       css_color color = 0;
+                       css_fixed value = 0;
+                       css_unit unit = CSS_UNIT_PX;
+
+                       border_width_funcs[i](style, &value, &unit);
+                       bstyle = border_style_funcs[i](style);
+                       border_color_funcs[i](style, &color);
+
+                       border[i].style = bstyle;
+                       border[i].c = color;
+
+                       if (bstyle == CSS_BORDER_STYLE_HIDDEN ||
+                                       bstyle == CSS_BORDER_STYLE_NONE)
+                               /* spec unclear: following Mozilla */
+                               border[i].width = 0;
+                       else
+                               border[i].width = 
FIXTOINT(css_unit_len2device_px(
+                                               style, unit_len_ctx,
+                                               value, unit));
+
+                       /* Special case for border-collapse: make all borders
+                        * on table/table-row-group/table-row zero width. */
+                       if (css_computed_border_collapse(style) ==
+                                       CSS_BORDER_COLLAPSE_COLLAPSE &&
+                                       (box->type == BOX_TABLE ||
+                                        box->type == BOX_TABLE_ROW_GROUP ||
+                                        box->type == BOX_TABLE_ROW))
+                               border[i].width = 0;
+               }
+       }
+}
+
+#endif
diff --git a/content/handlers/html/table.c b/content/handlers/html/table.c
index 4ffccea..5e5d1cc 100644
--- a/content/handlers/html/table.c
+++ b/content/handlers/html/table.c
@@ -836,8 +836,12 @@ table_calculate_column_types(const css_unit_ctx 
*unit_len_ctx, struct box *table
                                enum css_width_e type;
                                css_fixed value = 0;
                                css_unit unit = CSS_UNIT_PX;
-
-                               assert(cell->type == BOX_TABLE_CELL);
+if (cell->type != BOX_TABLE_CELL && cell->type != BOX_FLEX) {
+       box_dump(stderr, table, 0, false);
+       printf("cell %p type: %u\n", cell, cell->type);
+}
+                               assert(cell->type == BOX_TABLE_CELL ||
+                                      cell->type == BOX_FLEX);
                                assert(cell->style);
 
                                if (cell->columns != 1)


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=4341f589d4fbdf40f72e538f862d85fc3f30d1f9
commit 4341f589d4fbdf40f72e538f862d85fc3f30d1f9
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    CSS: Fix dump of display: inline-flex

diff --git a/content/handlers/css/dump.c b/content/handlers/css/dump.c
index 6ffc11e..ea411bf 100644
--- a/content/handlers/css/dump.c
+++ b/content/handlers/css/dump.c
@@ -868,7 +868,7 @@ void nscss_dump_computed_style(FILE *stream, const 
css_computed_style *style)
                fprintf(stream, "display: flex ");
                break;
        case CSS_DISPLAY_INLINE_FLEX:
-               fprintf(stream, "display: inline-flax ");
+               fprintf(stream, "display: inline-flex ");
                break;
        default:
                break;


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=93203140a3369caa389377ae23dd257c47df7921
commit 93203140a3369caa389377ae23dd257c47df7921
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Layout: Constify box through layout_find_dimensions().

diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index 442ced6..cb5be5d 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -1293,7 +1293,7 @@ static void
 layout_find_dimensions(const css_unit_ctx *unit_len_ctx,
                       int available_width,
                       int viewport_height,
-                      struct box *box,
+                      const struct box *box,
                       const css_computed_style *style,
                       int *width,
                       int *height,


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=62c7925c3e30233de9fa8550b17fe7aacdf4c902
commit 62c7925c3e30233de9fa8550b17fe7aacdf4c902
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Layout: Constify box through layout_handle_box_sizing().

diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index fb4010d..442ced6 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -1242,7 +1242,7 @@ static void layout_minmax_block(
  */
 static void layout_handle_box_sizing(
                const css_unit_ctx *unit_len_ctx,
-               struct box *box,
+               const struct box *box,
                int available_width,
                bool setwidth,
                int *dimension)


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=484441ac8064620fce0ec1a8d30581e447be8be8
commit 484441ac8064620fce0ec1a8d30581e447be8be8
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    layout: Add helpers for various box type checks.

diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index 4d55bb5..fb4010d 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -123,6 +123,50 @@ static inline bool lh__have_border(
        return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
 }
 
+/** Layout helper: Check whether box is a float. */
+static inline bool lh__box_is_float_box(const struct box *b)
+{
+       return b->type == BOX_FLOAT_LEFT ||
+              b->type == BOX_FLOAT_RIGHT;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_inline_flow(const struct box *b)
+{
+       return b->type == BOX_INLINE ||
+              b->type == BOX_INLINE_BLOCK ||
+              b->type == BOX_TEXT ||
+              b->type == BOX_INLINE_END;
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR.) */
+static inline bool lh__box_is_inline_level(const struct box *b)
+{
+       return lh__box_is_inline_flow(b) ||
+              b->type == BOX_BR;
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR, floats.) */
+static inline bool lh__box_is_inline_content(const struct box *b)
+{
+       return lh__box_is_float_box(b) ||
+              lh__box_is_inline_level(b);
+}
+
+/** Layout helper: Check whether box is an object. */
+static inline bool lh__box_is_object(const struct box *b)
+{
+       return b->object ||
+              (b->flags & (IFRAME | REPLACE_DIM));
+}
+
+/** Layout helper: Check whether box is replaced. */
+static inline bool lh__box_is_replace(const struct box *b)
+{
+       return b->gadget ||
+              lh__box_is_object(b);
+}
+
 /** Array of per-side access functions for computed style border colors. */
 static const css_border_color_func border_color_funcs[4] = {
        [TOP]    = css_computed_border_top_color,
@@ -595,11 +639,7 @@ layout_minmax_line(struct box *first,
                css_fixed value = 0;
                css_unit unit = CSS_UNIT_PX;
 
-               assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
-                               b->type == BOX_FLOAT_LEFT ||
-                               b->type == BOX_FLOAT_RIGHT ||
-                               b->type == BOX_BR || b->type == BOX_TEXT ||
-                               b->type == BOX_INLINE_END);
+               assert(lh__box_is_inline_content(b));
 
                NSLOG(layout, DEBUG, "%p: min %i, max %i", b, min, max);
 
@@ -608,7 +648,7 @@ layout_minmax_line(struct box *first,
                        break;
                }
 
-               if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT) {
+               if (lh__box_is_float_box(b)) {
                        assert(b->children);
                        if (b->children->type == BOX_BLOCK)
                                layout_minmax_block(b->children, font_func,
@@ -675,8 +715,7 @@ layout_minmax_line(struct box *first,
                        continue;
                }
 
-               if (!b->object && !(b->flags & IFRAME) && !b->gadget &&
-                               !(b->flags & REPLACE_DIM)) {
+               if (lh__box_is_replace(b) == false) {
                        /* inline non-replaced, 10.3.1 and 10.6.1 */
                        bool no_wrap_box;
                        if (!b->text)
@@ -1001,8 +1040,7 @@ static void layout_minmax_block(
        }
 
        /* set whether the minimum width is of any interest for this box */
-       if (((block->parent && (block->parent->type == BOX_FLOAT_LEFT ||
-                       block->parent->type == BOX_FLOAT_RIGHT)) ||
+       if (((block->parent && lh__box_is_float_box(block->parent)) ||
                        block->type == BOX_INLINE_BLOCK) &&
                        wtype != CSS_WIDTH_SET) {
                /* box shrinks to fit; need minimum width */
@@ -3216,20 +3254,14 @@ layout_line(struct box *first,
        for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) {
                int min_width, max_width, min_height, max_height;
 
-               assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
-                               b->type == BOX_FLOAT_LEFT ||
-                               b->type == BOX_FLOAT_RIGHT ||
-                               b->type == BOX_BR || b->type == BOX_TEXT ||
-                               b->type == BOX_INLINE_END);
-
+               assert(lh__box_is_inline_content(b));
 
                NSLOG(layout, DEBUG,  "pass 1: b %p, x %i", b, x);
 
-
                if (b->type == BOX_BR)
                        break;
 
-               if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT)
+               if (lh__box_is_float_box(b))
                        continue;
                if (b->type == BOX_INLINE_BLOCK &&
                                (css_computed_position(b->style) ==
@@ -3295,8 +3327,7 @@ layout_line(struct box *first,
                        continue;
                }
 
-               if (!b->object && !(b->flags & IFRAME) && !b->gadget &&
-                               !(b->flags & REPLACE_DIM)) {
+               if (lh__box_is_replace(b) == false) {
                        /* inline non-replaced, 10.3.1 and 10.6.1 */
                        b->height = line_height(&content->unit_len_ctx,
                                        b->style ? b->style :
@@ -3456,10 +3487,7 @@ layout_line(struct box *first,
                                                CSS_POSITION_FIXED)) {
                        b->x = x + space_after;
 
-               } else if (b->type == BOX_INLINE ||
-                               b->type == BOX_INLINE_BLOCK ||
-                               b->type == BOX_TEXT ||
-                               b->type == BOX_INLINE_END) {
+               } else if (lh__box_is_inline_flow(b)) {
                        assert(b->width != UNKNOWN_WIDTH);
 
                        x_previous = x;
@@ -3798,9 +3826,7 @@ layout_line(struct box *first,
                        d->y = *y;
                        continue;
                } else if ((d->type == BOX_INLINE &&
-                               ((d->object || d->gadget) == false) &&
-                               !(d->flags & IFRAME) &&
-                               !(d->flags & REPLACE_DIM)) ||
+                               lh__box_is_replace(d) == false) ||
                                d->type == BOX_BR ||
                                d->type == BOX_TEXT ||
                                d->type == BOX_INLINE_END) {
@@ -3921,8 +3947,7 @@ static bool layout_inline_container(struct box 
*inline_container, int width,
                                whitespace == CSS_WHITE_SPACE_PRE_WRAP);
                }
 
-               if ((!c->object && !(c->flags & REPLACE_DIM) &&
-                               !(c->flags & IFRAME) &&
+               if ((lh__box_is_object(c) == false &&
                                c->text && (c->length || is_pre)) ||
                                c->type == BOX_BR)
                        has_text_children = true;
@@ -4102,8 +4127,7 @@ layout_block_context(struct box *block,
                lm = rm = 0;
 
                if (box->type == BOX_BLOCK || box->flags & IFRAME) {
-                       if (!box->object && !(box->flags & IFRAME) &&
-                                       !(box->flags & REPLACE_DIM) &&
+                       if (lh__box_is_object(box) == false &&
                                        box->style &&
                                        (overflow_x != CSS_OVERFLOW_VISIBLE ||
                                         overflow_y != CSS_OVERFLOW_VISIBLE)) {


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=2139e583cdeafcd7824451db0debbfaaaf652d62
commit 2139e583cdeafcd7824451db0debbfaaaf652d62
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    layout: Add helper for checking if a style has a border on a side.

diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index f50a711..4d55bb5 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -115,6 +115,14 @@ static const css_border_style_func border_style_funcs[4] = 
{
        [LEFT]   = css_computed_border_left_style,
 };
 
+/** Layout helper: Check for CSS border on given side. */
+static inline bool lh__have_border(
+               enum box_side side,
+               const css_computed_style *style)
+{
+       return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
+}
+
 /** Array of per-side access functions for computed style border colors. */
 static const css_border_color_func border_color_funcs[4] = {
        [TOP]    = css_computed_border_top_color,
@@ -307,8 +315,7 @@ calculate_mbp_width(const css_unit_ctx *unit_len_ctx,
 
        /* border */
        if (border) {
-               if (border_style_funcs[side](style) !=
-                               CSS_BORDER_STYLE_NONE) {
+               if (lh__have_border(side, style)) {
                        border_width_funcs[side](style, &value, &unit);
 
                        *fixed += FIXTOINT(css_unit_len2device_px(


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=46e0fc5bf878ebc8647f2bdc4f332247ca033ffc
commit 46e0fc5bf878ebc8647f2bdc4f332247ca033ffc
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    layout: Drop redundant else block.

diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index c06fdf6..f50a711 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -5024,8 +5024,6 @@ layout_absolute(struct box *box,
                                containing_block->padding[RIGHT];
                containing_block->height += containing_block->padding[TOP] +
                                containing_block->padding[BOTTOM];
-       } else {
-               /** \todo inline containers */
        }
 
        layout_compute_offsets(&content->unit_len_ctx, box, containing_block,


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=eb2ccb63df03087c4c357c6c56eff59e106f24be
commit eb2ccb63df03087c4c357c6c56eff59e106f24be
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    CSS: Simplify css display to box type conversion.

diff --git a/content/handlers/css/dump.c b/content/handlers/css/dump.c
index 1e448e0..6ffc11e 100644
--- a/content/handlers/css/dump.c
+++ b/content/handlers/css/dump.c
@@ -814,7 +814,7 @@ void nscss_dump_computed_style(FILE *stream, const 
css_computed_style *style)
        }
 
        /* display */
-       val = ns_computed_display_static(style);
+       val = css_computed_display_static(style);
        switch (val) {
        case CSS_DISPLAY_INLINE:
                fprintf(stream, "display: inline ");
@@ -864,6 +864,12 @@ void nscss_dump_computed_style(FILE *stream, const 
css_computed_style *style)
        case CSS_DISPLAY_NONE:
                fprintf(stream, "display: none ");
                break;
+       case CSS_DISPLAY_FLEX:
+               fprintf(stream, "display: flex ");
+               break;
+       case CSS_DISPLAY_INLINE_FLEX:
+               fprintf(stream, "display: inline-flax ");
+               break;
        default:
                break;
        }
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index 541677a..3bd3955 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -26,43 +26,6 @@
 /** DPI of the screen, in fixed point units */
 extern css_fixed nscss_screen_dpi;
 
-/**
- * Temporary helper wrappers for for libcss computed style getter, while
- * we don't support flexbox related property values.
- */
-
-static inline uint8_t ns_computed_display(
-               const css_computed_style *style, bool root)
-{
-       uint8_t value = css_computed_display(style, root);
-
-       if (value == CSS_DISPLAY_FLEX) {
-               return CSS_DISPLAY_BLOCK;
-
-       } else if (value == CSS_DISPLAY_INLINE_FLEX) {
-               return CSS_DISPLAY_INLINE_BLOCK;
-       }
-
-       return value;
-}
-
-
-static inline uint8_t ns_computed_display_static(
-               const css_computed_style *style)
-{
-       uint8_t value = css_computed_display_static(style);
-
-       if (value == CSS_DISPLAY_FLEX) {
-               return CSS_DISPLAY_BLOCK;
-
-       } else if (value == CSS_DISPLAY_INLINE_FLEX) {
-               return CSS_DISPLAY_INLINE_BLOCK;
-       }
-
-       return value;
-}
-
-
 static inline uint8_t ns_computed_min_height(
                const css_computed_style *style,
                css_fixed *length, css_unit *unit)
diff --git a/content/handlers/html/box_construct.c 
b/content/handlers/html/box_construct.c
index 12d9df8..52e888e 100644
--- a/content/handlers/html/box_construct.c
+++ b/content/handlers/html/box_construct.c
@@ -86,28 +86,28 @@ struct box_construct_props {
 
 static const content_type image_types = CONTENT_IMAGE;
 
-/**
- * mapping from CSS display to box type this table must be in sync
- * with libcss' css_display enum
- */
+/* mapping from CSS display to box type
+ * this table must be in sync with libcss' css_display enum */
 static const box_type box_map[] = {
-       0, /* CSS_DISPLAY_INHERIT, */
-       BOX_INLINE, /* CSS_DISPLAY_INLINE, */
-       BOX_BLOCK, /* CSS_DISPLAY_BLOCK, */
-       BOX_BLOCK, /* CSS_DISPLAY_LIST_ITEM, */
-       BOX_INLINE, /* CSS_DISPLAY_RUN_IN, */
-       BOX_INLINE_BLOCK, /* CSS_DISPLAY_INLINE_BLOCK, */
-       BOX_TABLE, /* CSS_DISPLAY_TABLE, */
-       BOX_TABLE, /* CSS_DISPLAY_INLINE_TABLE, */
-       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_ROW_GROUP, */
-       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_HEADER_GROUP, */
-       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_FOOTER_GROUP, */
-       BOX_TABLE_ROW, /* CSS_DISPLAY_TABLE_ROW, */
-       BOX_NONE, /* CSS_DISPLAY_TABLE_COLUMN_GROUP, */
-       BOX_NONE, /* CSS_DISPLAY_TABLE_COLUMN, */
-       BOX_TABLE_CELL, /* CSS_DISPLAY_TABLE_CELL, */
-       BOX_INLINE, /* CSS_DISPLAY_TABLE_CAPTION, */
-       BOX_NONE /* CSS_DISPLAY_NONE */
+       BOX_BLOCK,           /* CSS_DISPLAY_INHERIT */
+       BOX_INLINE,          /* CSS_DISPLAY_INLINE */
+       BOX_BLOCK,           /* CSS_DISPLAY_BLOCK */
+       BOX_BLOCK,           /* CSS_DISPLAY_LIST_ITEM */
+       BOX_INLINE,          /* CSS_DISPLAY_RUN_IN */
+       BOX_INLINE_BLOCK,    /* CSS_DISPLAY_INLINE_BLOCK */
+       BOX_TABLE,           /* CSS_DISPLAY_TABLE */
+       BOX_TABLE,           /* CSS_DISPLAY_INLINE_TABLE */
+       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_ROW_GROUP */
+       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_HEADER_GROUP */
+       BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_FOOTER_GROUP */
+       BOX_TABLE_ROW,       /* CSS_DISPLAY_TABLE_ROW */
+       BOX_NONE,            /* CSS_DISPLAY_TABLE_COLUMN_GROUP */
+       BOX_NONE,            /* CSS_DISPLAY_TABLE_COLUMN */
+       BOX_TABLE_CELL,      /* CSS_DISPLAY_TABLE_CELL */
+       BOX_INLINE,          /* CSS_DISPLAY_TABLE_CAPTION */
+       BOX_NONE,            /* CSS_DISPLAY_NONE */
+       BOX_BLOCK,           /* CSS_DISPLAY_FLEX */
+       BOX_INLINE_BLOCK,    /* CSS_DISPLAY_INLINE_FLEX */
 };
 
 
@@ -142,7 +142,6 @@ static inline bool box_is_root(dom_node *n)
        return true;
 }
 
-
 /**
  * Extract transient construction properties
  *
@@ -329,7 +328,7 @@ box_construct_generate(dom_node *n,
        }
 
        /* create box for this element */
-       computed_display = ns_computed_display(style, box_is_root(n));
+       computed_display = css_computed_display(style, box_is_root(n));
        if (computed_display == CSS_DISPLAY_BLOCK ||
                        computed_display == CSS_DISPLAY_TABLE) {
                /* currently only support block level boxes */
@@ -342,7 +341,7 @@ box_construct_generate(dom_node *n,
                }
 
                /* set box type from computed display */
-               gen->type = box_map[ns_computed_display(
+               gen->type = box_map[css_computed_display(
                                style, box_is_root(n))];
 
                box_add_child(box, gen);
@@ -451,6 +450,7 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
 {
        dom_string *title0, *s;
        lwc_string *id = NULL;
+       enum css_display_e css_display;
        struct box *box = NULL, *old_box;
        css_select_results *styles = NULL;
        lwc_string *bgimage_uri;
@@ -549,16 +549,15 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
                dom_string_unref(s);
        }
 
+       css_display = css_computed_display_static(box->style);
+
        /* Set box type from computed display */
        if ((css_computed_position(box->style) == CSS_POSITION_ABSOLUTE ||
-                       css_computed_position(box->style) ==
-                                       CSS_POSITION_FIXED) &&
-                       (ns_computed_display_static(box->style) ==
-                                       CSS_DISPLAY_INLINE ||
-                        ns_computed_display_static(box->style) ==
-                                       CSS_DISPLAY_INLINE_BLOCK ||
-                        ns_computed_display_static(box->style) ==
-                                       CSS_DISPLAY_INLINE_TABLE)) {
+            css_computed_position(box->style) == CSS_POSITION_FIXED) &&
+                       (css_display == CSS_DISPLAY_INLINE ||
+                        css_display == CSS_DISPLAY_INLINE_BLOCK ||
+                        css_display == CSS_DISPLAY_INLINE_TABLE ||
+                        css_display == CSS_DISPLAY_INLINE_FLEX)) {
                /* Special case for absolute positioning: make absolute inlines
                 * into inline block so that the boxes are constructed in an
                 * inline container as if they were not absolutely positioned.
@@ -570,7 +569,7 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
                box->type = BOX_BLOCK;
        } else {
                /* Normal mapping */
-               box->type = box_map[ns_computed_display(box->style,
+               box->type = box_map[css_computed_display(box->style,
                                props.node_is_root)];
        }
 
@@ -587,10 +586,9 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
                                box->styles->styles[CSS_PSEUDO_ELEMENT_BEFORE]);
        }
 
-       if (box->type == BOX_NONE ||
-           (ns_computed_display(box->style,
-                                props.node_is_root) == CSS_DISPLAY_NONE &&
-            props.node_is_root == false)) {
+       if (box->type == BOX_NONE || (css_computed_display(box->style,
+                       props.node_is_root) == CSS_DISPLAY_NONE &&
+                       props.node_is_root == false)) {
                css_select_results_destroy(styles);
                box->styles = NULL;
                box->style = NULL;
@@ -681,7 +679,7 @@ box_construct_element(struct box_construct_ctx *ctx, bool 
*convert_children)
 
                box_add_child(props.inline_container, box);
        } else {
-               if (ns_computed_display(box->style, props.node_is_root) ==
+               if (css_computed_display(box->style, props.node_is_root) ==
                                CSS_DISPLAY_LIST_ITEM) {
                        /* List item: compute marker */
                        if (box_construct_marker(box, props.title, ctx,
@@ -1342,8 +1340,7 @@ struct box *box_for_node(dom_node *n)
        return box;
 }
 
-
-/* exported function documented in html/box_construct.h */
+/* exported function documented in html/box.h */
 bool
 box_extract_link(const html_content *content,
                 const dom_string *dsrel,
diff --git a/content/handlers/html/box_special.c 
b/content/handlers/html/box_special.c
index f761557..30f9f6f 100644
--- a/content/handlers/html/box_special.c
+++ b/content/handlers/html/box_special.c
@@ -825,8 +825,8 @@ box_canvas(dom_node *n,
        }
        *convert_children = false;
 
-       if (box->style &&
-           ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE)
+       if (box->style && css_computed_display(box->style,
+                       box_is_root(n)) == CSS_DISPLAY_NONE)
                return true;
 
        /* This is replaced content */
@@ -854,8 +854,8 @@ box_embed(dom_node *n,
        dom_string *src;
        dom_exception err;
 
-       if (box->style &&
-           ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE)
+       if (box->style && css_computed_display(box->style,
+                       box_is_root(n)) == CSS_DISPLAY_NONE)
                return true;
 
        params = talloc(content->bctx, struct object_params);
@@ -1025,8 +1025,8 @@ box_iframe(dom_node *n,
        struct content_html_iframe *iframe;
        int i;
 
-       if (box->style &&
-           ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE)
+       if (box->style && css_computed_display(box->style,
+                       box_is_root(n)) == CSS_DISPLAY_NONE)
                return true;
 
        if (box->style &&
@@ -1154,8 +1154,8 @@ box_image(dom_node *n,
        css_unit wunit = CSS_UNIT_PX;
        css_unit hunit = CSS_UNIT_PX;
 
-       if (box->style &&
-           ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE)
+       if (box->style && css_computed_display(box->style,
+                       box_is_root(n)) == CSS_DISPLAY_NONE)
                return true;
 
        /* handle alt text */
@@ -1322,10 +1322,9 @@ box_input(dom_node *n,
                                                   corestring_lwc_image)) {
                gadget->type = GADGET_IMAGE;
 
-               if (box->style &&
-                   ns_computed_display(box->style,
+               if (box->style && css_computed_display(box->style,
                                box_is_root(n)) != CSS_DISPLAY_NONE &&
-                   nsoption_bool(foreground_images) == true) {
+                               nsoption_bool(foreground_images) == true) {
                        dom_string *s;
 
                        err = dom_element_get_attribute(n, corestring_dom_src, 
&s);
@@ -1405,8 +1404,8 @@ box_object(dom_node *n,
        dom_node *c;
        dom_exception err;
 
-       if (box->style &&
-           ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE)
+       if (box->style && css_computed_display(box->style,
+                       box_is_root(n)) == CSS_DISPLAY_NONE)
                return true;
 
        if (box_get_attribute(n, "usemap", content->bctx, &box->usemap) ==


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=289c910a1cd0fe82a1d5678daad7f94f96dd60c9
commit 289c910a1cd0fe82a1d5678daad7f94f96dd60c9
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    HACK: USE LOCAL LIBCURL

diff --git a/Makefile b/Makefile
index f66f796..c30994f 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@ VQ=@
 
 # Override this only if the host compiler is called something different
 BUILD_CC := cc
-BUILD_CFLAGS = -g -W -Wall -Wundef -Wpointer-arith -Wcast-align \
+BUILD_CFLAGS = -I/usr/local -g -W -Wall -Wundef -Wpointer-arith -Wcast-align \
        -Wwrite-strings -Wmissing-declarations -Wuninitialized \
        -Wno-unused-parameter
 
@@ -147,7 +147,7 @@ $(eval $(call pkg_config_find_and_add,libdom,DOM))
 $(eval $(call pkg_config_find_and_add,libnsutils,nsutils))
 
 # Common libraries without pkg-config support
-LDFLAGS += -lz
+LDFLAGS += -L/usr/local -lz
 
 # Optional libraries with pkgconfig
 
@@ -324,6 +324,7 @@ endif
 
 OBJECTS := $(sort $(addprefix $(OBJROOT)/,$(subst /,_,$(patsubst 
%.c,%.o,$(patsubst %.cpp,%.o,$(patsubst %.m,%.o,$(patsubst 
%.s,%.o,$(SOURCES))))))))
 
+
 # Include directory flags
 IFLAGS = $(addprefix -I,$(INCLUDE_DIRS))
 


-----------------------------------------------------------------------


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to