diff options
author | bptato <nincsnevem662@gmail.com> | 2022-07-25 19:20:10 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-07-25 19:20:31 +0200 |
commit | cc92092fe8053f77d0c63e57c3990272b36be4ef (patch) | |
tree | 072415fc89542f9344062b29e799e937ca105371 | |
parent | a76416401297cfc10ae6d0645f2ee212b5336a33 (diff) | |
download | chawan-cc92092fe8053f77d0c63e57c3990272b36be4ef.tar.gz |
Fix & simplify blockgroup
+ start implementing table
-rw-r--r-- | src/css/values.nim | 2 | ||||
-rw-r--r-- | src/layout/box.nim | 6 | ||||
-rw-r--r-- | src/layout/engine.nim | 65 |
3 files changed, 51 insertions, 22 deletions
diff --git a/src/css/values.nim b/src/css/values.nim index fc7e035f..be8f5305 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -589,7 +589,7 @@ func cssDisplay(d: CSSDeclaration): CSSDisplay = of "inline": return DISPLAY_INLINE of "list-item": return DISPLAY_LIST_ITEM of "inline-block": return DISPLAY_INLINE_BLOCK - # of "table": return DISPLAY_TABLE + of "table": return DISPLAY_TABLE # of "table-row": return DISPLAY_TABLE_ROW # of "table-cell": return DISPLAY_TABLE_CELL # of "table-column": return DISPLAY_TABLE_COLUMN diff --git a/src/layout/box.nim b/src/layout/box.nim index 2bd83185..7e0ac948 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -48,6 +48,10 @@ type marker*: MarkerBoxBuilder content*: BlockBoxBuilder + TableBoxBuilder* = ref object of BoxBuilder + inline*: bool + content*: BlockBoxBuilder + InlineAtom* = ref object of RootObj offset*: Offset width*: int @@ -119,6 +123,8 @@ type ListItemBox* = ref object of BlockBox marker*: InlineContext + TableBox* = ref object of BlockBox + InlineBlockBox* = ref object of InlineAtom bctx*: BlockBox margin_top*: int diff --git a/src/layout/engine.nim b/src/layout/engine.nim index ddc5bb30..8ec1c668 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -615,6 +615,7 @@ proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: Node) = case child.computed{"display"} of DISPLAY_BLOCK: cblock = buildBlock(BlockBoxBuilder(child), bctx) of DISPLAY_LIST_ITEM: cblock = buildListItem(ListItemBoxBuilder(child), bctx) + of DISPLAY_TABLE: cblock = buildBlock(TableBoxBuilder(child).content, bctx) else: assert false, "child.t is " & $child.computed{"display"} bctx.nested.add(cblock) bctx.positionBlocks() @@ -677,31 +678,46 @@ proc getListItemBox(computed: CSSComputedValues, listItemCounter: int): ListItem result.computed = computed.copyProperties() result.marker = getMarkerBox(computed, listItemCounter) +proc getTableBox(computed: CSSComputedValues): TableBoxBuilder = + new(result) + result.computed = computed.copyProperties() + +type BlockGroup = object + parent: BlockBoxBuilder + boxes: seq[BoxBuilder] + +proc add(blockgroup: var BlockGroup, box: BoxBuilder) {.inline.} = + blockgroup.boxes.add(box) + +proc flush(blockgroup: var BlockGroup) {.inline.} = + if blockgroup.boxes.len > 0: + let bbox = getBlockBox(blockgroup.parent.computed.inheritProperties()) + bbox.inlinelayout = true + bbox.children = blockgroup.boxes + blockgroup.parent.children.add(bbox) + blockgroup.boxes.setLen(0) + # Don't generate empty anonymous inline blocks between block boxes -func canGenerateAnonymousInline(blockgroup: seq[BoxBuilder], computed: CSSComputedValues, str: string): bool = - return blockgroup.len > 0 and blockgroup[^1].computed{"display"} == DISPLAY_INLINE or +func canGenerateAnonymousInline(blockgroup: BlockGroup, computed: CSSComputedValues, str: string): bool = + return blockgroup.boxes.len > 0 and blockgroup.boxes[^1].computed{"display"} == DISPLAY_INLINE or computed{"white-space"} in {WHITESPACE_PRE_LINE, WHITESPACE_PRE, WHITESPACE_PRE_WRAP} or not str.onlyWhitespace() proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(MarkerBoxBuilder)): BlockBoxBuilder -template flush_block_group(computed: CSSComputedValues) = - if blockgroup.len > 0: - let bbox = getBlockBox(computed.inheritProperties()) - bbox.inlinelayout = true - bbox.children = blockgroup - box.children.add(bbox) - blockgroup.setLen(0) - template flush_ibox() = if ibox != nil: assert ibox.computed{"display"} in {DISPLAY_INLINE, DISPLAY_INLINE_BLOCK} blockgroup.add(ibox) ibox = nil -proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, listItemCounter: var int) +proc newBlockGroup(parent: BlockBoxBuilder): BlockGroup = + result.parent = parent + +proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int) -proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, ibox: var InlineBoxBuilder, listItemCounter: var int) = +proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, ibox: var InlineBoxBuilder, listItemCounter: var int) = + let box = blockgroup.parent if styledNode.node != nil: let elem = Element(styledNode.node) if elem.tagType == TAG_BR: @@ -711,11 +727,11 @@ proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: case styledNode.computed{"display"} of DISPLAY_BLOCK: - flush_block_group(styledNode.computed) + blockgroup.flush() let childbox = styledNode.generateBlockBox(viewport) box.children.add(childbox) of DISPLAY_LIST_ITEM: - flush_block_group(styledNode.computed) + blockgroup.flush() let childbox = getListItemBox(styledNode.computed, listItemCounter) if childbox.computed{"list-style-position"} == LIST_STYLE_POSITION_INSIDE: childbox.content = styledNode.generateBlockBox(viewport, some(childbox.marker)) @@ -732,16 +748,23 @@ proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: let childbox = getInlineBlockBox(styledNode.computed) childbox.content = styledNode.generateBlockBox(viewport) blockgroup.add(childbox) + of DISPLAY_TABLE: + blockgroup.flush() + let childbox = getTableBox(styledNode.computed) + childbox.content = styledNode.generateBlockBox(viewport) + box.children.add(childbox) + of DISPLAY_TABLE_ROW_GROUP: + discard else: discard #TODO -proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, listItemCounter: var int) = +proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int) = var ibox: InlineBoxBuilder = nil for child in styledNode.children: case child.t of STYLED_ELEMENT: - box.generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) + generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) of STYLED_TEXT: if ibox == nil: ibox = getTextBox(styledNode.computed) @@ -752,7 +775,7 @@ proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgrou proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(MarkerBoxBuilder)): BlockBoxBuilder = let box = getBlockBox(styledNode.computed) - var blockgroup: seq[BoxBuilder] + var blockgroup = newBlockGroup(box) var ibox: InlineBoxBuilder = nil var listItemCounter = 1 # ordinal value of current list @@ -764,7 +787,7 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( case child.t of STYLED_ELEMENT: flush_ibox - box.generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) + generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) of STYLED_TEXT: if canGenerateAnonymousInline(blockgroup, box.computed, child.text): if ibox == nil: @@ -773,13 +796,13 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( ibox.text.add(child.text) flush_ibox - if blockgroup.len > 0: + if blockgroup.boxes.len > 0: # Avoid unnecessary anonymous block boxes if box.children.len == 0: - box.children = blockgroup + box.children = blockgroup.boxes box.inlinelayout = true else: - flush_block_group(styledNode.computed) + blockgroup.flush() return box |