diff options
author | bptato <nincsnevem662@gmail.com> | 2022-07-27 22:28:14 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-07-27 23:26:24 +0200 |
commit | dd9cb39c7d6adfa02feb181dd629bb9a93b7250c (patch) | |
tree | 4d4f840847a20577729f12a879c95c7a29a859b7 /src/layout | |
parent | cc92092fe8053f77d0c63e57c3990272b36be4ef (diff) | |
download | chawan-dd9cb39c7d6adfa02feb181dd629bb9a93b7250c.tar.gz |
Fix StyledNode invalidation & others
Diffstat (limited to 'src/layout')
-rw-r--r-- | src/layout/box.nim | 13 | ||||
-rw-r--r-- | src/layout/engine.nim | 102 |
2 files changed, 88 insertions, 27 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim index 7e0ac948..1626791d 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -1,5 +1,6 @@ import options +import css/stylednode import css/values import html/dom import io/term @@ -28,8 +29,7 @@ type children*: seq[BoxBuilder] inlinelayout*: bool computed*: CSSComputedValues - node*: Node - element*: Element + node*: StyledNode InlineBoxBuilder* = ref object of BoxBuilder text*: seq[string] @@ -48,9 +48,12 @@ type marker*: MarkerBoxBuilder content*: BlockBoxBuilder + TableRowGroupBoxBuilder* = ref object of BoxBuilder + + TableRowBoxBuilder* = ref object of BoxBuilder + TableBoxBuilder* = ref object of BoxBuilder - inline*: bool - content*: BlockBoxBuilder + rowgroups*: seq[TableRowGroupBoxBuilder] InlineAtom* = ref object of RootObj offset*: Offset @@ -66,7 +69,7 @@ type fontweight*: int textdecoration*: CSSTextDecoration color*: CSSColor - node*: Node + node*: StyledNode InlineSpacing* = ref object of InlineAtom format*: ComputedFormat diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 8ec1c668..18af9e7b 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -16,7 +16,7 @@ func px(l: CSSLength, viewport: Viewport, p = 0): int {.inline.} = type InlineState = object ictx: InlineContext skip: bool - node: Node + node: StyledNode word: InlineWord maxwidth: int computed: CSSComputedValues @@ -284,7 +284,7 @@ proc processWhitespace(state: var InlineState, c: char) = else: inc state.ictx.whitespacenum -proc renderText*(ictx: InlineContext, str: string, maxwidth: int, computed: CSSComputedValues, node: Node) = +proc renderText*(ictx: InlineContext, str: string, maxwidth: int, computed: CSSComputedValues, node: StyledNode) = var state: InlineState state.computed = computed state.ictx = ictx @@ -421,7 +421,7 @@ proc positionInlines(bctx: BlockBox) = proc buildBlock(box: BlockBoxBuilder, parent: BlockBox): BlockBox proc buildInlines(bctx: BlockBox, inlines: seq[BoxBuilder]): InlineContext -proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: Node) +proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) proc applyInlineDimensions(bctx: BlockBox) = bctx.height += bctx.inline.height @@ -436,7 +436,7 @@ proc buildInlineLayout(bctx: BlockBox, children: seq[BoxBuilder]) = bctx.positionInlines() # Builder only contains block boxes. -proc buildBlockLayout(bctx: BlockBox, children: seq[BoxBuilder], node: Node) = +proc buildBlockLayout(bctx: BlockBox, children: seq[BoxBuilder], node: StyledNode) = bctx.buildBlocks(children, node) func baseline(bctx: BlockBox): int = @@ -609,13 +609,13 @@ proc positionBlocks(bctx: BlockBox) = bctx.width += bctx.padding_left bctx.width += bctx.padding_right -proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: Node) = +proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) = for child in blocks: var cblock: BlockBox 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) + of DISPLAY_TABLE: cblock = buildBlock(BlockBoxBuilder(child), bctx) else: assert false, "child.t is " & $child.computed{"display"} bctx.nested.add(cblock) bctx.positionBlocks() @@ -682,9 +682,19 @@ proc getTableBox(computed: CSSComputedValues): TableBoxBuilder = new(result) result.computed = computed.copyProperties() +# Also known as <tbody>. +proc getTableRowGroupBox(computed: CSSComputedValues): TableRowGroupBoxBuilder = + new(result) + result.computed = computed.copyProperties() + +proc getTableRowBox(computed: CSSComputedValues): TableRowBoxBuilder = + new(result) + result.computed = computed.copyProperties() + type BlockGroup = object parent: BlockBoxBuilder boxes: seq[BoxBuilder] + listItemCounter: int proc add(blockgroup: var BlockGroup, box: BoxBuilder) {.inline.} = blockgroup.boxes.add(box) @@ -703,8 +713,6 @@ func canGenerateAnonymousInline(blockgroup: BlockGroup, computed: CSSComputedVal 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_ibox() = if ibox != nil: assert ibox.computed{"display"} in {DISPLAY_INLINE, DISPLAY_INLINE_BLOCK} @@ -713,10 +721,13 @@ template flush_ibox() = proc newBlockGroup(parent: BlockBoxBuilder): BlockGroup = result.parent = parent + result.listItemCounter = 1 + +proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(MarkerBoxBuilder)): BlockBoxBuilder -proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int) +proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport) -proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, ibox: var InlineBoxBuilder, listItemCounter: var int) = +proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, ibox: var InlineBoxBuilder) = let box = blockgroup.parent if styledNode.node != nil: let elem = Element(styledNode.node) @@ -732,17 +743,17 @@ proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewpo box.children.add(childbox) of DISPLAY_LIST_ITEM: blockgroup.flush() - let childbox = getListItemBox(styledNode.computed, listItemCounter) + let childbox = getListItemBox(styledNode.computed, blockgroup.listItemCounter) if childbox.computed{"list-style-position"} == LIST_STYLE_POSITION_INSIDE: childbox.content = styledNode.generateBlockBox(viewport, some(childbox.marker)) childbox.marker = nil else: childbox.content = styledNode.generateBlockBox(viewport) box.children.add(childbox) - inc listItemCounter + inc blockgroup.listItemCounter of DISPLAY_INLINE: flush_ibox - box.generateInlineBoxes(styledNode, blockgroup, viewport, listItemCounter) + box.generateInlineBoxes(styledNode, blockgroup, viewport) of DISPLAY_INLINE_BLOCK: flush_ibox let childbox = getInlineBlockBox(styledNode.computed) @@ -750,25 +761,24 @@ proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewpo blockgroup.add(childbox) of DISPLAY_TABLE: blockgroup.flush() - let childbox = getTableBox(styledNode.computed) - childbox.content = styledNode.generateBlockBox(viewport) - box.children.add(childbox) + #styledNode.generateFromElemTable(blockgroup.parent, viewport) of DISPLAY_TABLE_ROW_GROUP: discard + of DISPLAY_NONE: discard else: discard #TODO -proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int) = +proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport) = var ibox: InlineBoxBuilder = nil for child in styledNode.children: case child.t of STYLED_ELEMENT: - generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) + generateFromElem(child, blockgroup, viewport, ibox) of STYLED_TEXT: if ibox == nil: ibox = getTextBox(styledNode.computed) - ibox.node = styledNode.node + ibox.node = styledNode ibox.text.add(child.text) flush_ibox @@ -777,7 +787,6 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( let box = getBlockBox(styledNode.computed) var blockgroup = newBlockGroup(box) var ibox: InlineBoxBuilder = nil - var listItemCounter = 1 # ordinal value of current list if marker.issome: ibox = marker.get @@ -787,12 +796,12 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( case child.t of STYLED_ELEMENT: flush_ibox - generateFromElem(child, blockgroup, viewport, ibox, listItemCounter) + generateFromElem(child, blockgroup, viewport, ibox) of STYLED_TEXT: if canGenerateAnonymousInline(blockgroup, box.computed, child.text): if ibox == nil: ibox = getTextBox(styledNode.computed) - ibox.node = styledNode.node + ibox.node = styledNode ibox.text.add(child.text) flush_ibox @@ -805,6 +814,55 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( blockgroup.flush() return box +const RowGroupBox = {DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, + DISPLAY_TABLE_FOOTER_GROUP} +const ProperTableChild = {DISPLAY_TABLE_ROW, DISPLAY_TABLE_COLUMN, + DISPLAY_TABLE_COLUMN_GROUP} + RowGroupBox +const ProperTableRowParent = {DISPLAY_TABLE} + RowGroupBox #TODO inline-table box +const InternalTableBox = {DISPLAY_TABLE_CELL, DISPLAY_TABLE_ROW, DISPLAY_TABLE_COLUMN, DISPLAY_TABLE_COLUMN_GROUP} + RowGroupBox +const TabularContainer = {DISPLAY_TABLE_ROW} + ProperTableRowParent + +proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBox = + discard + #let box = getTableBox(styledNode.computed) + #var blockgroup = newBlockGroup(box) + #var ibox: InlineBoxBuilder = nil + #var listItemCounter = 1 + + #for child in styledNode.children: + # if child.t == STYLED_ELEMENT: + # generateFromElem(child, blockgroup, viewport, ibox) + # else: + # if canGenerateAnonymousInline(blockgroup, box.computed, child.text): + # if ibox == nil: + # ibox = getTextBox(styledNode.computed) + # ibox.node = styledNode.node + # ibox.text.add(child.text) + + #flush_ibox + #blockgroup.flush() + + ## Generate missing child wrappers + #var anonRow: TableRowBoxBuilder + #for child in box.children: + # if child.computed{"display"} notin ProperTableChild: + # if anonRow != nil: + # anonRow = getTableRowBox(box.computed.inheritProperties()) + # discard + + +#proc generateFromElemTable(styledNode: StyledNode, viewport: Viewport, table: TableBoxBuilder = nil, parent: BoxBuilder = nil): BlockBox = +# case styledNode.computed{"display"} +# of DISPLAY_TABLE: +# of DISPLAY_TABLE_ROW_GROUP: +# if parent != table: +# # misparented +# let box = getTableRowGroupBox(styledNode.computed) +# let anonymousTable = getTableBox(styledNode.computed.inheritProperties()) +# anonymousTable.children.add(box) +# parent.children.add(anonymousTable) +# else: +# discard proc renderLayout*(viewport: var Viewport, document: Document, root: StyledNode) = let builder = root.generateBlockBox(viewport) |