diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-16 00:44:01 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-16 00:44:01 +0100 |
commit | cd83ed439db510e5236be23006763aaa6f184b5d (patch) | |
tree | 6a5ae37eb98b09fe384b2f7ce68431ed6d3b2f9d /src/layout | |
parent | e0435743807c6f0c3b1d04cc89089c0528c9b33b (diff) | |
download | chawan-cd83ed439db510e5236be23006763aaa6f184b5d.tar.gz |
layout/engine: fix a <br> bug that ate inline boxes, add broken min-width/max-width
min-width, max-width, min-height, max-height are mostly broken, because they aren't enforced on inline level. Though really the whole size calculation mechanism needs to be refactored, its current state is horrible.
Diffstat (limited to 'src/layout')
-rw-r--r-- | src/layout/box.nim | 6 | ||||
-rw-r--r-- | src/layout/engine.nim | 60 |
2 files changed, 55 insertions, 11 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim index c79c52e1..e770c7ec 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -116,7 +116,11 @@ type width*: int height*: int - minwidth*: int + max_width*: Option[int] + max_height*: Option[int] + min_width*: Option[int] + min_height*: Option[int] + xminwidth*: int margin_top*: int margin_bottom*: int margin_left*: int diff --git a/src/layout/engine.nim b/src/layout/engine.nim index a122b7fa..ee66a7da 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -222,7 +222,7 @@ proc finish(ictx: InlineContext, computed: CSSComputedValues, maxwidth: int) = func minwidth(atom: InlineAtom): int = if atom of InlineBlockBox: - return cast[InlineBlockBox](atom).innerbox.minwidth + return cast[InlineBlockBox](atom).innerbox.xminwidth return atom.width # pcomputed: computed values of parent, for white-space: pre, line-height @@ -333,6 +333,10 @@ type PreferredDimensions = object padding_right: int padding_top: int padding_bottom: int + max_width: Option[int] + max_height: Option[int] + min_width: Option[int] + min_height: Option[int] proc preferredDimensions(computed: CSSComputedValues, viewport: Viewport, width: int, height: Option[int]): PreferredDimensions = let pwidth = computed{"width"} @@ -341,6 +345,22 @@ proc preferredDimensions(computed: CSSComputedValues, viewport: Viewport, width: else: result.compwidth = pwidth.px(viewport, width) + if not computed{"max-width"}.auto: + result.max_width = some(computed{"max-width"}.px(viewport, width)) + if not computed{"max-height"}.auto: + if computed{"max-height"}.unit != UNIT_PERC: + result.max_height = computed{"max-height"}.px(viewport).some + elif height.issome: + result.max_height = computed{"max-height"}.px(viewport, height.get).some + + if not computed{"min-width"}.auto: + result.min_width = some(computed{"min-width"}.px(viewport, width)) + if not computed{"min-height"}.auto: + if computed{"min-height"}.unit != UNIT_PERC: + result.compheight = computed{"min-height"}.px(viewport).some + elif height.issome: + result.compheight = computed{"min-height"}.px(viewport, height.get).some + result.margin_top = computed{"margin-top"}.px(viewport, width) result.margin_bottom = computed{"margin-top"}.px(viewport, width) result.margin_left = computed{"margin-left"}.px(viewport, width) @@ -377,6 +397,10 @@ proc setPreferredDimensions(box: BlockBox, width: int, height: Option[int]) = box.margin_bottom = preferred.margin_bottom box.margin_left = preferred.margin_left box.margin_right = preferred.margin_right + box.max_width = preferred.max_width + box.max_height = preferred.max_height + box.min_width = preferred.min_width + box.min_height = preferred.min_height proc newBlockBox_common2(box: BlockBox, parent: BlockBox, builder: BoxBuilder) {.inline.} = box.viewport = parent.viewport @@ -388,12 +412,12 @@ proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, paren result.viewport = viewport result.computed = box.computed result.setPreferredDimensions(parentWidth, parentHeight) - result.shrink = result.computed{"width"}.auto and shrink + result.shrink = result.computed{"width"}.auto and shrink or result.computed{"position"} == POSITION_ABSOLUTE proc newBlockBox(parent: BlockBox, box: BoxBuilder): BlockBox = new(result) result.newBlockBox_common2(parent, box) - result.shrink = result.computed{"width"}.auto and parent.shrink + result.shrink = result.computed{"width"}.auto and parent.shrink or result.computed{"position"} == POSITION_ABSOLUTE proc newListItem(parent: BlockBox, builder: ListItemBoxBuilder): ListItemBox = new(result) @@ -424,7 +448,7 @@ proc positionInlines(parent: BlockBox) = parent.width += parent.padding_right - parent.minwidth = max(parent.minwidth, parent.inline.minwidth) + parent.xminwidth = max(parent.xminwidth, parent.inline.minwidth) if parent.computed{"width"}.auto: if parent.shrink: @@ -433,6 +457,14 @@ proc positionInlines(parent: BlockBox) = parent.width = max(parent.width, parent.compwidth) else: parent.width = parent.compwidth + if parent.max_width.isSome and parent.max_width.get < parent.width: + parent.width = parent.max_width.get + if parent.min_width.isSome and parent.width < parent.min_width.get: + parent.width = parent.min_width.get + if parent.max_height.isSome and parent.max_height.get < parent.height: + parent.height = parent.max_height.get + if parent.min_height.isSome and parent.height < parent.min_height.get: + parent.height = parent.min_height.get proc buildBlock(box: BlockBoxBuilder, parent: BlockBox): BlockBox proc buildInlines(parent: BlockBox, inlines: seq[BoxBuilder]): InlineContext @@ -639,13 +671,13 @@ proc positionFixed(box: BlockBox, last: BlockBox = box.viewport.root[0]) = 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 += last.compwidth - 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 += last.compheight.get(box.viewport.window.height_px) - bottom.px(box.viewport, box.compheight.get(0)) - box.height box.offset.y -= box.margin_bottom box.viewport.root.add(box) @@ -718,7 +750,7 @@ proc positionBlocks(box: BlockBox) = y += child.height box.height += child.height box.width = max(box.width, child.width) - box.minwidth = max(box.minwidth, child.minwidth) + box.xminwidth = max(box.xminwidth, child.xminwidth) margin_todo = Strut() margin_todo.append(child.margin_bottom) @@ -776,6 +808,14 @@ proc positionBlocks(box: BlockBox) = box.width += box.padding_left box.width += box.padding_right + if box.max_width.isSome and box.max_width.get < box.width: + box.width = box.max_width.get + if box.min_width.isSome and box.width < box.min_width.get: + box.width = box.min_width.get + if box.max_height.isSome and box.max_height.get < box.height: + box.height = box.max_height.get + if box.min_height.isSome and box.height < box.min_height.get: + box.height = box.min_height.get proc buildTableCaption(viewport: Viewport, box: TableCaptionBoxBuilder, maxwidth: int, maxheight: Option[int], shrink = false): BlockBox = result = viewport.newFlowRootBox(box, maxwidth, maxheight, shrink) @@ -805,7 +845,7 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B pctx.cols.setLen(n + cellbuilder.colspan) if ctx.reflow.len < n + cellbuilder.colspan: ctx.reflow.setLen(n + cellbuilder.colspan) - let minw = cell.minwidth div cellbuilder.colspan + let minw = cell.xminwidth div cellbuilder.colspan let w = cell.width div cellbuilder.colspan for i in n ..< n + cellbuilder.colspan: ctx.width += pctx.inlinespacing @@ -1066,8 +1106,7 @@ proc buildBlock(box: BlockBoxBuilder, parent: BlockBox): BlockBox = # Establish a new flow-root context and build a block box. proc buildRootBlock(viewport: Viewport, builder: BlockBoxBuilder) = - let box = viewport.newFlowRootBox(builder, viewport.window.width_px) - #box.shrink = false + let box = viewport.newFlowRootBox(builder, viewport.window.width_px, shrink = false) viewport.root.add(box) if builder.inlinelayout: box.buildInlineLayout(builder.children) @@ -1229,6 +1268,7 @@ proc generateFromElem(ctx: var InnerBlockContext, styledNode: StyledNode) = if styledNode.node != nil: let elem = Element(styledNode.node) if elem.tagType == TAG_BR: + ctx.iflush() ctx.ibox = box.getTextBox() ctx.ibox.newline = true ctx.iflush() |