Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3
...commit
http://git.netsurf-browser.org/netsurf.git/commit/d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3
...tree
http://git.netsurf-browser.org/netsurf.git/tree/d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3
The branch, tlsa/flex has been updated
discards 01d03a7899c759259b21ca1e1cccc3faf2a53e2c (commit)
via d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3 (commit)
via 5b011d4434468edeb06675624dd3b00b8ab476ce (commit)
via 04e9db66f1395e66293e94b7e7ec2fc95d9d4f90 (commit)
via d0470365d7db7ad5418c899908e5232d93c6fe6f (commit)
via 5b6b7ab896f9628fa3e80dfb1214c630cd31b414 (commit)
via 8fb6610d7116713f97695a0a07db927d84ef1008 (commit)
via 6e34e01118d38cdaa12faef8efc0da1a9107a579 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (01d03a7899c759259b21ca1e1cccc3faf2a53e2c)
\
N -- N -- N (d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3
commit d405207bde232b6e8d5f0ba2a7d7c7e4d5ffb4a3
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
WIP: Flex columns
diff --git a/content/handlers/html/layout_flex.c
b/content/handlers/html/layout_flex.c
index 2c2c7ad..8a53b98 100644
--- a/content/handlers/html/layout_flex.c
+++ b/content/handlers/html/layout_flex.c
@@ -51,10 +51,10 @@ struct flex_item_data {
css_fixed shrink;
css_fixed grow;
- int min_width;
- int max_width;
- int min_height;
- int max_height;
+ int min_main;
+ int max_main;
+ int min_cross;
+ int max_cross;
int target_main_size;
int base_size;
@@ -80,8 +80,10 @@ struct flex_ctx {
const struct box *flex;
const css_unit_ctx *unit_len_ctx;
+ int main_size;
int cross_size;
+ bool horizontal;
enum css_flex_wrap_e wrap;
struct flex_items {
@@ -134,18 +136,54 @@ static struct flex_ctx *layout_flex_ctx__create(
ctx->flex = flex;
ctx->content = content;
ctx->unit_len_ctx = &content->unit_len_ctx;
+
ctx->wrap = css_computed_flex_wrap(flex->style);
+ ctx->horizontal = layout_flex__main_is_horizontal(flex);
return ctx;
}
-static inline void layout_flex__base_and_main_sizes(
+static bool layout_flex_item(
+ const struct flex_ctx *ctx,
+ const struct flex_item_data *item,
+ int available_width)
+{
+ bool success;
+ struct box *b = item->box;
+
+ switch (b->type) {
+ case BOX_BLOCK:
+ success = layout_block_context(b, -1,
+ ctx->content);
+ break;
+ case BOX_TABLE:
+ b->float_container = b->parent;
+ success = layout_table(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ case BOX_FLEX:
+ b->float_container = b->parent;
+ success = layout_flex(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ default:
+ assert(0 && "Bad flex item back type");
+ success = false;
+ break;
+ }
+
+ return success;
+}
+
+static inline bool 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);
+ int delta_outer_main = lh__delta_outer_main(b);
if (item->basis == CSS_FLEX_BASIS_SET) {
if (item->basis_unit == CSS_UNIT_PCT) {
@@ -160,37 +198,59 @@ static inline void layout_flex__base_and_main_sizes(
}
} else if (item->basis == CSS_FLEX_BASIS_AUTO) {
- item->base_size = b->width;
+ item->base_size = ctx->horizontal ? b->width : b->height;
} else {
item->base_size = AUTO;
}
+ if (ctx->horizontal == false) {
+ if (b->width == AUTO) {
+ b->width = min(available_width, b->max_width);
+ b->width -= lh__delta_outer_cross(b);
+ }
+
+ if (!layout_flex_item(ctx, item, available_width)) {
+ NSLOG(flex, WARNING, "box %p: layout failed", b);
+ return false;
+ }
+ }
+
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;
+ if (ctx->horizontal == false) {
+ item->base_size = b->height;
+ } else {
+ item->base_size = b->max_width;
+ }
}
- item->base_size += delta_outer_width;
+ item->base_size = min(item->base_size + delta_outer_main,
+ available_width);
- item->base_size = max(min(item->base_size, available_width),
- b->min_width + delta_outer_width);
+ if (ctx->horizontal) {
+ item->base_size = max(item->base_size,
+ b->min_width + delta_outer_main);
+ }
item->target_main_size = item->base_size;
item->main_size = item->base_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->max_main > 0 &&
+ item->main_size > item->max_main + delta_outer_main) {
+ item->main_size = item->max_main + delta_outer_main;
}
- if (item->main_size < item->min_width + delta_outer_width) {
- item->main_size = item->min_width + delta_outer_width;
+ if (item->main_size < item->min_main + delta_outer_main) {
+ item->main_size = item->min_main + delta_outer_main;
}
+
NSLOG(flex, WARNING, "flex-item box: %p: base_size: %i, main_size %i",
b, item->base_size, item->main_size);
+
+ return true;
}
static void layout_flex_ctx__populate_item_data(
@@ -199,6 +259,7 @@ static void layout_flex_ctx__populate_item_data(
int available_width)
{
size_t i = 0;
+ bool horizontal = ctx->horizontal;
for (struct box *b = flex->children; b != NULL; b = b->next) {
struct flex_item_data *item = &ctx->item.data[i++];
@@ -206,8 +267,10 @@ static void layout_flex_ctx__populate_item_data(
b->float_container = b->parent;
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,
+ horizontal ? &item->max_main : &item->max_cross,
+ horizontal ? &item->min_main : &item->min_cross,
+ horizontal ? &item->max_cross : &item->max_main,
+ horizontal ? &item->min_cross : &item->min_main,
b->margin, b->padding, b->border);
b->float_container = NULL;
@@ -244,11 +307,12 @@ static bool layout_flex_ctx__ensure_line(struct flex_ctx
*ctx)
return true;
}
-static size_t layout_flex__build_line(struct flex_ctx *ctx,
+static struct flex_line_data *layout_flex__build_line(struct flex_ctx *ctx,
size_t item_index, int available_width, html_content *content)
{
struct flex_line_data *line;
- int used_width = 0;
+ int available_main;
+ int used_main = 0;
if (!layout_flex_ctx__ensure_line(ctx)) {
return 0;
@@ -257,21 +321,32 @@ static size_t layout_flex__build_line(struct flex_ctx
*ctx,
line = &ctx->line.data[ctx->line.count];
line->first = item_index;
+ if (ctx->horizontal) {
+ available_main = available_width;
+ } else {
+ available_main = ctx->flex->height;
+ }
+
+ NSLOG(flex, WARNING, "flex container %p: available main: %i",
+ ctx->flex, available_main);
+
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;
+ int main;
- width += lh__delta_outer_width(b);
+ main = ctx->horizontal ? b->max_width : b->height;
+ main += lh__delta_outer_main(b);
if (ctx->wrap == CSS_FLEX_WRAP_NOWRAP ||
lh__box_is_absolute(item->box) ||
- width == 0 ||
- width + used_width <= available_width ||
+ main == 0 ||
+ main + used_main <= available_main ||
+ available_main == AUTO ||
line->count == 0) {
line->main_size += item->main_size;
item->line = ctx->line.count;
- used_width += width;
+ used_main += main;
line->count++;
item_index++;
} else {
@@ -281,37 +356,11 @@ static size_t layout_flex__build_line(struct flex_ctx
*ctx,
if (line->count > 0) {
ctx->line.count++;
+ } else {
+ NSLOG(layout, ERROR, "Failed to fit any flex items");
}
- return line->count;
-}
-
-static bool layout_flex__collect_items_into_lines(
- struct flex_ctx *ctx,
- int available_width,
- html_content *content)
-{
- size_t fitted = 0;
- size_t pos = 0;
-
- if (ctx->item.count > 0) {
- do {
- fitted = layout_flex__build_line(ctx, pos,
- available_width, content);
- pos += fitted;
- NSLOG(flex, WARNING, "flex-container: %p: "
- "fitted: %zu (total: %zu/%zu)",
- ctx->flex, fitted,
- pos, ctx->item.count);
- } while (fitted != 0 && pos != ctx->item.count);
-
- if (fitted == 0) {
- NSLOG(layout, ERROR, "Failed to fit any flex items");
- return false;
- }
- }
-
- return true;
+ return line;
}
static inline void layout_flex__item_freeze(
@@ -320,7 +369,7 @@ static inline void layout_flex__item_freeze(
{
item->freeze = true;
line->frozen++;
- NSLOG(flex, WARNING, "flex-item box: %p: Frozen at width: %i",
+ NSLOG(flex, WARNING, "flex-item box: %p: Frozen at target_main_size:
%i",
item->box, item->target_main_size);
}
@@ -383,19 +432,19 @@ static inline int layout_flex__get_min_max_violations(
continue;
}
- if (item->max_width > 0 &&
- target_main_size > item->max_width) {
- target_main_size = item->max_width;
+ if (item->max_main > 0 &&
+ target_main_size > item->max_main) {
+ target_main_size = item->max_main;
item->max_violation = true;
- NSLOG(flex, WARNING, "Violation: max_width: %i",
- item->max_width);
+ NSLOG(flex, WARNING, "Violation: max_main: %i",
+ item->max_main);
}
- if (target_main_size < item->min_width) {
- target_main_size = item->min_width;
+ if (target_main_size < item->min_main) {
+ target_main_size = item->min_main;
item->min_violation = true;
- NSLOG(flex, WARNING, "Violation: min_width: %i",
- item->min_width);
+ NSLOG(flex, WARNING, "Violation: min_main: %i",
+ item->min_main);
}
if (target_main_size < item->box->min_width) {
@@ -489,18 +538,94 @@ static inline void layout_flex__distribute_free_space(
}
}
+static bool layout_flex__resolve_line_horizontal(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ int available_width)
+{
+ size_t item_count = line->first + line->count;
+ int x = 0;
+
+ for (size_t i = line->first; i < item_count; 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);
+
+ success = layout_flex_item(ctx, item, available_width);
+ if (!success) {
+ NSLOG(flex, WARNING, "box %p: layout failed", b);
+ return false;
+ }
+
+ height = b->height + lh__delta_outer_height(b);
+
+ b->y = ctx->cross_size +
+ b->margin[TOP] +
+ b->border[TOP].width +
+ b->padding[TOP];
+ if (line->cross_size < height) {
+ line->cross_size = height;
+ }
+
+ b->x = x + b->margin[LEFT] +
+ b->border[LEFT].width +
+ b->padding[LEFT];
+ x += b->width + lh__delta_outer_width(b);
+ }
+
+ return true;
+}
+
+static bool layout_flex__resolve_line_vertical(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ int available_width)
+{
+ size_t item_count = line->first + line->count;
+ int y = 0;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ struct box *b = item->box;
+ int width;
+
+ width = b->width + lh__delta_outer_width(b);
+
+ b->x = ctx->cross_size +
+ b->margin[LEFT] +
+ b->border[LEFT].width +
+ b->padding[LEFT];
+ if (line->cross_size < width) {
+ line->cross_size = width;
+ }
+
+ b->y = y + b->margin[TOP] +
+ b->border[TOP].width +
+ b->padding[TOP];
+ y += b->height + lh__delta_outer_height(b);
+ }
+
+ return true;
+}
+
/** 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,
+ int available_width)
{
- 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;
+ int initial_free_space = available_width;
+
+ assert(ctx->line.count > 0);
+ NSLOG(flex, WARNING, "box %p: line %zu: first: %zu, count: %zu",
+ ctx->flex, line - ctx->line.data,
+ line->first, line->count);
NSLOG(flex, WARNING, "Line main_size: %i, available_width: %i",
line->main_size, available_width);
@@ -567,55 +692,52 @@ static bool layout_flex__resolve_line(
}
}
- for (size_t i = line->first; i < line->first + line->count; i++) {
- struct flex_item_data *item = &ctx->item.data[i];
- struct box *b = item->box;
- bool success = false;
- int height;
+ if (ctx->horizontal) {
+ if (!layout_flex__resolve_line_horizontal(ctx,
+ line, available_width)) {
+ return false;
+ }
+ } else {
+ if (!layout_flex__resolve_line_vertical(ctx,
+ line, available_width)) {
+ return false;
+ }
+ }
- b->width = item->target_main_size - lh__delta_outer_width(b);
+ return true;
+}
- switch (b->type) {
- case BOX_BLOCK:
- success = layout_block_context(b, -1,
- ctx->content);
- break;
- case BOX_TABLE:
- b->float_container = b->parent;
- success = layout_table(b, available_width,
- ctx->content);
- b->float_container = NULL;
- break;
- case BOX_FLEX:
- b->float_container = b->parent;
- success = layout_flex(b, available_width,
- ctx->content);
- b->float_container = NULL;
- break;
- default:
- assert(0 && "Bad flex item back type");
- success = false;
- break;
- }
- if (!success) {
- NSLOG(flex, WARNING, "box %p: layout failed", b);
+static bool layout_flex__collect_items_into_lines(
+ struct flex_ctx *ctx,
+ int available_width,
+ html_content *content)
+{
+ size_t pos = 0;
+
+ while (pos < ctx->item.count) {
+ struct flex_line_data *line;
+
+ line = layout_flex__build_line(ctx, pos,
+ available_width, content);
+ if (line == NULL) {
return false;
}
- height = b->height + lh__delta_outer_height(b);
+ pos += line->count;
- b->y = ctx->cross_size +
- b->margin[TOP] +
- b->border[TOP].width +
- b->padding[TOP];
- if (line->cross_size < height) {
- line->cross_size = height;
+ NSLOG(flex, WARNING, "flex-container: %p: "
+ "fitted: %zu (total: %zu/%zu)",
+ ctx->flex, line->count,
+ pos, ctx->item.count);
+
+ if (!layout_flex__resolve_line(ctx, line, available_width)) {
+ return false;
}
- b->x = x + b->margin[LEFT] +
- b->border[LEFT].width +
- b->padding[LEFT];
- x += b->width + lh__delta_outer_width(b);
+ ctx->cross_size += line->cross_size;
+ if (ctx->main_size < line->main_size) {
+ ctx->main_size = line->main_size;
+ }
}
return true;
@@ -636,14 +758,13 @@ bool layout_flex(struct box *flex, int available_width,
struct flex_ctx *ctx;
bool success = false;
- NSLOG(flex, WARNING, "box %p", flex);
-
ctx = layout_flex_ctx__create(content, flex);
if (ctx == NULL) {
return false;
}
- layout_flex_ctx__populate_item_data(ctx, flex, available_width);
+ NSLOG(flex, WARNING, "box %p (%s)", flex,
+ ctx->horizontal ? "horizontal" : "vertical");
layout_find_dimensions(
ctx->unit_len_ctx, available_width, -1,
@@ -671,6 +792,8 @@ bool layout_flex(struct box *flex, int available_width,
available_width -= lh__delta_outer_width(flex);
+ layout_flex_ctx__populate_item_data(ctx, flex, available_width);
+
/* Place items onto lines. */
success = layout_flex__collect_items_into_lines(ctx,
available_width, content);
@@ -678,24 +801,10 @@ bool layout_flex(struct box *flex, int available_width,
goto cleanup;
}
- /* Layout children */
- for (size_t i = 0; i < ctx->line.count; i++) {
- NSLOG(flex, WARNING, "box %p: "
- "line %zu: first: %zu, count: %zu",
- flex, 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->cross_size += ctx->line.data[i].cross_size;
- }
-
if (flex->height == AUTO) {
- flex->height = ctx->cross_size;
+ flex->height = ctx->horizontal ?
+ ctx->cross_size :
+ ctx->main_size;
}
if (max_width >= 0 && flex->width > max_width) {
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=5b011d4434468edeb06675624dd3b00b8ab476ce
commit 5b011d4434468edeb06675624dd3b00b8ab476ce
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
wip col
diff --git a/content/handlers/html/layout_flex.c
b/content/handlers/html/layout_flex.c
index 3c86bbe..2c2c7ad 100644
--- a/content/handlers/html/layout_flex.c
+++ b/content/handlers/html/layout_flex.c
@@ -67,9 +67,8 @@ struct flex_item_data {
};
struct flex_line_data {
- int height;
-
int main_size;
+ int cross_size;
size_t first;
size_t count;
@@ -77,11 +76,12 @@ struct flex_line_data {
};
struct flex_ctx {
- int height;
html_content *content;
const struct box *flex;
const css_unit_ctx *unit_len_ctx;
+ int cross_size;
+
enum css_flex_wrap_e wrap;
struct flex_items {
@@ -604,12 +604,17 @@ static bool layout_flex__resolve_line(
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->y = ctx->cross_size +
+ b->margin[TOP] +
+ b->border[TOP].width +
+ b->padding[TOP];
+ if (line->cross_size < height) {
+ line->cross_size = height;
}
- b->x = x + b->margin[LEFT] + b->border[LEFT].width +
b->padding[LEFT];
+ b->x = x + b->margin[LEFT] +
+ b->border[LEFT].width +
+ b->padding[LEFT];
x += b->width + lh__delta_outer_width(b);
}
@@ -686,11 +691,11 @@ bool layout_flex(struct box *flex, int available_width,
goto cleanup;
}
- ctx->height += ctx->line.data[i].height;
+ ctx->cross_size += ctx->line.data[i].cross_size;
}
if (flex->height == AUTO) {
- flex->height = ctx->height;
+ flex->height = ctx->cross_size;
}
if (max_width >= 0 && flex->width > max_width) {
diff --git a/content/handlers/html/layout_internal.h
b/content/handlers/html/layout_internal.h
index 483d52e..7934ddd 100644
--- a/content/handlers/html/layout_internal.h
+++ b/content/handlers/html/layout_internal.h
@@ -166,7 +166,7 @@ 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)
+static inline bool layout_flex__main_is_horizontal(const struct box *flex)
{
const css_computed_style *style = flex->style;
@@ -203,6 +203,24 @@ static inline int lh__delta_outer_width(const struct box
*b)
b->padding[RIGHT];
}
+static inline int lh__delta_outer_main(const struct box *flex)
+{
+ if (layout_flex__main_is_horizontal(flex)) {
+ return lh__delta_outer_width(flex);
+ } else {
+ return lh__delta_outer_height(flex);
+ }
+}
+
+static inline int lh__delta_outer_cross(const struct box *flex)
+{
+ if (layout_flex__main_is_horizontal(flex) == false) {
+ return lh__delta_outer_width(flex);
+ } else {
+ return lh__delta_outer_height(flex);
+ }
+}
+
/**
* Determine width of margin, borders, and padding on one side of a box.
*
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=04e9db66f1395e66293e94b7e7ec2fc95d9d4f90
commit 04e9db66f1395e66293e94b7e7ec2fc95d9d4f90
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
WIP: Work out how flex container table cells should work
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=d0470365d7db7ad5418c899908e5232d93c6fe6f
commit d0470365d7db7ad5418c899908e5232d93c6fe6f
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
WIP: Initial implementation of display: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 cd2702e..22763e6 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -522,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;
@@ -536,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;
@@ -869,7 +869,6 @@ layout_minmax_inline_container(struct box *inline_container,
inline_container->max_width);
}
-
/**
* Calculate minimum and maximum width of a block.
*
@@ -898,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);
@@ -913,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;
@@ -924,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 ||
@@ -973,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);
@@ -1014,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;
@@ -1030,8 +1045,8 @@ static void layout_minmax_block(
}
/* fixed width takes priority */
- if (block->type != BOX_TABLE_CELL && wtype == CSS_WIDTH_SET &&
- wunit != CSS_UNIT_PCT) {
+ if (block->type != BOX_TABLE_CELL && !lh__box_is_flex_item(block) &&
+ wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT) {
min = max = FIXTOINT(css_unit_len2device_px(block->style,
&content->unit_len_ctx, width, wunit));
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
@@ -2550,12 +2565,20 @@ 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))
- return false;
+ if (b->type == BOX_TABLE || b->type == BOX_INLINE_FLEX) {
+ if (b->type == BOX_TABLE) {
+ if (!layout_table(b, width, content))
+ return false;
+ } else {
+ if (!layout_flex(b, width, content))
+ return false;
+ }
if (b->margin[LEFT] == AUTO)
b->margin[LEFT] = 0;
if (b->margin[RIGHT] == AUTO)
@@ -2564,8 +2587,9 @@ static bool layout_float(struct box *b, int width,
html_content *content)
b->margin[TOP] = 0;
if (b->margin[BOTTOM] == AUTO)
b->margin[BOTTOM] = 0;
- } else
+ } else {
return layout_block_context(b, -1, content);
+ }
return true;
}
@@ -2773,7 +2797,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;
@@ -2993,7 +3018,8 @@ layout_line(struct box *first,
b->x = x;
if ((b->type == BOX_INLINE && !b->inline_end) ||
- b->type == BOX_INLINE_BLOCK) {
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_INLINE_FLEX) {
b->x += b->margin[LEFT] + b->border[LEFT].width;
x = b->x + b->padding[LEFT] + b->width +
b->padding[RIGHT] +
@@ -3494,7 +3520,9 @@ bool layout_block_context(
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);
@@ -3563,7 +3591,9 @@ bool layout_block_context(
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
@@ -3647,7 +3677,7 @@ bool layout_block_context(
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;
@@ -3680,11 +3710,21 @@ bool layout_block_context(
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. */
@@ -3700,6 +3740,7 @@ bool layout_block_context(
/* 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)) ||
@@ -4525,7 +4566,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
@@ -4760,6 +4803,13 @@ 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) {
+ /* layout_table also expects the containing block to be
+ * stored in the float_container field */
+ box->float_container = containing_block;
+ if (!layout_flex(box, width, content))
+ return false;
+ box->float_container = NULL;
}
/* 10.6.4 */
@@ -4896,7 +4946,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) ==
diff --git a/content/handlers/html/layout_flex.c
b/content/handlers/html/layout_flex.c
new file mode 100644
index 0000000..3c86bbe
--- /dev/null
+++ b/content/handlers/html/layout_flex.c
@@ -0,0 +1,720 @@
+/*
+ * 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/log.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;
+
+ 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;
+
+ 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;
+ }
+ NSLOG(flex, WARNING, "flex-item box: %p: base_size: %i, main_size %i",
+ b, item->base_size, 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++];
+
+ b->float_container = b->parent;
+ 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);
+ b->float_container = NULL;
+
+ 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;
+
+ 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;
+
+ 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__build_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 (ctx->wrap == CSS_FLEX_WRAP_NOWRAP ||
+ 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 bool layout_flex__collect_items_into_lines(
+ struct flex_ctx *ctx,
+ int available_width,
+ html_content *content)
+{
+ size_t fitted = 0;
+ size_t pos = 0;
+
+ if (ctx->item.count > 0) {
+ do {
+ fitted = layout_flex__build_line(ctx, pos,
+ available_width, content);
+ pos += fitted;
+ NSLOG(flex, WARNING, "flex-container: %p: "
+ "fitted: %zu (total: %zu/%zu)",
+ ctx->flex, fitted,
+ pos, ctx->item.count);
+ } while (fitted != 0 && pos != ctx->item.count);
+
+ if (fitted == 0) {
+ NSLOG(layout, ERROR, "Failed to fit any flex items");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static inline void layout_flex__item_freeze(
+ struct flex_line_data *line,
+ struct flex_item_data *item)
+{
+ item->freeze = true;
+ line->frozen++;
+ NSLOG(flex, WARNING, "flex-item box: %p: Frozen at width: %i",
+ item->box, item->target_main_size);
+}
+
+static inline int layout_flex__remaining_free_space(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ css_fixed *unfrozen_factor_sum,
+ int initial_free_space,
+ int available_width,
+ bool grow)
+{
+ int remaining_free_space = available_width;
+ size_t item_count = line->first + line->count;
+
+ *unfrozen_factor_sum = 0;
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ NSLOG(flex, WARNING, "Remaining free space: %i", remaining_free_space);
+
+ return remaining_free_space;
+}
+
+static inline int layout_flex__get_min_max_violations(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line)
+{
+
+ int total_violation = 0;
+ size_t item_count = line->first + line->count;
+
+ 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;
+
+ NSLOG(flex, WARNING, "item %p: target_main_size: %i",
+ item->box, 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;
+ NSLOG(flex, WARNING, "Violation: max_width: %i",
+ item->max_width);
+ }
+
+ if (target_main_size < item->min_width) {
+ target_main_size = item->min_width;
+ item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: min_width: %i",
+ item->min_width);
+ }
+
+ if (target_main_size < item->box->min_width) {
+ target_main_size = item->box->min_width;
+ item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: box min_width: %i",
+ item->box->min_width);
+ }
+
+ if (target_main_size < 0) {
+ target_main_size = 0;
+ item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: less than 0");
+ }
+
+ total_violation += target_main_size - item->target_main_size;
+ item->target_main_size = target_main_size;
+ }
+
+ NSLOG(flex, WARNING, "Total violation: %i", total_violation);
+
+ return total_violation;
+}
+
+static inline void layout_flex__distribute_free_space(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ css_fixed unfrozen_factor_sum,
+ int remaining_free_space,
+ bool grow)
+{
+ size_t item_count = line->first + line->count;
+
+ 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;
+ } else if (scaled_shrink_factor_sum == 0) {
+ item->target_main_size = item->main_size;
+ layout_flex__item_freeze(line, item);
+ 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));
+ }
+ }
+}
+
+/** 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;
+
+ NSLOG(flex, WARNING, "Line main_size: %i, available_width: %i",
+ 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) {
+ item->target_main_size = item->main_size;
+ 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) {
+ css_fixed unfrozen_factor_sum;
+ int remaining_free_space;
+ int total_violation;
+
+ NSLOG(flex, WARNING, "flex-container: %p: Resolver pass",
+ ctx->flex);
+
+ /* b */
+ remaining_free_space = layout_flex__remaining_free_space(ctx,
+ line, &unfrozen_factor_sum, initial_free_space,
+ available_width, grow);
+
+ /* c */
+ if (remaining_free_space != 0) {
+ layout_flex__distribute_free_space(ctx,
+ line, unfrozen_factor_sum,
+ remaining_free_space, grow);
+ }
+
+ /* d */
+ total_violation = layout_flex__get_min_max_violations(
+ ctx, line);
+
+ /* 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++) {
+ 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:
+ success = layout_block_context(b, -1,
+ ctx->content);
+ break;
+ case BOX_TABLE:
+ b->float_container = b->parent;
+ success = layout_table(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ case BOX_FLEX:
+ b->float_container = b->parent;
+ success = layout_flex(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ default:
+ assert(0 && "Bad flex item back type");
+ success = false;
+ break;
+ }
+ if (!success) {
+ NSLOG(flex, WARNING, "box %p: layout failed", 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;
+
+ NSLOG(flex, WARNING, "box %p", 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 -= lh__delta_outer_width(flex);
+
+ /* Place items onto lines. */
+ success = layout_flex__collect_items_into_lines(ctx,
+ available_width, content);
+ if (!success) {
+ goto cleanup;
+ }
+
+ /* Layout children */
+ for (size_t i = 0; i < ctx->line.count; i++) {
+ NSLOG(flex, WARNING, "box %p: "
+ "line %zu: first: %zu, count: %zu",
+ flex, 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);
+
+ NSLOG(flex, WARNING, "box %p: %s", flex,
+ success ? "success" : "failure");
+ return success;
+}
diff --git a/content/handlers/html/layout_internal.h
b/content/handlers/html/layout_internal.h
index 0c171ef..483d52e 100644
--- a/content/handlers/html/layout_internal.h
+++ b/content/handlers/html/layout_internal.h
@@ -106,11 +106,25 @@ static inline bool lh__box_is_float_box(const struct box
*b)
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 takes part in inline flow. */
+static inline bool lh__box_is_flex_item(const struct box *b)
+{
+ return (b->parent != NULL) && lh__box_is_flex_container(b->parent);
+}
+
/** Layout helper: Check whether box is inline level. (Includes BR.) */
static inline bool lh__box_is_inline_level(const struct box *b)
{
@@ -147,6 +161,48 @@ static inline bool lh__have_border(
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.
*
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=5b6b7ab896f9628fa3e80dfb1214c630cd31b414
commit 5b6b7ab896f9628fa3e80dfb1214c630cd31b414
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
HACK: layout debug
diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index 9fe93a7..cd2702e 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -5250,6 +5250,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)); */
@@ -5385,6 +5394,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;
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=8fb6610d7116713f97695a0a07db927d84ef1008
commit 8fb6610d7116713f97695a0a07db927d84ef1008
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
log: Add flex logging catagory
diff --git a/utils/log.c b/utils/log.c
index 68b188e..8cc42a3 100644
--- a/utils/log.c
+++ b/utils/log.c
@@ -99,6 +99,7 @@ NSLOG_DEFINE_CATEGORY(plot, "Rendering system");
NSLOG_DEFINE_CATEGORY(schedule, "Scheduler");
NSLOG_DEFINE_CATEGORY(fbtk, "Framebuffer toolkit");
NSLOG_DEFINE_CATEGORY(layout, "Layout");
+NSLOG_DEFINE_CATEGORY(flex, "Flex");
NSLOG_DEFINE_CATEGORY(dukky, "Duktape JavaScript Binding");
NSLOG_DEFINE_CATEGORY(jserrors, "JavaScript error messages");
diff --git a/utils/log.h b/utils/log.h
index 02a886c..b7aa833 100644
--- a/utils/log.h
+++ b/utils/log.h
@@ -84,6 +84,7 @@ NSLOG_DECLARE_CATEGORY(plot);
NSLOG_DECLARE_CATEGORY(schedule);
NSLOG_DECLARE_CATEGORY(fbtk);
NSLOG_DECLARE_CATEGORY(layout);
+NSLOG_DECLARE_CATEGORY(flex);
NSLOG_DECLARE_CATEGORY(dukky);
NSLOG_DECLARE_CATEGORY(jserrors);
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=6e34e01118d38cdaa12faef8efc0da1a9107a579
commit 6e34e01118d38cdaa12faef8efc0da1a9107a579
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
html: layout: Improve block container assertions
diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index 99e9bcf..9fe93a7 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -4433,9 +4433,9 @@ layout_compute_offsets(const css_unit_ctx *unit_len_ctx,
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
- assert(containing_block->width != UNKNOWN_WIDTH &&
- containing_block->width != AUTO &&
- containing_block->height != AUTO);
+ assert(containing_block->width != UNKNOWN_WIDTH);
+ assert(containing_block->width != AUTO);
+ assert(containing_block->height != AUTO);
/* left */
type = css_computed_left(box->style, &value, &unit);
-----------------------------------------------------------------------
Summary of changes:
content/handlers/html/layout.c | 25 +-
content/handlers/html/layout_flex.c | 403 ++++++++++++++++++++-----------
content/handlers/html/layout_internal.h | 26 +-
utils/log.c | 1 +
utils/log.h | 1 +
5 files changed, 311 insertions(+), 145 deletions(-)
diff --git a/content/handlers/html/layout.c b/content/handlers/html/layout.c
index 6aaf08d..22763e6 100644
--- a/content/handlers/html/layout.c
+++ b/content/handlers/html/layout.c
@@ -1045,8 +1045,8 @@ static void layout_minmax_block(
}
/* fixed width takes priority */
- if (block->type != BOX_TABLE_CELL && wtype == CSS_WIDTH_SET &&
- wunit != CSS_UNIT_PCT) {
+ if (block->type != BOX_TABLE_CELL && !lh__box_is_flex_item(block) &&
+ wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT) {
min = max = FIXTOINT(css_unit_len2device_px(block->style,
&content->unit_len_ctx, width, wunit));
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
@@ -2571,9 +2571,14 @@ static bool layout_float(struct box *b, int width,
html_content *content)
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))
- return false;
+ if (b->type == BOX_TABLE || b->type == BOX_INLINE_FLEX) {
+ if (b->type == BOX_TABLE) {
+ if (!layout_table(b, width, content))
+ return false;
+ } else {
+ if (!layout_flex(b, width, content))
+ return false;
+ }
if (b->margin[LEFT] == AUTO)
b->margin[LEFT] = 0;
if (b->margin[RIGHT] == AUTO)
@@ -2582,8 +2587,9 @@ static bool layout_float(struct box *b, int width,
html_content *content)
b->margin[TOP] = 0;
if (b->margin[BOTTOM] == AUTO)
b->margin[BOTTOM] = 0;
- } else
+ } else {
return layout_block_context(b, -1, content);
+ }
return true;
}
@@ -3012,7 +3018,8 @@ layout_line(struct box *first,
b->x = x;
if ((b->type == BOX_INLINE && !b->inline_end) ||
- b->type == BOX_INLINE_BLOCK) {
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_INLINE_FLEX) {
b->x += b->margin[LEFT] + b->border[LEFT].width;
x = b->x + b->padding[LEFT] + b->width +
b->padding[RIGHT] +
@@ -4797,8 +4804,12 @@ layout_absolute(struct box *box,
layout_solve_width(box, box->parent->width, box->width, 0, 0,
-1, -1);
} else if (box->type == BOX_FLEX || box->type == BOX_INLINE_FLEX) {
+ /* layout_table also expects the containing block to be
+ * stored in the float_container field */
+ box->float_container = containing_block;
if (!layout_flex(box, width, content))
return false;
+ box->float_container = NULL;
}
/* 10.6.4 */
diff --git a/content/handlers/html/layout_flex.c
b/content/handlers/html/layout_flex.c
index 79b1bfc..8a53b98 100644
--- a/content/handlers/html/layout_flex.c
+++ b/content/handlers/html/layout_flex.c
@@ -51,10 +51,10 @@ struct flex_item_data {
css_fixed shrink;
css_fixed grow;
- int min_width;
- int max_width;
- int min_height;
- int max_height;
+ int min_main;
+ int max_main;
+ int min_cross;
+ int max_cross;
int target_main_size;
int base_size;
@@ -67,9 +67,8 @@ struct flex_item_data {
};
struct flex_line_data {
- int height;
-
int main_size;
+ int cross_size;
size_t first;
size_t count;
@@ -77,11 +76,14 @@ struct flex_line_data {
};
struct flex_ctx {
- int height;
html_content *content;
const struct box *flex;
const css_unit_ctx *unit_len_ctx;
+ int main_size;
+ int cross_size;
+
+ bool horizontal;
enum css_flex_wrap_e wrap;
struct flex_items {
@@ -134,18 +136,54 @@ static struct flex_ctx *layout_flex_ctx__create(
ctx->flex = flex;
ctx->content = content;
ctx->unit_len_ctx = &content->unit_len_ctx;
+
ctx->wrap = css_computed_flex_wrap(flex->style);
+ ctx->horizontal = layout_flex__main_is_horizontal(flex);
return ctx;
}
-static inline void layout_flex__base_and_main_sizes(
+static bool layout_flex_item(
+ const struct flex_ctx *ctx,
+ const struct flex_item_data *item,
+ int available_width)
+{
+ bool success;
+ struct box *b = item->box;
+
+ switch (b->type) {
+ case BOX_BLOCK:
+ success = layout_block_context(b, -1,
+ ctx->content);
+ break;
+ case BOX_TABLE:
+ b->float_container = b->parent;
+ success = layout_table(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ case BOX_FLEX:
+ b->float_container = b->parent;
+ success = layout_flex(b, available_width,
+ ctx->content);
+ b->float_container = NULL;
+ break;
+ default:
+ assert(0 && "Bad flex item back type");
+ success = false;
+ break;
+ }
+
+ return success;
+}
+
+static inline bool 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);
+ int delta_outer_main = lh__delta_outer_main(b);
if (item->basis == CSS_FLEX_BASIS_SET) {
if (item->basis_unit == CSS_UNIT_PCT) {
@@ -160,39 +198,59 @@ static inline void layout_flex__base_and_main_sizes(
}
} else if (item->basis == CSS_FLEX_BASIS_AUTO) {
- item->base_size = b->width;
+ item->base_size = ctx->horizontal ? b->width : b->height;
} else {
item->base_size = AUTO;
}
+ if (ctx->horizontal == false) {
+ if (b->width == AUTO) {
+ b->width = min(available_width, b->max_width);
+ b->width -= lh__delta_outer_cross(b);
+ }
+
+ if (!layout_flex_item(ctx, item, available_width)) {
+ NSLOG(flex, WARNING, "box %p: layout failed", b);
+ return false;
+ }
+ }
+
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;
+ if (ctx->horizontal == false) {
+ item->base_size = b->height;
+ } else {
+ item->base_size = b->max_width;
+ }
}
- item->base_size += delta_outer_width;
+ item->base_size = min(item->base_size + delta_outer_main,
+ available_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);
+ if (ctx->horizontal) {
+ item->base_size = max(item->base_size,
+ b->min_width + delta_outer_main);
+ }
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->max_main > 0 &&
+ item->main_size > item->max_main + delta_outer_main) {
+ item->main_size = item->max_main + delta_outer_main;
}
- if (item->main_size < item->min_width + delta_outer_width) {
- item->main_size = item->min_width + delta_outer_width;
+ if (item->main_size < item->min_main + delta_outer_main) {
+ item->main_size = item->min_main + delta_outer_main;
}
- fprintf(stderr, "main_size: %i\n", item->main_size);
+
+ NSLOG(flex, WARNING, "flex-item box: %p: base_size: %i, main_size %i",
+ b, item->base_size, item->main_size);
+
+ return true;
}
static void layout_flex_ctx__populate_item_data(
@@ -201,15 +259,20 @@ static void layout_flex_ctx__populate_item_data(
int available_width)
{
size_t i = 0;
+ bool horizontal = ctx->horizontal;
for (struct box *b = flex->children; b != NULL; b = b->next) {
struct flex_item_data *item = &ctx->item.data[i++];
+ b->float_container = b->parent;
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,
+ horizontal ? &item->max_main : &item->max_cross,
+ horizontal ? &item->min_main : &item->min_cross,
+ horizontal ? &item->max_cross : &item->max_main,
+ horizontal ? &item->min_cross : &item->min_main,
b->margin, b->padding, b->border);
+ b->float_container = NULL;
item->box = b;
item->basis = css_computed_flex_basis(b->style,
@@ -227,9 +290,6 @@ 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;
}
@@ -240,9 +300,6 @@ static bool layout_flex_ctx__ensure_line(struct flex_ctx
*ctx)
}
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;
@@ -250,11 +307,12 @@ static bool layout_flex_ctx__ensure_line(struct flex_ctx
*ctx)
return true;
}
-static size_t layout_flex__build_line(struct flex_ctx *ctx,
+static struct flex_line_data *layout_flex__build_line(struct flex_ctx *ctx,
size_t item_index, int available_width, html_content *content)
{
struct flex_line_data *line;
- int used_width = 0;
+ int available_main;
+ int used_main = 0;
if (!layout_flex_ctx__ensure_line(ctx)) {
return 0;
@@ -263,21 +321,32 @@ static size_t layout_flex__build_line(struct flex_ctx
*ctx,
line = &ctx->line.data[ctx->line.count];
line->first = item_index;
+ if (ctx->horizontal) {
+ available_main = available_width;
+ } else {
+ available_main = ctx->flex->height;
+ }
+
+ NSLOG(flex, WARNING, "flex container %p: available main: %i",
+ ctx->flex, available_main);
+
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;
+ int main;
- width += lh__delta_outer_width(b);
+ main = ctx->horizontal ? b->max_width : b->height;
+ main += lh__delta_outer_main(b);
if (ctx->wrap == CSS_FLEX_WRAP_NOWRAP ||
lh__box_is_absolute(item->box) ||
- width == 0 ||
- width + used_width <= available_width ||
+ main == 0 ||
+ main + used_main <= available_main ||
+ available_main == AUTO ||
line->count == 0) {
line->main_size += item->main_size;
item->line = ctx->line.count;
- used_width += width;
+ used_main += main;
line->count++;
item_index++;
} else {
@@ -287,35 +356,11 @@ static size_t layout_flex__build_line(struct flex_ctx
*ctx,
if (line->count > 0) {
ctx->line.count++;
+ } else {
+ NSLOG(layout, ERROR, "Failed to fit any flex items");
}
- return line->count;
-}
-
-static bool layout_flex__collect_items_into_lines(
- struct flex_ctx *ctx,
- int available_width,
- html_content *content)
-{
- size_t fitted = 0;
- size_t pos = 0;
-
- if (ctx->item.count > 0) {
- do {
- fitted = layout_flex__build_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) {
- NSLOG(layout, ERROR, "Failed to fit any flex items");
- return false;
- }
- }
-
- return true;
+ return line;
}
static inline void layout_flex__item_freeze(
@@ -324,7 +369,7 @@ static inline void layout_flex__item_freeze(
{
item->freeze = true;
line->frozen++;
- fprintf(stderr, " frozen: block: %p: width: %i\n",
+ NSLOG(flex, WARNING, "flex-item box: %p: Frozen at target_main_size:
%i",
item->box, item->target_main_size);
}
@@ -353,7 +398,6 @@ static inline int layout_flex__remaining_free_space(
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),
@@ -362,9 +406,10 @@ static inline int layout_flex__remaining_free_space(
if (free_space < remaining_free_space) {
remaining_free_space = free_space;
}
- fprintf(stderr, " Remaining free space: %i\n",
remaining_free_space);
}
+ NSLOG(flex, WARNING, "Remaining free space: %i", remaining_free_space);
+
return remaining_free_space;
}
@@ -380,35 +425,47 @@ static inline int layout_flex__get_min_max_violations(
struct flex_item_data *item = &ctx->item.data[i];
int target_main_size = item->target_main_size;
+ NSLOG(flex, WARNING, "item %p: target_main_size: %i",
+ item->box, target_main_size);
+
if (item->freeze) {
continue;
}
- if (item->max_width > 0 &&
- target_main_size > item->max_width) {
- target_main_size = item->max_width;
+ if (item->max_main > 0 &&
+ target_main_size > item->max_main) {
+ target_main_size = item->max_main;
item->max_violation = true;
+ NSLOG(flex, WARNING, "Violation: max_main: %i",
+ item->max_main);
}
- if (target_main_size < item->min_width) {
- target_main_size = item->min_width;
+ if (target_main_size < item->min_main) {
+ target_main_size = item->min_main;
item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: min_main: %i",
+ item->min_main);
}
if (target_main_size < item->box->min_width) {
target_main_size = item->box->min_width;
item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: box min_width: %i",
+ item->box->min_width);
}
if (target_main_size < 0) {
target_main_size = 0;
item->min_violation = true;
+ NSLOG(flex, WARNING, "Violation: less than 0");
}
total_violation += target_main_size - item->target_main_size;
item->target_main_size = target_main_size;
}
+ NSLOG(flex, WARNING, "Total violation: %i", total_violation);
+
return total_violation;
}
@@ -461,6 +518,10 @@ static inline void layout_flex__distribute_free_space(
if (item->freeze) {
continue;
+ } else if (scaled_shrink_factor_sum == 0) {
+ item->target_main_size = item->main_size;
+ layout_flex__item_freeze(line, item);
+ continue;
}
scaled_shrink_factor = FMUL(
@@ -477,19 +538,95 @@ static inline void layout_flex__distribute_free_space(
}
}
+static bool layout_flex__resolve_line_horizontal(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ int available_width)
+{
+ size_t item_count = line->first + line->count;
+ int x = 0;
+
+ for (size_t i = line->first; i < item_count; 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);
+
+ success = layout_flex_item(ctx, item, available_width);
+ if (!success) {
+ NSLOG(flex, WARNING, "box %p: layout failed", b);
+ return false;
+ }
+
+ height = b->height + lh__delta_outer_height(b);
+
+ b->y = ctx->cross_size +
+ b->margin[TOP] +
+ b->border[TOP].width +
+ b->padding[TOP];
+ if (line->cross_size < height) {
+ line->cross_size = height;
+ }
+
+ b->x = x + b->margin[LEFT] +
+ b->border[LEFT].width +
+ b->padding[LEFT];
+ x += b->width + lh__delta_outer_width(b);
+ }
+
+ return true;
+}
+
+static bool layout_flex__resolve_line_vertical(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ int available_width)
+{
+ size_t item_count = line->first + line->count;
+ int y = 0;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ struct box *b = item->box;
+ int width;
+
+ width = b->width + lh__delta_outer_width(b);
+
+ b->x = ctx->cross_size +
+ b->margin[LEFT] +
+ b->border[LEFT].width +
+ b->padding[LEFT];
+ if (line->cross_size < width) {
+ line->cross_size = width;
+ }
+
+ b->y = y + b->margin[TOP] +
+ b->border[TOP].width +
+ b->padding[TOP];
+ y += b->height + lh__delta_outer_height(b);
+ }
+
+ return true;
+}
+
/** 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,
+ int available_width)
{
- 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;
+ int initial_free_space = available_width;
- fprintf(stderr, " Line main_size: %i, available_width: %i\n",
+ assert(ctx->line.count > 0);
+
+ NSLOG(flex, WARNING, "box %p: line %zu: first: %zu, count: %zu",
+ ctx->flex, line - ctx->line.data,
+ line->first, line->count);
+ NSLOG(flex, WARNING, "Line main_size: %i, available_width: %i",
line->main_size, available_width);
for (size_t i = line->first; i < item_count; i++) {
@@ -499,11 +636,7 @@ static bool layout_flex__resolve_line(
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 {
@@ -528,7 +661,8 @@ static bool layout_flex__resolve_line(
int remaining_free_space;
int total_violation;
- fprintf(stderr, " Flex resolver pass\n");
+ NSLOG(flex, WARNING, "flex-container: %p: Resolver pass",
+ ctx->flex);
/* b */
remaining_free_space = layout_flex__remaining_free_space(ctx,
@@ -558,48 +692,52 @@ static bool layout_flex__resolve_line(
}
}
- 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;
+ if (ctx->horizontal) {
+ if (!layout_flex__resolve_line_horizontal(ctx,
+ line, available_width)) {
+ return false;
+ }
+ } else {
+ if (!layout_flex__resolve_line_vertical(ctx,
+ line, available_width)) {
+ return false;
+ }
+ }
- b->width = item->target_main_size - lh__delta_outer_width(b);
+ return true;
+}
- 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);
+static bool layout_flex__collect_items_into_lines(
+ struct flex_ctx *ctx,
+ int available_width,
+ html_content *content)
+{
+ size_t pos = 0;
+
+ while (pos < ctx->item.count) {
+ struct flex_line_data *line;
+
+ line = layout_flex__build_line(ctx, pos,
+ available_width, content);
+ if (line == NULL) {
return false;
}
- height = b->height + lh__delta_outer_height(b);
+ pos += line->count;
+
+ NSLOG(flex, WARNING, "flex-container: %p: "
+ "fitted: %zu (total: %zu/%zu)",
+ ctx->flex, line->count,
+ pos, ctx->item.count);
- b->y = ctx->height + b->margin[TOP] + b->border[TOP].width +
b->padding[TOP];
- if (line->height < height) {
- line->height = height;
+ if (!layout_flex__resolve_line(ctx, line, available_width)) {
+ return false;
}
- b->x = x + b->margin[LEFT] + b->border[LEFT].width +
b->padding[LEFT];
- x += b->width + lh__delta_outer_width(b);
+ ctx->cross_size += line->cross_size;
+ if (ctx->main_size < line->main_size) {
+ ctx->main_size = line->main_size;
+ }
}
return true;
@@ -620,14 +758,13 @@ bool layout_flex(struct box *flex, int available_width,
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);
+ NSLOG(flex, WARNING, "box %p (%s)", flex,
+ ctx->horizontal ? "horizontal" : "vertical");
layout_find_dimensions(
ctx->unit_len_ctx, available_width, -1,
@@ -655,6 +792,8 @@ bool layout_flex(struct box *flex, int available_width,
available_width -= lh__delta_outer_width(flex);
+ layout_flex_ctx__populate_item_data(ctx, flex, available_width);
+
/* Place items onto lines. */
success = layout_flex__collect_items_into_lines(ctx,
available_width, content);
@@ -662,22 +801,10 @@ bool layout_flex(struct box *flex, int available_width,
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;
+ flex->height = ctx->horizontal ?
+ ctx->cross_size :
+ ctx->main_size;
}
if (max_width >= 0 && flex->width > max_width) {
@@ -700,6 +827,8 @@ bool layout_flex(struct box *flex, int available_width,
cleanup:
layout_flex_ctx__destroy(ctx);
- fprintf(stderr, "Flex layout: %s\n\n", success ? "success" : "failure");
+
+ NSLOG(flex, WARNING, "box %p: %s", flex,
+ success ? "success" : "failure");
return success;
}
diff --git a/content/handlers/html/layout_internal.h
b/content/handlers/html/layout_internal.h
index 3233fce..7934ddd 100644
--- a/content/handlers/html/layout_internal.h
+++ b/content/handlers/html/layout_internal.h
@@ -119,6 +119,12 @@ static inline bool lh__box_is_flex_container(const struct
box *b)
b->type == BOX_INLINE_FLEX;
}
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_flex_item(const struct box *b)
+{
+ return (b->parent != NULL) && lh__box_is_flex_container(b->parent);
+}
+
/** Layout helper: Check whether box is inline level. (Includes BR.) */
static inline bool lh__box_is_inline_level(const struct box *b)
{
@@ -160,7 +166,7 @@ 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)
+static inline bool layout_flex__main_is_horizontal(const struct box *flex)
{
const css_computed_style *style = flex->style;
@@ -197,6 +203,24 @@ static inline int lh__delta_outer_width(const struct box
*b)
b->padding[RIGHT];
}
+static inline int lh__delta_outer_main(const struct box *flex)
+{
+ if (layout_flex__main_is_horizontal(flex)) {
+ return lh__delta_outer_width(flex);
+ } else {
+ return lh__delta_outer_height(flex);
+ }
+}
+
+static inline int lh__delta_outer_cross(const struct box *flex)
+{
+ if (layout_flex__main_is_horizontal(flex) == false) {
+ return lh__delta_outer_width(flex);
+ } else {
+ return lh__delta_outer_height(flex);
+ }
+}
+
/**
* Determine width of margin, borders, and padding on one side of a box.
*
diff --git a/utils/log.c b/utils/log.c
index 68b188e..8cc42a3 100644
--- a/utils/log.c
+++ b/utils/log.c
@@ -99,6 +99,7 @@ NSLOG_DEFINE_CATEGORY(plot, "Rendering system");
NSLOG_DEFINE_CATEGORY(schedule, "Scheduler");
NSLOG_DEFINE_CATEGORY(fbtk, "Framebuffer toolkit");
NSLOG_DEFINE_CATEGORY(layout, "Layout");
+NSLOG_DEFINE_CATEGORY(flex, "Flex");
NSLOG_DEFINE_CATEGORY(dukky, "Duktape JavaScript Binding");
NSLOG_DEFINE_CATEGORY(jserrors, "JavaScript error messages");
diff --git a/utils/log.h b/utils/log.h
index 02a886c..b7aa833 100644
--- a/utils/log.h
+++ b/utils/log.h
@@ -84,6 +84,7 @@ NSLOG_DECLARE_CATEGORY(plot);
NSLOG_DECLARE_CATEGORY(schedule);
NSLOG_DECLARE_CATEGORY(fbtk);
NSLOG_DECLARE_CATEGORY(layout);
+NSLOG_DECLARE_CATEGORY(flex);
NSLOG_DECLARE_CATEGORY(dukky);
NSLOG_DECLARE_CATEGORY(jserrors);
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]