diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/css/values.nim | 34 | ||||
-rw-r--r-- | src/layout/box.nim | 5 | ||||
-rw-r--r-- | src/layout/engine.nim | 288 | ||||
-rw-r--r-- | src/render/renderdocument.nim | 5 |
4 files changed, 221 insertions, 111 deletions
diff --git a/src/css/values.nim b/src/css/values.nim index 55ee663e..86faf75b 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -27,13 +27,14 @@ type PROPERTY_PADDING_TOP, PROPERTY_PADDING_LEFT, PROPERTY_PADDING_RIGHT, PROPERTY_PADDING_BOTTOM, PROPERTY_WORD_SPACING, PROPERTY_VERTICAL_ALIGN, PROPERTY_LINE_HEIGHT, PROPERTY_TEXT_ALIGN, PROPERTY_LIST_STYLE_POSITION, - PROPERTY_BACKGROUND_COLOR + PROPERTY_BACKGROUND_COLOR, PROPERTY_POSITION, PROPERTY_LEFT, + PROPERTY_RIGHT, PROPERTY_TOP, PROPERTY_BOTTOM CSSValueType* = enum VALUE_NONE, VALUE_LENGTH, VALUE_COLOR, VALUE_CONTENT, VALUE_DISPLAY, VALUE_FONT_STYLE, VALUE_WHITE_SPACE, VALUE_INTEGER, VALUE_TEXT_DECORATION, VALUE_WORD_BREAK, VALUE_LIST_STYLE_TYPE, VALUE_VERTICAL_ALIGN, - VALUE_TEXT_ALIGN, VALUE_LIST_STYLE_POSITION + VALUE_TEXT_ALIGN, VALUE_LIST_STYLE_POSITION, VALUE_POSITION CSSGlobalValueType* = enum VALUE_NOGLOBAL, VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET @@ -54,7 +55,7 @@ type CSSPosition* = enum POSITION_STATIC, POSITION_RELATIVE, POSITION_ABSOLUTE, POSITION_FIXED, - POSITION_INHERIT + POSITION_STICKY CSSTextDecoration* = enum TEXT_DECORATION_NONE, TEXT_DECORATION_UNDERLINE, TEXT_DECORATION_OVERLINE, @@ -131,6 +132,8 @@ type textalign*: CSSTextAlign of VALUE_LIST_STYLE_POSITION: liststyleposition*: CSSListStylePosition + of VALUE_POSITION: + position*: CSSPosition of VALUE_NONE: discard CSSComputedValues* = ref array[CSSPropertyType, CSSComputedValue] @@ -183,6 +186,11 @@ const PropertyNames = { "text-align": PROPERTY_TEXT_ALIGN, "list-style-position": PROPERTY_LIST_STYLE_POSITION, "background-color": PROPERTY_BACKGROUND_COLOR, + "position": PROPERTY_POSITION, + "left": PROPERTY_LEFT, + "right": PROPERTY_RIGHT, + "top": PROPERTY_TOP, + "bottom": PROPERTY_BOTTOM }.toTable() const ValueTypes* = [ @@ -215,6 +223,11 @@ const ValueTypes* = [ PROPERTY_TEXT_ALIGN: VALUE_TEXT_ALIGN, PROPERTY_LIST_STYLE_POSITION: VALUE_LIST_STYLE_POSITION, PROPERTY_BACKGROUND_COLOR: VALUE_COLOR, + PROPERTY_POSITION: VALUE_POSITION, + PROPERTY_LEFT: VALUE_LENGTH, + PROPERTY_RIGHT: VALUE_LENGTH, + PROPERTY_TOP: VALUE_LENGTH, + PROPERTY_BOTTOM: VALUE_LENGTH ] const InheritedProperties = { @@ -618,6 +631,19 @@ func cssListStylePosition(d: CSSDeclaration): CSSListStylePosition = else: raise newException(CSSValueError, "Invalid list style position") raise newException(CSSValueError, "Invalid list style position") +func cssPosition(d: CSSDeclaration): CSSPosition = + if isToken(d): + let tok = getToken(d) + if tok.tokenType == CSS_IDENT_TOKEN: + return case tok.value + of "static": POSITION_STATIC + of "relative": POSITION_RELATIVE + of "absolute": POSITION_ABSOLUTE + of "fixed": POSITION_FIXED + of "sticky": POSITION_STICKY + else: raise newException(CSSValueError, "Invalid list style position") + raise newException(CSSValueError, "Invalid list style position") + proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueType, ptype: CSSPropertyType) = case vtype of VALUE_COLOR: val.color = cssColor(d) @@ -642,6 +668,7 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueT of VALUE_VERTICAL_ALIGN: val.verticalalign = cssVerticalAlign(d) of VALUE_TEXT_ALIGN: val.textalign = cssTextAlign(d) of VALUE_LIST_STYLE_POSITION: val.liststyleposition = cssListStylePosition(d) + of VALUE_POSITION: val.position = cssPosition(d) of VALUE_NONE: discard func getInitialColor(t: CSSPropertyType): RGBAColor = @@ -717,6 +744,7 @@ func equals*(a, b: CSSComputedValue): bool = of VALUE_VERTICAL_ALIGN: return a.verticalalign == b.verticalalign of VALUE_TEXT_ALIGN: return a.textalign == b.textalign of VALUE_LIST_STYLE_POSITION: return a.liststyleposition == b.liststyleposition + of VALUE_POSITION: return a.position == b.position of VALUE_NONE: return true return false diff --git a/src/layout/box.nim b/src/layout/box.nim index 8f460a19..a3dae912 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -24,7 +24,8 @@ type Viewport* = ref object window*: WindowAttributes - root*: BlockBox + root*: seq[BlockBox] + absolutes*: seq[BlockBox] BoxBuilder* = ref object of RootObj children*: seq[BoxBuilder] @@ -152,7 +153,7 @@ type maxwidth*: int InlineBlockBox* = ref object of InlineAtom - bctx*: BlockBox + innerbox*: BlockBox margin_top*: int margin_bottom*: int diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 408c3b70..4a136c87 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -218,15 +218,19 @@ proc finish(ictx: InlineContext, computed: CSSComputedValues, maxwidth: int) = for line in ictx.lines: ictx.horizontalAlignLine(line, computed, maxwidth, line == ictx.lines[^1]) -proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, computed: CSSComputedValues) = - var shift = ictx.computeShift(computed) +# pcomputed: computed values of parent, for white-space: pre, line-height +# computed: computed values of child, for vertical-align +# (TODO: surely there's a better way to do this? like storing pcomputed in ictx +# or something...) +proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, pcomputed, computed: CSSComputedValues) = + var shift = ictx.computeShift(pcomputed) ictx.whitespacenum = 0 # Line wrapping - if not computed.whitespacepre: + if not pcomputed.whitespacepre: if ictx.currentLine.width + atom.width + shift > maxwidth: - ictx.finishLine(computed, maxwidth, false) + ictx.finishLine(pcomputed, maxwidth, false) # Recompute on newline - shift = ictx.computeShift(computed) + shift = ictx.computeShift(pcomputed) if atom.width > 0 and atom.height > 0: atom.vertalign = computed{"vertical-align"} @@ -235,7 +239,7 @@ proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, computed: CSS ictx.currentLine.addSpacing(shift, ictx.cellheight, ictx.format) atom.offset.x += ictx.currentLine.width - applyLineHeight(ictx.viewport, ictx.currentLine, computed) + applyLineHeight(ictx.viewport, ictx.currentLine, pcomputed) ictx.currentLine.width += atom.width if atom of InlineWord: ictx.format = InlineWord(atom).format @@ -248,7 +252,7 @@ proc addWord(state: var InlineState) = var word = state.word word.height = state.ictx.cellheight word.baseline = word.height - state.ictx.addAtom(word, state.maxwidth, state.computed) + state.ictx.addAtom(word, state.maxwidth, state.computed, state.computed) state.newWord() # Start a new line, even if the previous one is empty @@ -351,18 +355,18 @@ proc preferredDimensions(computed: CSSComputedValues, viewport: Viewport, width: elif height.issome: result.compheight = pheight.px(viewport, height.get).some -proc setPreferredDimensions(bctx: BlockBox, width: int, height: Option[int]) = - let preferred = preferredDimensions(bctx.computed, bctx.viewport, width, height) - bctx.compwidth = preferred.compwidth - bctx.compheight = preferred.compheight - bctx.padding_top = preferred.padding_top - bctx.padding_bottom = preferred.padding_bottom - bctx.padding_left = preferred.padding_left - bctx.padding_right = preferred.padding_right - bctx.margin_top = preferred.margin_top - bctx.margin_bottom = preferred.margin_bottom - bctx.margin_left = preferred.margin_left - bctx.margin_right = preferred.margin_right +proc setPreferredDimensions(box: BlockBox, width: int, height: Option[int]) = + let preferred = preferredDimensions(box.computed, box.viewport, width, height) + box.compwidth = preferred.compwidth + box.compheight = preferred.compheight + box.padding_top = preferred.padding_top + box.padding_bottom = preferred.padding_bottom + box.padding_left = preferred.padding_left + box.padding_right = preferred.padding_right + box.margin_top = preferred.margin_top + box.margin_bottom = preferred.margin_bottom + box.margin_left = preferred.margin_left + box.margin_right = preferred.margin_right proc newBlockBox_common2(box: BlockBox, parent: BlockBox, builder: BoxBuilder) {.inline.} = box.viewport = parent.viewport @@ -405,52 +409,56 @@ proc newBlockBox(viewport: Viewport, box: BlockBoxBuilder): BlockBox = proc newInlineBlock(viewport: Viewport, builder: InlineBlockBoxBuilder, parentWidth: int, parentHeight = none(int)): InlineBlockBox = new(result) - result.bctx = newFlowRootBox(viewport, builder.content, parentWidth, parentHeight) + result.innerbox = newFlowRootBox(viewport, builder.content, parentWidth, parentHeight) -proc newInlineContext(bctx: BlockBox): InlineContext = +proc newInlineContext(parent: BlockBox): InlineContext = new(result) result.currentLine = LineBox() - result.viewport = bctx.viewport - result.shrink = bctx.shrink + result.viewport = parent.viewport + result.shrink = parent.shrink -proc positionInlines(bctx: BlockBox) = - bctx.width += bctx.padding_left - bctx.inline.offset.x += bctx.padding_left +proc positionInlines(parent: BlockBox) = + parent.width += parent.padding_left + parent.inline.offset.x += parent.padding_left - bctx.height += bctx.padding_top - bctx.inline.offset.y += bctx.padding_top + parent.height += parent.padding_top + parent.inline.offset.y += parent.padding_top - bctx.height += bctx.padding_bottom + parent.height += parent.padding_bottom - bctx.width += bctx.padding_right + parent.width += parent.padding_right - if bctx.computed{"width"}.auto: - if bctx.shrink: - bctx.width = min(bctx.width, bctx.compwidth) + if parent.computed{"width"}.auto: + if parent.shrink: + parent.width = min(parent.width, parent.compwidth) else: - bctx.width = max(bctx.width, bctx.compwidth) + parent.width = max(parent.width, parent.compwidth) else: - bctx.width = bctx.compwidth + parent.width = parent.compwidth proc buildBlock(box: BlockBoxBuilder, parent: BlockBox, maxwidth = none(int)): BlockBox -proc buildInlines(bctx: BlockBox, inlines: seq[BoxBuilder]): InlineContext -proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) +proc buildInlines(parent: BlockBox, inlines: seq[BoxBuilder]): InlineContext +proc buildBlocks(parent: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) -proc applyInlineDimensions(bctx: BlockBox) = - bctx.height += bctx.inline.height - if bctx.compheight.issome: - bctx.height = bctx.compheight.get - bctx.width = max(bctx.width, bctx.inline.maxwidth) +proc applyInlineDimensions(parent: BlockBox) = + parent.height += parent.inline.height + if parent.compheight.issome: + parent.height = parent.compheight.get + parent.width = max(parent.width, parent.inline.maxwidth) # Builder only contains inline boxes. -proc buildInlineLayout(bctx: BlockBox, children: seq[BoxBuilder]) = - bctx.inline = bctx.buildInlines(children) - bctx.applyInlineDimensions() - bctx.positionInlines() +proc buildInlineLayout(parent: BlockBox, children: seq[BoxBuilder]) = + parent.inline = parent.buildInlines(children) + parent.applyInlineDimensions() + parent.positionInlines() # Builder only contains block boxes. -proc buildBlockLayout(bctx: BlockBox, children: seq[BoxBuilder], node: StyledNode) = - bctx.buildBlocks(children, node) +proc buildBlockLayout(parent: BlockBox, children: seq[BoxBuilder], node: StyledNode) = + if parent.computed{"position"} == POSITION_ABSOLUTE: + parent.viewport.absolutes.add(parent) + parent.buildBlocks(children, node) + if parent.computed{"position"} == POSITION_ABSOLUTE: + discard parent.viewport.absolutes.pop() func baseline(bctx: BlockBox): int = if bctx.inline != nil: @@ -470,9 +478,9 @@ proc buildInlineBlock(builder: InlineBlockBoxBuilder, parent: InlineContext, par let blockbuilder = builder.content if blockbuilder.inlinelayout: - result.bctx.buildInlineLayout(blockbuilder.children) + result.innerbox.buildInlineLayout(blockbuilder.children) else: - result.bctx.buildBlockLayout(blockbuilder.children, blockbuilder.node) + result.innerbox.buildBlockLayout(blockbuilder.children, blockbuilder.node) let pwidth = builder.computed{"width"} if pwidth.auto: @@ -480,23 +488,23 @@ proc buildInlineBlock(builder: InlineBlockBoxBuilder, parent: InlineContext, par # Currently the misery that is determining content width is deferred to the # inline layouting algorithm, which doesn't work that great but that's what # we have. - result.bctx.width = min(parentWidth, result.bctx.width) + result.innerbox.width = min(parentWidth, result.innerbox.width) else: - result.bctx.width = pwidth.px(parent.viewport, parentWidth) + result.innerbox.width = pwidth.px(parent.viewport, parentWidth) # Apply the block box's properties to the atom itself. - result.width = result.bctx.width - result.height = result.bctx.height + result.width = result.innerbox.width + result.height = result.innerbox.height - result.margin_top = result.bctx.margin_top - result.margin_bottom = result.bctx.margin_bottom + result.margin_top = result.innerbox.margin_top + result.margin_bottom = result.innerbox.margin_bottom - result.baseline = result.bctx.baseline + result.baseline = result.innerbox.baseline # I don't like this, but it works... - result.offset.x = result.bctx.margin_left - result.width += result.bctx.margin_left - result.width += result.bctx.margin_right + result.offset.x = result.innerbox.margin_left + result.width += result.innerbox.margin_left + result.width += result.innerbox.margin_right proc buildInline(viewport: Viewport, box: InlineBoxBuilder, parentWidth: int, parentHeight = none(int)) = assert box.ictx != nil @@ -524,7 +532,7 @@ proc buildInline(viewport: Viewport, box: InlineBoxBuilder, parentWidth: int, pa of DISPLAY_INLINE_BLOCK: let child = InlineBlockBoxBuilder(child) let iblock = child.buildInlineBlock(box.ictx, parentWidth, parentHeight) - box.ictx.addAtom(iblock, parentWidth, child.computed) + box.ictx.addAtom(iblock, parentWidth, box.computed, child.computed) box.ictx.whitespacenum = 0 else: assert false, "child.t is " & $child.computed{"display"} @@ -537,23 +545,23 @@ proc buildInline(viewport: Viewport, box: InlineBoxBuilder, parentWidth: int, pa let margin_right = box.computed{"margin-right"}.px(viewport, parentWidth) box.ictx.currentLine.width += margin_right -proc buildInlines(bctx: BlockBox, inlines: seq[BoxBuilder]): InlineContext = - let ictx = bctx.newInlineContext() +proc buildInlines(parent: BlockBox, inlines: seq[BoxBuilder]): InlineContext = + let ictx = parent.newInlineContext() if inlines.len > 0: for child in inlines: case child.computed{"display"} of DISPLAY_INLINE: let child = InlineBoxBuilder(child) child.ictx = ictx - buildInline(bctx.viewport, child, bctx.compwidth, bctx.compheight) + buildInline(parent.viewport, child, parent.compwidth, parent.compheight) of DISPLAY_INLINE_BLOCK: let child = InlineBlockBoxBuilder(child) - let iblock = child.buildInlineBlock(ictx, bctx.compwidth) - ictx.addAtom(iblock, bctx.compwidth, child.computed) + let iblock = child.buildInlineBlock(ictx, parent.compwidth) + ictx.addAtom(iblock, parent.compwidth, parent.computed, child.computed) ictx.whitespacenum = 0 else: assert false, "child.t is " & $child.computed{"display"} - ictx.finish(bctx.computed, bctx.compwidth) + ictx.finish(parent.computed, parent.compwidth) return ictx @@ -568,59 +576,130 @@ proc buildListItem(builder: ListItemBoxBuilder, parent: BlockBox): ListItemBox = else: result.buildBlockLayout(builder.content.children, builder.content.node) -proc positionBlocks(bctx: BlockBox) = +proc positionFixed(box: BlockBox, last: BlockBox = box.viewport.root[0]) = + #TODO for now this is a good approximation, but fixed actually means + # something completely different... + box.offset.x += last.offset.x + box.offset.y += last.offset.y + #TODO TODO TODO subtract these from width/height + let left = box.computed{"left"} + let right = box.computed{"right"} + let top = box.computed{"top"} + let bottom = box.computed{"bottom"} + if not left.auto: + box.offset.x += left.px(box.viewport, last.compwidth) + box.offset.x += box.margin_left + elif not right.auto: + box.offset.x += last.width - right.px(box.viewport, box.compwidth) - box.width + box.offset.x -= box.margin_right + if not top.auto: + box.offset.y += top.px(box.viewport, box.compheight.get(0)) + box.offset.y += box.margin_top + elif not bottom.auto: + box.offset.y += last.height - bottom.px(box.viewport, box.compheight.get(0)) - box.height + box.offset.y -= box.margin_bottom + box.viewport.root.add(box) + +proc positionAbsolute(box: BlockBox) = + let last = if box.viewport.absolutes.len > 0: + box.viewport.absolutes[^1] + else: + box.viewport.root[0] + box.positionFixed(last) + +proc positionRelative(parent, box: BlockBox) = + let left = box.computed{"left"} + let right = box.computed{"right"} + let top = box.computed{"top"} + let bottom = box.computed{"bottom"} + if not left.auto: + box.offset.x += right.px(parent.viewport) + elif not right.auto: + box.offset.x += parent.width - right.px(parent.viewport) - box.width + if not top.auto: + box.offset.y += top.px(parent.viewport) + elif not top.auto: + box.offset.y -= parent.height - bottom.px(parent.viewport) - box.height + +proc positionBlocks(box: BlockBox) = var y = 0 var x = 0 var margin_todo: Strut - y += bctx.padding_top - bctx.height += bctx.padding_top + y += box.padding_top + box.height += box.padding_top - x += bctx.padding_left - if bctx.computed{"text-align"} == TEXT_ALIGN_CHA_CENTER: - x += bctx.compwidth div 2 + x += box.padding_left + if box.computed{"text-align"} == TEXT_ALIGN_CHA_CENTER: + x += box.compwidth div 2 template apply_child(child: BlockBox) = child.offset.y = y child.offset.x = x + child.margin_left - if bctx.computed{"text-align"} == TEXT_ALIGN_CHA_CENTER: + if box.computed{"text-align"} == TEXT_ALIGN_CHA_CENTER: child.offset.x -= child.width div 2 + if box.computed{"position"} == POSITION_RELATIVE: + box.positionRelative(child) y += child.height - bctx.height += child.height - bctx.width = max(bctx.width, child.width) + box.height += child.height + box.width = max(box.width, child.width) margin_todo = Strut() margin_todo.append(child.margin_bottom) - if bctx.nested.len > 0: - let child = bctx.nested[0] + var i = 0 - margin_todo.append(bctx.margin_top) + template position_out_of_flow() = + # Skip absolute, fixed, sticky + while i < box.nested.len: + case box.nested[i].computed{"position"} + of POSITION_STATIC, POSITION_RELATIVE: + break + of POSITION_ABSOLUTE: + positionAbsolute(box.nested[i]) + of POSITION_FIXED: + box.positionFixed(box.nested[i]) + of POSITION_STICKY: + #TODO implement this once relayouting every scroll isn't too expensive + break + box.nested.delete(i) + + position_out_of_flow + + if i < box.nested.len: + let child = box.nested[i] + + margin_todo.append(box.margin_top) margin_todo.append(child.margin_top) - bctx.margin_top = margin_todo.sum() + box.margin_top = margin_todo.sum() apply_child(child) + inc i + + while true: + position_out_of_flow - var i = 1 - while i < bctx.nested.len: - let child = bctx.nested[i] + if i >= box.nested.len: + break + + let child = box.nested[i] margin_todo.append(child.margin_top) y += margin_todo.sum() - bctx.height += margin_todo.sum() + box.height += margin_todo.sum() apply_child(child) inc i - margin_todo.append(bctx.margin_bottom) - bctx.margin_bottom = margin_todo.sum() + margin_todo.append(box.margin_bottom) + box.margin_bottom = margin_todo.sum() - bctx.height += bctx.padding_bottom + box.height += box.padding_bottom - if bctx.compheight.issome: - bctx.height = bctx.compheight.get + if box.compheight.issome: + box.height = box.compheight.get - bctx.width += bctx.padding_left - bctx.width += bctx.padding_right + box.width += box.padding_left + box.width += box.padding_right proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox, cellwidth = none(int)): BlockBox = result = parent.newTableCellBox(box) @@ -746,16 +825,16 @@ proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox = table.width = max(row.width, table.width) return table -proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) = +proc buildBlocks(parent: 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 = buildTable(TableBoxBuilder(child), bctx) + of DISPLAY_BLOCK: cblock = buildBlock(BlockBoxBuilder(child), parent) + of DISPLAY_LIST_ITEM: cblock = buildListItem(ListItemBoxBuilder(child), parent) + of DISPLAY_TABLE: cblock = buildTable(TableBoxBuilder(child), parent) else: assert false, "child.t is " & $child.computed{"display"} - bctx.nested.add(cblock) - bctx.positionBlocks() + parent.nested.add(cblock) + parent.positionBlocks() # Build a block box inside another block box, based on a builder. proc buildBlock(box: BlockBoxBuilder, parent: BlockBox, maxwidth = none(int)): BlockBox = @@ -767,13 +846,14 @@ proc buildBlock(box: BlockBoxBuilder, parent: BlockBox, maxwidth = none(int)): B result.buildBlockLayout(box.children, box.node) # Establish a new flow-root context and build a block box. -proc buildRootBlock(box: BlockBoxBuilder, viewport: Viewport): BlockBox = - result = viewport.newBlockBox(box) - result.shrink = false - if box.inlinelayout: - result.buildInlineLayout(box.children) +proc buildRootBlock(viewport: Viewport, builder: BlockBoxBuilder) = + let box = viewport.newBlockBox(builder) + box.shrink = false + viewport.root.add(box) + if builder.inlinelayout: + box.buildInlineLayout(builder.children) else: - result.buildBlockLayout(box.children, box.node) + box.buildBlockLayout(builder.children, builder.node) # Generation phase @@ -1153,4 +1233,4 @@ proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuild proc renderLayout*(viewport: var Viewport, document: Document, root: StyledNode) = let builder = root.generateBlockBox(viewport) - viewport.root = buildRootBlock(builder, viewport) + viewport.buildRootBlock(builder) diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim index 9eebe61d..158773f9 100644 --- a/src/render/renderdocument.nim +++ b/src/render/renderdocument.nim @@ -253,7 +253,7 @@ proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int, for atom in line.atoms: if atom of InlineBlockBox: let iblock = InlineBlockBox(atom) - grid.renderBlockContext(iblock.bctx, x + iblock.offset.x, y + iblock.offset.y, window) + grid.renderBlockContext(iblock.innerbox, x + iblock.offset.x, y + iblock.offset.y, window) elif atom of InlineWord: let word = InlineWord(atom) grid.setRowWord(word, x, y, window) @@ -297,6 +297,7 @@ proc renderDocument*(document: Document, window: WindowAttributes, userstyle: CS result[1] = styledNode layout.renderLayout(document, styledNode) result[0].setLen(0) - result[0].renderBlockContext(layout.root, 0, 0, window) + for root in layout.root: + result[0].renderBlockContext(root, 0, 0, window) if result[0].len == 0: result[0].addLine() |