diff options
author | bptato <nincsnevem662@gmail.com> | 2025-01-01 16:03:03 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-01-01 16:03:03 +0100 |
commit | 585ca24c924cadf351d9a95143732f3051cb157e (patch) | |
tree | 5969c9d8159b393108e1dd457115a68099fd1e48 /src/css/layout.nim | |
parent | 2914d4553d2fe06028e9bdafaa8a126be3135756 (diff) | |
download | chawan-585ca24c924cadf351d9a95143732f3051cb157e.tar.gz |
layout: prevent double-clear for flow roots
I don't like the extra flag, but I don't see a better way.
Diffstat (limited to 'src/css/layout.nim')
-rw-r--r-- | src/css/layout.nim | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/src/css/layout.nim b/src/css/layout.nim index 3c41bbeb..531f8a19 100644 --- a/src/css/layout.nim +++ b/src/css/layout.nim @@ -1506,11 +1506,16 @@ proc layoutInline(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes) = bctx.lctx.popPositioned(box.state.overflow, box.state.size) box.state.overflow.finalize(box.state.size) -proc layoutFlow(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes) = +# canClear signals if the box should clear in its inner (flow) layout. +# In general, this is only true for block boxes that do not establish +# a BFC; other boxes (e.g. flex) either have nothing to clear, or clear +# in their parent BFC (e.g. flow-root). +proc layoutFlow(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes; + canClear: bool) = if box.canFlushMargins(sizes): bctx.flushMargins(box) bctx.positionFloats() - if box.computed{"clear"} != ClearNone: + if canClear and box.computed{"clear"} != ClearNone: box.state.offset.y.clearFloats(bctx, bctx.bfcOffset.y, box.computed{"clear"}) if box.inline != nil: @@ -1528,7 +1533,10 @@ proc layoutListItem(bctx: var BlockContext; box: BlockBox; let content = box.children[1] marker.state = BoxLayoutState() content.state = BoxLayoutState(offset: box.state.offset) - bctx.layoutFlow(content, sizes) + #TODO should markers establish a new BFC? + # Actually, I'm not sure if it even matters, since they are out + # of flow. Either way, they certainly shouldn't clear. + bctx.layoutFlow(content, sizes, canClear = false) #TODO we should put markers right before the first atom of the parent # list item or something... var bctx = BlockContext(lctx: bctx.lctx) @@ -1536,13 +1544,13 @@ proc layoutListItem(bctx: var BlockContext; box: BlockBox; space: availableSpace(w = fitContent(sizes.space.w), h = sizes.space.h), bounds: DefaultBounds ) - bctx.layoutFlow(marker, markerSizes) + bctx.layoutFlow(marker, markerSizes, canClear = true) marker.state.offset.x = -marker.state.size.w # take inner box min width etc. box.state = content.state content.state.offset = offset(x = 0, y = 0) of ListStylePositionInside: - bctx.layoutFlow(box, sizes) + bctx.layoutFlow(box, sizes, canClear = true) proc addInlineFloat(ictx: var InlineContext; state: var InlineState; box: BlockBox) = @@ -1841,7 +1849,7 @@ proc layoutTableCell(lctx: LayoutContext; box: BlockBox; sizes.space.w.u -= sizes.padding[dtHorizontal].sum() box.state = BoxLayoutState() var bctx = BlockContext(lctx: lctx) - bctx.layoutFlow(box, sizes) + bctx.layoutFlow(box, sizes, canClear = false) assert bctx.unpositionedFloats.len == 0 # Table cells ignore margins. box.state.offset.y = 0 @@ -2276,10 +2284,11 @@ proc layoutTableWrapper(bctx: BlockContext; box: BlockBox; tctx.layoutCaption(box, caption) #TODO overflow -proc layout(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes) = +proc layout(bctx: var BlockContext; box: BlockBox; sizes: ResolvedSizes; + canClear: bool) = case box.computed{"display"} of DisplayBlock, DisplayFlowRoot, DisplayTableCaption, DisplayInlineBlock: - bctx.layoutFlow(box, sizes) + bctx.layoutFlow(box, sizes, canClear) of DisplayListItem: bctx.layoutListItem(box, sizes) of DisplayTableWrapper, DisplayInlineTableWrapper: @@ -2294,7 +2303,7 @@ proc layoutFlexItem(lctx: LayoutContext; box: BlockBox; sizes: ResolvedSizes) = # 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) + 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. @@ -2526,7 +2535,7 @@ proc layoutRootBlock(lctx: LayoutContext; box: BlockBox; offset: Offset; box.state = BoxLayoutState( offset: offset(x = offset.x + sizes.margin.left, y = offset.y) ) - bctx.layout(box, sizes) + bctx.layout(box, sizes, canClear = false) assert bctx.unpositionedFloats.len == 0 let marginBottom = bctx.marginTodo.sum() # If the highest float edge is higher than the box itself, set that as @@ -2575,7 +2584,7 @@ proc layoutBlockChild(state: var BlockState; bctx: var BlockContext; bctx.marginTodo.append(sizes.margin.top) child.state = BoxLayoutState(offset: offset(x = sizes.margin.left, y = 0)) child.state.offset += state.offset - bctx.layout(child, sizes) + bctx.layout(child, sizes, canClear = true) bctx.marginTodo.append(sizes.margin.bottom) return size( w = child.outerSize(dtHorizontal, sizes), |