diff options
author | bptato <nincsnevem662@gmail.com> | 2025-01-02 18:24:40 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-01-02 18:24:51 +0100 |
commit | 57d6a0d18d080b82b353a5451b5724807a5658b1 (patch) | |
tree | ee777cf2ffe31a9edc2b76399c4542a2217c6a07 | |
parent | 9ef9d6a0615aa4166f905fc7b6527b8b380739b0 (diff) | |
download | chawan-57d6a0d18d080b82b353a5451b5724807a5658b1.tar.gz |
layout: implement layoutFlexItem as layoutRootBlock
This way, it benefits from sub-layout caching. Which is great because our flex layout likes to unnecessarily redo item layout... Also, we now account for the bottom margin in flex items.
-rw-r--r-- | src/css/layout.nim | 31 | ||||
-rw-r--r-- | test/layout/flex-item-margin-collapsing.color.expected | 17 | ||||
-rw-r--r-- | test/layout/flex-item-margin-collapsing.html | 28 |
3 files changed, 60 insertions, 16 deletions
diff --git a/src/css/layout.nim b/src/css/layout.nim index ce7127b5..d2538af8 100644 --- a/src/css/layout.nim +++ b/src/css/layout.nim @@ -1202,7 +1202,7 @@ proc layoutTableWrapper(bctx: BlockContext; box: BlockBox; sizes: ResolvedSizes) proc layoutFlex(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes) proc layoutInline(ictx: var InlineContext; box: InlineBox) proc layoutRootBlock(lctx: LayoutContext; box: BlockBox; offset: Offset; - sizes: ResolvedSizes) + sizes: ResolvedSizes; includeMargin = false) # Note: padding must still be applied after this. proc applySize(box: BlockBox; sizes: ResolvedSizes; @@ -2272,18 +2272,6 @@ proc layout(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes; else: assert false -proc layoutFlexItem(lctx: LayoutContext; box: BlockBox; sizes: ResolvedSizes) = - var bctx = BlockContext(lctx: lctx) - # note: we do not append margins here, since those belong to the flex item, - # not its inner BFC. - box.state = BoxLayoutState(offset: offset(x = sizes.margin.left, y = 0)) - bctx.layout(box, sizes, canClear = false) - assert bctx.unpositionedFloats.len == 0 - # If the highest float edge is higher than the box itself, set that as - # the box height. - box.state.size.h = max(box.state.size.h, bctx.maxFloatHeight) - box.state.intr.h = max(box.state.intr.h, bctx.maxFloatHeight) - type FlexWeightType = enum fwtGrow, fwtShrink @@ -2311,6 +2299,9 @@ type totalWeight: array[FlexWeightType, float64] pending: seq[FlexPendingItem] +proc layoutFlexItem(lctx: LayoutContext; box: BlockBox; sizes: ResolvedSizes) = + lctx.layoutRootBlock(box, offset(x = 0, y = 0), sizes, includeMargin = true) + const FlexRow = {FlexDirectionRow, FlexDirectionRowReverse} proc updateMaxSizes(mctx: var FlexMainContext; child: BlockBox; @@ -2404,6 +2395,10 @@ proc flushMain(fctx: var FlexContext; mctx: var FlexMainContext; # instead. (if the box's available height is definite, then this will # change nothing, so we skip it as an optimization.) it.sizes.space[odim] = stretch(h - it.sizes.margin[odim].sum()) + if odim == dtVertical: + # Do not include the bottom margin; space only applies to the + # actual height. + it.sizes.space[odim].u -= it.child.state.marginBottom lctx.layoutFlexItem(it.child, it.sizes) it.child.state.offset[dim] += offset[dim] # margins are added here, since they belong to the flex item. @@ -2504,7 +2499,7 @@ proc layoutFlex(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes) = # Returns the bottom margin for the box, collapsed with the appropriate # margins from its descendants. proc layoutRootBlock(lctx: LayoutContext; box: BlockBox; offset: Offset; - sizes: ResolvedSizes) = + sizes: ResolvedSizes; includeMargin = false) = if box.sizes == sizes: box.state.offset = offset return @@ -2516,10 +2511,14 @@ proc layoutRootBlock(lctx: LayoutContext; box: BlockBox; offset: Offset; bctx.layout(box, sizes, canClear = false) assert bctx.unpositionedFloats.len == 0 let marginBottom = bctx.marginTodo.sum() + if includeMargin: + box.state.size.h += marginBottom + else: + bctx.maxFloatHeight -= marginBottom # If the highest float edge is higher than the box itself, set that as # the box height. - box.state.size.h = max(box.state.size.h, bctx.maxFloatHeight - marginBottom) - box.state.intr.h = max(box.state.intr.h, bctx.maxFloatHeight - marginBottom) + box.state.size.h = max(box.state.size.h, bctx.maxFloatHeight) + box.state.intr.h = max(box.state.intr.h, bctx.maxFloatHeight) box.state.marginBottom = marginBottom proc initBlockPositionStates(state: var BlockState; bctx: var BlockContext; diff --git a/test/layout/flex-item-margin-collapsing.color.expected b/test/layout/flex-item-margin-collapsing.color.expected new file mode 100644 index 00000000..e38eebc4 --- /dev/null +++ b/test/layout/flex-item-margin-collapsing.color.expected @@ -0,0 +1,17 @@ +[48;2;0;128;0mtest[48;2;255;0;0m [49m +[48;2;0;0;255m [48;2;255;0;0m [49m +[48;2;255;0;0m [49m +[48;2;255;0;0m [49m +[48;2;0;128;0mtest2[49m +[48;2;0;0;255m [49m +[48;2;0;0;255m [49m +[48;2;255;0;0m [49m +[48;2;0;128;0mtest3[49m +[48;2;0;0;255m [49m +[48;2;255;0;0m [49m +[48;2;255;0;0m [49m +[48;2;0;128;0mtest3[49m +[48;2;0;0;255m [49m +[48;2;0;0;255m [49m +[48;2;255;0;0m [49m + diff --git a/test/layout/flex-item-margin-collapsing.html b/test/layout/flex-item-margin-collapsing.html new file mode 100644 index 00000000..56c7260d --- /dev/null +++ b/test/layout/flex-item-margin-collapsing.html @@ -0,0 +1,28 @@ +<div style="display: flex; background: red; width: 5ch"> +<div style="margin-bottom: 2em; background: blue"> +<div style="margin-bottom: 1em; background: green"> +test +</div> +</div> +</div> +<div style="display: flex; background: red; width: 5ch"> +<div style="margin-bottom: 1em; background: blue"> +<div style="margin-bottom: 2em; background: green"> +test2 +</div> +</div> +</div> +<div style="display: flex; flex-direction: column; background: red; width: 5ch"> +<div style="margin-bottom: 2em; background: blue"> +<div style="margin-bottom: 1em; background: green"> +test3 +</div> +</div> +</div> +<div style="display: flex; flex-direction: column; background: red; width: 5ch"> +<div style="margin-bottom: 1em; background: blue"> +<div style="margin-bottom: 2em; background: green"> +test3 +</div> +</div> +</div> |