From 510f1b4040d9b7f43d5cbd90a29e0dd7034624f9 Mon Sep 17 00:00:00 2001 From: bptato Date: Fri, 12 Nov 2021 21:21:26 +0100 Subject: Rename layout.nim --- src/layout/engine.nim | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/layout/layout.nim | 204 -------------------------------------------------- src/main.nim | 2 +- 3 files changed, 205 insertions(+), 205 deletions(-) create mode 100644 src/layout/engine.nim delete mode 100644 src/layout/layout.nim diff --git a/src/layout/engine.nim b/src/layout/engine.nim new file mode 100644 index 00000000..a74f58c7 --- /dev/null +++ b/src/layout/engine.nim @@ -0,0 +1,204 @@ +import unicode +import options + +import layout/box +import types/enums +import html/dom +import css/style +import io/buffer +import utils/twtstr + +func newContext*(box: CSSBox): InlineContext = + new(result) + result.fromx = box.x + result.whitespace = true + +func newBlockBox*(parent: CSSBox, vals: CSSComputedValues): CSSBlockBox = + new(result) + result.bcontext = parent.bcontext #TODO statify + result.x = parent.x + if parent.context.conty: + inc parent.height + eprint "inc n" + inc parent.context.fromy + parent.context.conty = false + result.y = parent.context.fromy + let mtop = vals[RULE_MARGIN_TOP].length.cells() + if mtop > parent.bcontext.marginy: + result.y += mtop - parent.bcontext.marginy + eprint "my", mtop, parent.bcontext.marginy + parent.bcontext.marginy = mtop + + result.width = parent.width + result.context = newContext(parent) + eprint "inc to", result.y + result.context.fromy = result.y + result.cssvalues = vals + +func newInlineBox*(parent: CSSBox, vals: CSSComputedValues): CSSInlineBox = + assert parent != nil + new(result) + result.x = parent.x + result.y = parent.context.fromy + + result.width = parent.width + result.context = parent.context + result.bcontext = parent.bcontext + result.cssvalues = vals + if result.context == nil: + result.context = newContext(parent) + +#TODO there should be actual inline contexts to store these stuff +proc setup(rowbox: var CSSRowBox, cssvalues: CSSComputedValues) = + rowbox.color = cssvalues[RULE_COLOR].color + rowbox.fontstyle = cssvalues[RULE_FONT_STYLE].fontstyle + rowbox.fontweight = cssvalues[RULE_FONT_WEIGHT].integer + +proc inlineWrap(ibox: var CSSInlineBox, rowi: var int, fromx: var int, rowbox: var CSSRowBox) = + ibox.content.add(rowbox) + inc rowi + fromx = ibox.x + ibox.context.whitespace = true + ibox.context.conty = true + rowbox = CSSRowBox(x: ibox.x, y: ibox.y + rowi) + rowbox.setup(ibox.cssvalues) + +#TODO statify +proc processInlineBox(parent: CSSBox, str: string): CSSBox = + var ibox: CSSInlineBox + var use_parent = false + if parent of CSSInlineBox: + ibox = CSSInlineBox(parent) + use_parent = true + else: + ibox = newInlineBox(parent, parent.cssvalues) + + if str.len == 0: + return + + var i = 0 + var rowi = 0 + var fromx = ibox.context.fromx + var rowbox = CSSRowBox(x: fromx, y: ibox.context.fromy) + rowbox.setup(ibox.cssvalues) + var r: Rune + while i < str.len: + fastRuneAt(str, i, r) + if rowbox.width + r.width() > ibox.width: + inlineWrap(ibox, rowi, fromx, rowbox) + if r.isWhitespace(): + if ibox.context.whitespace: + continue + else: + let wsr = ibox.cssvalues[RULE_WHITESPACE].whitespace + + case wsr + of WHITESPACE_NORMAL, WHITESPACE_NOWRAP: + r = Rune(' ') + of WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP: + if r == Rune('\n'): + inlineWrap(ibox, rowi, fromx, rowbox) + ibox.context.whitespace = false + continue + + case wsr + of WHITESPACE_NORMAL, WHITESPACE_NOWRAP, WHITESPACE_PRE_LINE: + ibox.context.whitespace = true + else: + ibox.context.whitespace = false + else: + ibox.context.whitespace = false + rowbox.width += r.width() + rowbox.runes.add(r) + if rowbox.runes.len > 0: + ibox.content.add(rowbox) + ibox.context.fromx = fromx + rowbox.width + ibox.context.conty = true + + ibox.height += rowi + eprint "inc i", rowi, rowbox.runes + if rowi > 0 or rowbox.width > 0: + parent.bcontext.marginy = 0 + ibox.context.fromy += rowi + if use_parent: + return nil + return ibox + +proc processElemBox(parent: CSSBox, elem: Element): CSSBox = + case elem.cssvalues[RULE_DISPLAY].display + of DISPLAY_BLOCK: + eprint "START", elem.tagType + result = newBlockBox(parent, elem.cssvalues) + CSSBlockBox(result).tag = $elem.tagType + of DISPLAY_INLINE: + result = newInlineBox(parent, elem.cssvalues) + of DISPLAY_NONE: + return nil + else: + return nil + +proc add(parent: var CSSBox, box: CSSBox) = + if box == nil: + return + if box of CSSBlockBox: + parent.context.fromx = 0 + parent.context.whitespace = true + if box.context.conty: + inc box.height + eprint "inc a" + inc box.context.fromy + box.context.conty = false + let mbot = box.cssvalues[RULE_MARGIN_BOTTOM].length.cells() + eprint "inc b", mbot + box.context.fromy += mbot + box.bcontext.marginy = mbot + eprint "END", CSSBlockBox(box).tag + parent.height += box.height + eprint "parent to", box.context.fromy + parent.context.fromy = box.context.fromy + parent.children.add(box) + +proc processPseudoBox(parent: CSSBox, cssvalues: CSSComputedValues): CSSBox = + case cssvalues[RULE_DISPLAY].display + of DISPLAY_BLOCK: + result = newBlockBox(parent, cssvalues) + result.add(processInlineBox(parent, $cssvalues[RULE_CONTENT].content)) + of DISPLAY_INLINE: + result = processInlineBox(parent, $cssvalues[RULE_CONTENT].content) + of DISPLAY_NONE: + return nil + else: + return nil + +proc processNode(parent: CSSBox, node: Node): CSSBox = + case node.nodeType + of ELEMENT_NODE: + let elem = Element(node) + + result = processElemBox(parent, elem) + if result == nil: + return + + if elem.cssvalues_before.isSome: + let bbox = processPseudoBox(parent, elem.cssvalues_before.get) + if bbox != nil: + result.add(bbox) + + for child in elem.childNodes: + result.add(processNode(result, child)) + + if elem.cssvalues_after.isSome: + let abox = processPseudoBox(parent, elem.cssvalues_after.get) + if abox != nil: + result.add(abox) + of TEXT_NODE: + let text = Text(node) + return processInlineBox(parent, text.data) + else: discard + +proc alignBoxes*(buffer: Buffer) = + buffer.rootbox = CSSBlockBox(x: 0, y: 0, width: buffer.width, height: 0) + buffer.rootbox.context = newContext(buffer.rootbox) + buffer.rootbox.bcontext = new(BlockContext) + for child in buffer.document.root.childNodes: + buffer.rootbox.add(processNode(buffer.rootbox, child)) diff --git a/src/layout/layout.nim b/src/layout/layout.nim deleted file mode 100644 index a74f58c7..00000000 --- a/src/layout/layout.nim +++ /dev/null @@ -1,204 +0,0 @@ -import unicode -import options - -import layout/box -import types/enums -import html/dom -import css/style -import io/buffer -import utils/twtstr - -func newContext*(box: CSSBox): InlineContext = - new(result) - result.fromx = box.x - result.whitespace = true - -func newBlockBox*(parent: CSSBox, vals: CSSComputedValues): CSSBlockBox = - new(result) - result.bcontext = parent.bcontext #TODO statify - result.x = parent.x - if parent.context.conty: - inc parent.height - eprint "inc n" - inc parent.context.fromy - parent.context.conty = false - result.y = parent.context.fromy - let mtop = vals[RULE_MARGIN_TOP].length.cells() - if mtop > parent.bcontext.marginy: - result.y += mtop - parent.bcontext.marginy - eprint "my", mtop, parent.bcontext.marginy - parent.bcontext.marginy = mtop - - result.width = parent.width - result.context = newContext(parent) - eprint "inc to", result.y - result.context.fromy = result.y - result.cssvalues = vals - -func newInlineBox*(parent: CSSBox, vals: CSSComputedValues): CSSInlineBox = - assert parent != nil - new(result) - result.x = parent.x - result.y = parent.context.fromy - - result.width = parent.width - result.context = parent.context - result.bcontext = parent.bcontext - result.cssvalues = vals - if result.context == nil: - result.context = newContext(parent) - -#TODO there should be actual inline contexts to store these stuff -proc setup(rowbox: var CSSRowBox, cssvalues: CSSComputedValues) = - rowbox.color = cssvalues[RULE_COLOR].color - rowbox.fontstyle = cssvalues[RULE_FONT_STYLE].fontstyle - rowbox.fontweight = cssvalues[RULE_FONT_WEIGHT].integer - -proc inlineWrap(ibox: var CSSInlineBox, rowi: var int, fromx: var int, rowbox: var CSSRowBox) = - ibox.content.add(rowbox) - inc rowi - fromx = ibox.x - ibox.context.whitespace = true - ibox.context.conty = true - rowbox = CSSRowBox(x: ibox.x, y: ibox.y + rowi) - rowbox.setup(ibox.cssvalues) - -#TODO statify -proc processInlineBox(parent: CSSBox, str: string): CSSBox = - var ibox: CSSInlineBox - var use_parent = false - if parent of CSSInlineBox: - ibox = CSSInlineBox(parent) - use_parent = true - else: - ibox = newInlineBox(parent, parent.cssvalues) - - if str.len == 0: - return - - var i = 0 - var rowi = 0 - var fromx = ibox.context.fromx - var rowbox = CSSRowBox(x: fromx, y: ibox.context.fromy) - rowbox.setup(ibox.cssvalues) - var r: Rune - while i < str.len: - fastRuneAt(str, i, r) - if rowbox.width + r.width() > ibox.width: - inlineWrap(ibox, rowi, fromx, rowbox) - if r.isWhitespace(): - if ibox.context.whitespace: - continue - else: - let wsr = ibox.cssvalues[RULE_WHITESPACE].whitespace - - case wsr - of WHITESPACE_NORMAL, WHITESPACE_NOWRAP: - r = Rune(' ') - of WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP: - if r == Rune('\n'): - inlineWrap(ibox, rowi, fromx, rowbox) - ibox.context.whitespace = false - continue - - case wsr - of WHITESPACE_NORMAL, WHITESPACE_NOWRAP, WHITESPACE_PRE_LINE: - ibox.context.whitespace = true - else: - ibox.context.whitespace = false - else: - ibox.context.whitespace = false - rowbox.width += r.width() - rowbox.runes.add(r) - if rowbox.runes.len > 0: - ibox.content.add(rowbox) - ibox.context.fromx = fromx + rowbox.width - ibox.context.conty = true - - ibox.height += rowi - eprint "inc i", rowi, rowbox.runes - if rowi > 0 or rowbox.width > 0: - parent.bcontext.marginy = 0 - ibox.context.fromy += rowi - if use_parent: - return nil - return ibox - -proc processElemBox(parent: CSSBox, elem: Element): CSSBox = - case elem.cssvalues[RULE_DISPLAY].display - of DISPLAY_BLOCK: - eprint "START", elem.tagType - result = newBlockBox(parent, elem.cssvalues) - CSSBlockBox(result).tag = $elem.tagType - of DISPLAY_INLINE: - result = newInlineBox(parent, elem.cssvalues) - of DISPLAY_NONE: - return nil - else: - return nil - -proc add(parent: var CSSBox, box: CSSBox) = - if box == nil: - return - if box of CSSBlockBox: - parent.context.fromx = 0 - parent.context.whitespace = true - if box.context.conty: - inc box.height - eprint "inc a" - inc box.context.fromy - box.context.conty = false - let mbot = box.cssvalues[RULE_MARGIN_BOTTOM].length.cells() - eprint "inc b", mbot - box.context.fromy += mbot - box.bcontext.marginy = mbot - eprint "END", CSSBlockBox(box).tag - parent.height += box.height - eprint "parent to", box.context.fromy - parent.context.fromy = box.context.fromy - parent.children.add(box) - -proc processPseudoBox(parent: CSSBox, cssvalues: CSSComputedValues): CSSBox = - case cssvalues[RULE_DISPLAY].display - of DISPLAY_BLOCK: - result = newBlockBox(parent, cssvalues) - result.add(processInlineBox(parent, $cssvalues[RULE_CONTENT].content)) - of DISPLAY_INLINE: - result = processInlineBox(parent, $cssvalues[RULE_CONTENT].content) - of DISPLAY_NONE: - return nil - else: - return nil - -proc processNode(parent: CSSBox, node: Node): CSSBox = - case node.nodeType - of ELEMENT_NODE: - let elem = Element(node) - - result = processElemBox(parent, elem) - if result == nil: - return - - if elem.cssvalues_before.isSome: - let bbox = processPseudoBox(parent, elem.cssvalues_before.get) - if bbox != nil: - result.add(bbox) - - for child in elem.childNodes: - result.add(processNode(result, child)) - - if elem.cssvalues_after.isSome: - let abox = processPseudoBox(parent, elem.cssvalues_after.get) - if abox != nil: - result.add(abox) - of TEXT_NODE: - let text = Text(node) - return processInlineBox(parent, text.data) - else: discard - -proc alignBoxes*(buffer: Buffer) = - buffer.rootbox = CSSBlockBox(x: 0, y: 0, width: buffer.width, height: 0) - buffer.rootbox.context = newContext(buffer.rootbox) - buffer.rootbox.bcontext = new(BlockContext) - for child in buffer.document.root.childNodes: - buffer.rootbox.add(processNode(buffer.rootbox, child)) diff --git a/src/main.nim b/src/main.nim index c208375a..15cb5578 100644 --- a/src/main.nim +++ b/src/main.nim @@ -6,7 +6,7 @@ import terminal import html/parser import html/dom -import layout/layout +import layout/engine import io/buffer import io/term import config/config -- cgit 1.4.1-2-gfad0