diff options
author | bptato <nincsnevem662@gmail.com> | 2024-04-15 12:19:34 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-04-15 12:19:34 +0200 |
commit | ad368735ed9e78f5f4e7ed73a5e3cf8d19ce055b (patch) | |
tree | 0c6ca2999dd85c85867165f50bdf6fc49a93aca3 | |
parent | b0b3d6c0b9e04c6679c57bc9029268d30a6bd269 (diff) | |
download | chawan-ad368735ed9e78f5f4e7ed73a5e3cf8d19ce055b.tar.gz |
layout: remove ListItemBox, handle inline-flex correctly
This allows us to unify BlockBox instantiation and block-level inner layout calls.
-rw-r--r-- | src/layout/box.nim | 3 | ||||
-rw-r--r-- | src/layout/engine.nim | 143 | ||||
-rw-r--r-- | src/layout/renderdocument.nim | 10 |
3 files changed, 65 insertions, 91 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim index ab86f67b..bbb3d91e 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -76,6 +76,3 @@ type firstBaseline*: LayoutUnit # baseline of the last line box of all descendants baseline*: LayoutUnit - - ListItemBox* = ref object of BlockBox - marker*: RootInlineFragment diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 4156a302..aea9f2c8 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -1343,6 +1343,43 @@ proc layoutFlow(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder; # Builder only contains block boxes. bctx.layoutBlock(box, builder, sizes) +proc layoutListItem(bctx: var BlockContext; box: BlockBox; + builder: ListItemBoxBuilder; sizes: ResolvedSizes) = + if builder.marker != nil: + # wrap marker + main box in a new box + let innerBox = BlockBox( + computed: builder.computed, + node: builder.node, + offset: Offset(x: sizes.margin.left), + margin: sizes.margin + ) + bctx.layoutFlow(innerBox, builder.content, sizes) + #TODO we should put markers right before the first atom of the parent + # list item or something... + var bctx = BlockContext(lctx: bctx.lctx) + let children = @[BoxBuilder(builder.marker)] + let space = AvailableSpace(w: fitContent(sizes.space.w), h: sizes.space.h) + let markerInline = bctx.layoutRootInline(children, space, + builder.marker.computed, Offset(), Offset()) + let marker = BlockBox( + computed: builder.marker.computed, + inline: markerInline, + size: markerInline.size, + offset: Offset(x: -markerInline.size.w), + xminwidth: markerInline.xminwidth + ) + # take inner box min width etc. + box.xminwidth = innerBox.xminwidth + box.baseline = innerBox.baseline + box.firstBaseline = innerBox.firstBaseline + box.size = innerBox.size + # innerBox can keep its margin without double margin, it won't be used + # anymore. + box.margin = innerBox.margin + box.nested = @[marker, innerBox] + else: + bctx.layoutFlow(box, builder.content, sizes) + # parentWidth, parentHeight: width/height of the containing block. proc addInlineBlock(ictx: var InlineContext; state: var InlineState; builder: BlockBoxBuilder; parentWidth, parentHeight: SizeConstraint) = @@ -1476,7 +1513,7 @@ proc layoutRootInline(bctx: var BlockContext, inlines: seq[BoxBuilder], of DISPLAY_INLINE: let childFragment = ictx.layoutInline(InlineBoxBuilder(child)) root.fragment.children.add(childFragment) - of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE: + of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE, DISPLAY_INLINE_FLEX: # add an anonymous fragment to contain this var state = InlineState( computed: computed, @@ -1502,48 +1539,6 @@ proc layoutRootInline(bctx: var BlockContext, inlines: seq[BoxBuilder], root.xminwidth = ictx.minwidth return root -# Build a block box without establishing a new block formatting context. -proc buildBlock(bctx: var BlockContext; builder: BlockBoxBuilder; - sizes: ResolvedSizes; offset: Offset): BlockBox = - let box = BlockBox( - computed: builder.computed, - node: builder.node, - offset: Offset(x: offset.x + sizes.margin.left, y: offset.y), - margin: sizes.margin - ) - bctx.layoutFlow(box, builder, sizes) - return box - -proc buildListItem(bctx: var BlockContext; builder: ListItemBoxBuilder; - sizes: ResolvedSizes; offset: Offset): ListItemBox = - let box = ListItemBox( - computed: builder.computed, - node: builder.node, - offset: Offset(x: offset.x + sizes.margin.left, y: offset.y), - margin: sizes.margin - ) - if builder.marker != nil: - #TODO we should put markers right before the first atom of the parent - # list item or something... - var bctx = BlockContext(lctx: bctx.lctx) - let children = @[BoxBuilder(builder.marker)] - let space = AvailableSpace(w: fitContent(sizes.space.w), h: sizes.space.h) - box.marker = bctx.layoutRootInline(children, space, builder.marker.computed, - Offset(), Offset()) - bctx.layoutFlow(box, builder.content, sizes) - return box - -proc buildTable(bctx: var BlockContext; builder: TableBoxBuilder; - sizes: ResolvedSizes; offset: Offset): BlockBox = - let box = BlockBox( - computed: builder.computed, - node: builder.node, - offset: Offset(x: offset.x + sizes.margin.left, y: offset.y), - margin: sizes.margin - ) - bctx.lctx.layoutTable(box, builder, sizes) - return box - proc positionAbsolute(lctx: LayoutState, box: BlockBox, margin: RelativeRect) = let last = lctx.positioned[^1] let left = box.computed{"left"} @@ -2058,35 +2053,32 @@ proc postAlignChild(box, child: BlockBox, width: LayoutUnit) = else: discard -proc buildFlex(bctx: var BlockContext; builder: BlockBoxBuilder; - sizes: ResolvedSizes; offset: Offset): BlockBox = - let box = BlockBox( - computed: builder.computed, - node: builder.node, - offset: Offset(x: offset.x + sizes.margin.left, y: offset.y), - margin: sizes.margin - ) - bctx.layoutFlex(box, builder, sizes) - return box - -proc layoutFlexChild(lctx: LayoutState; builder: BoxBuilder; - sizes: ResolvedSizes): BlockBox = - var bctx = BlockContext(lctx: lctx) - # note: we do not append margins here, since those belong to the flex item, - # not its inner BFC. - var offset = Offset() - let box = case builder.computed{"display"} +proc layout(bctx: var BlockContext; box: BlockBox; builder: BoxBuilder; + sizes: ResolvedSizes) = + case builder.computed{"display"} of DISPLAY_BLOCK, DISPLAY_FLOW_ROOT: - bctx.buildBlock(BlockBoxBuilder(builder), sizes, offset) + bctx.layoutFlow(box, BlockBoxBuilder(builder), sizes) of DISPLAY_LIST_ITEM: - bctx.buildListItem(ListItemBoxBuilder(builder), sizes, offset) + bctx.layoutListItem(box, ListItemBoxBuilder(builder), sizes) of DISPLAY_TABLE: - bctx.buildTable(TableBoxBuilder(builder), sizes, offset) + bctx.lctx.layoutTable(box, TableBoxBuilder(builder), sizes) of DISPLAY_FLEX: - bctx.buildFlex(BlockBoxBuilder(builder), sizes, offset) + bctx.layoutFlex(box, BlockBoxBuilder(builder), sizes) else: assert false, "builder.t is " & $builder.computed{"display"} - BlockBox(nil) + +proc layoutFlexChild(lctx: LayoutState; builder: BoxBuilder; + sizes: ResolvedSizes): BlockBox = + var bctx = BlockContext(lctx: lctx) + # note: we do not append margins here, since those belong to the flex item, + # not its inner BFC. + let box = BlockBox( + computed: builder.computed, + node: builder.node, + offset: Offset(x: sizes.margin.left), + margin: sizes.margin + ) + bctx.layout(box, builder, sizes) return box type @@ -2339,18 +2331,13 @@ proc layoutBlockChild(bctx: var BlockContext; builder: BoxBuilder; # for nested blocks that do not establish their own BFC, and thus take part # in margin collapsing. bctx.marginTodo.append(sizes.margin.top) - let box = case builder.computed{"display"} - of DISPLAY_BLOCK, DISPLAY_FLOW_ROOT: - bctx.buildBlock(BlockBoxBuilder(builder), sizes, offset) - of DISPLAY_LIST_ITEM: - bctx.buildListItem(ListItemBoxBuilder(builder), sizes, offset) - of DISPLAY_TABLE: - bctx.buildTable(TableBoxBuilder(builder), sizes, offset) - of DISPLAY_FLEX: - bctx.buildFlex(BlockBoxBuilder(builder), sizes, offset) - else: - assert false, "builder.t is " & $builder.computed{"display"} - BlockBox(nil) + let box = BlockBox( + computed: builder.computed, + node: builder.node, + offset: Offset(x: offset.x + sizes.margin.left, y: offset.y), + margin: sizes.margin + ) + bctx.layout(box, builder, sizes) if appendMargins: bctx.marginTodo.append(sizes.margin.bottom) return box diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim index 06a6992a..7227cbfe 100644 --- a/src/layout/renderdocument.nim +++ b/src/layout/renderdocument.nim @@ -431,16 +431,6 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState; let y = toInt(offset.y div state.attrs.ppl) if y >= 0 and x + w >= 0: grid.setText(s, x, y, box.computed.toFormat(), box.node) - - if box of ListItemBox: - let box = ListItemBox(box) - if box.marker != nil: - let offset = Offset( - x: offset.x - box.marker.size.w, - y: offset.y - ) - grid.renderRootInlineFragment(state, box.marker, offset) - if box.inline != nil: assert box.nested.len == 0 if box.computed{"visibility"} == VISIBILITY_VISIBLE: |