diff options
author | bptato <nincsnevem662@gmail.com> | 2022-01-26 22:15:00 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-01-26 22:16:15 +0100 |
commit | 876f5e9c64992ffef8630cd2bafa8c5ba9431f01 (patch) | |
tree | 33f318fd1f7f5371d08182a3c99536906f380a37 | |
parent | 402f7595b6c63e668ae09c040410bfa13de5b588 (diff) | |
download | chawan-876f5e9c64992ffef8630cd2bafa8c5ba9431f01.tar.gz |
Implement padding
-rw-r--r-- | src/io/buffer.nim | 36 | ||||
-rw-r--r-- | src/io/cell.nim | 118 | ||||
-rw-r--r-- | src/layout/box.nim | 20 | ||||
-rw-r--r-- | src/layout/engine.nim | 102 | ||||
-rw-r--r-- | src/render/renderdocument.nim | 46 | ||||
-rw-r--r-- | src/render/rendertext.nim | 4 |
6 files changed, 199 insertions, 127 deletions
diff --git a/src/io/buffer.nim b/src/io/buffer.nim index 0b8d09a4..6663458f 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -65,7 +65,7 @@ proc newBuffer*(): Buffer = func generateFullOutput(buffer: Buffer): string = var x = 0 var w = 0 - var formatting = newFormatting() + var format = newFormat() result &= HVP(1, 1) for cell in buffer.display: @@ -75,7 +75,7 @@ func generateFullOutput(buffer: Buffer): string = x = 0 w = 0 - result &= formatting.processFormatting(cell.formatting) + result &= format.processFormat(cell.format) result &= $cell.runes w += cell.width() @@ -88,7 +88,7 @@ func generateFullOutput(buffer: Buffer): string = # current one. ideally should be used when small changes are made (e.g. hover # changes underlining) func generateSwapOutput(buffer: Buffer): string = - var formatting = newFormatting() + var format = newFormat() let curr = buffer.display let prev = buffer.prevdisplay var i = 0 @@ -107,7 +107,7 @@ func generateSwapOutput(buffer: Buffer): string = inc y line = "" lr = lr or (curr[i] != prev[i]) - line &= formatting.processFormatting(curr[i].formatting) + line &= format.processFormat(curr[i].format) line &= $curr[i].runes inc i inc x @@ -140,7 +140,7 @@ func generateSwapOutput(buffer: Buffer): string = # cx = x # cy = y - # text &= formatting.processFormatting(curr[i].formatting) + # text &= format.processFormat(curr[i].format) # text &= $curr[i].runes # if currwidth < prevwidth: @@ -157,10 +157,10 @@ func generateSwapOutput(buffer: Buffer): string = # result &= $text func generateStatusMessage*(buffer: Buffer): string = - var formatting = newFormatting() + var format = newFormat() var w = 0 for cell in buffer.statusmsg: - result &= formatting.processFormatting(cell.formatting) + result &= format.processFormat(cell.format) result &= $cell.runes w += cell.width() if w < buffer.width: @@ -309,7 +309,7 @@ proc refreshDisplay(buffer: Buffer) = nf = line.findNextFormat(j) buffer.display[dls + k].runes.add(r) if cf.pos != -1: - buffer.display[dls + k].formatting = cf.formatting + buffer.display[dls + k].format = cf.format buffer.display[dls + k].node = cf.node let tk = k + r.width() while k < tk and k < buffer.width - 1: @@ -763,7 +763,7 @@ proc cursorBufferPos(buffer: Buffer) = proc clearStatusMessage(buffer: Buffer) = buffer.statusmsg = newFixedGrid(buffer.width) -proc writeStatusMessage(buffer: Buffer, str: string, formatting: Formatting = Formatting()) = +proc writeStatusMessage(buffer: Buffer, str: string, format: Format = Format()) = buffer.clearStatusMessage() var i = 0 for r in str.runes: @@ -773,16 +773,16 @@ proc writeStatusMessage(buffer: Buffer, str: string, formatting: Formatting = Fo buffer.statusmsg[^1].runes.add(Rune('$')) break buffer.statusmsg[i].runes.add(r) - buffer.statusmsg[i].formatting = formatting + buffer.statusmsg[i].format = format proc statusMsgForBuffer(buffer: Buffer) = var msg = $(buffer.cursory + 1) & "/" & $buffer.numLines & " (" & $buffer.atPercentOf() & "%) " & "<" & buffer.title & ">" if buffer.hovertext.len > 0: msg &= " " & buffer.hovertext - var formatting: Formatting - formatting.reverse = true - buffer.writeStatusMessage(msg, formatting) + var format: Format + format.reverse = true + buffer.writeStatusMessage(msg, format) proc setStatusMessage*(buffer: Buffer, str: string) = buffer.writeStatusMessage(str) @@ -811,16 +811,16 @@ proc click*(buffer: Buffer): string = return "" proc drawBuffer*(buffer: Buffer) = - var formatting = newFormatting() + var format = newFormat() for line in buffer.lines: if line.formats.len == 0: print(line.str & '\n') else: var x = 0 - for format in line.formats: - print(line.str.substr(x, format.pos - 1)) - print(formatting.processFormatting(format.formatting)) - x = format.pos + for f in line.formats: + print(line.str.substr(x, f.pos - 1)) + print(format.processFormat(f.format)) + x = f.pos print(line.str.substr(x, line.str.len) & '\n') proc refreshBuffer*(buffer: Buffer) = diff --git a/src/io/cell.nim b/src/io/cell.nim index b783d180..7009a12a 100644 --- a/src/io/cell.nim +++ b/src/io/cell.nim @@ -5,6 +5,7 @@ import sugar import unicode import html/dom +import layout/box import types/color import utils/twtstr @@ -17,21 +18,22 @@ type FLAG_STRIKE FLAG_OVERLINE - Formatting* = object + Format* = object fgcolor*: CellColor bgcolor*: CellColor flags: set[FormatFlags] Cell* = object of RootObj - formatting*: Formatting + format*: Format node*: Node - FormattingCell* = object of Cell + FormatCell* = object of Cell pos*: int + computed*: ComputedFormat FlexibleLine* = object str*: string - formats*: seq[FormattingCell] + formats*: seq[FormatCell] FlexibleGrid* = seq[FlexibleLine] @@ -49,20 +51,20 @@ const FormatCodes: array[FormatFlags, tuple[s: int, e: int]] = [ FLAG_OVERLINE: (53, 55), ] -template flag_template(formatting: Formatting, val: bool, flag: FormatFlags) = - if val: formatting.flags.incl(flag) - else: formatting.flags.excl(flag) +template flag_template(format: Format, val: bool, flag: FormatFlags) = + if val: format.flags.incl(flag) + else: format.flags.excl(flag) -template `italic=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_ITALIC -template `bold=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_BOLD -template `underline=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_UNDERLINE -template `reverse=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_REVERSE -template `strike=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_STRIKE -template `overline=`*(f: var Formatting, b: bool) = flag_template f, b, FLAG_OVERLINE +template `italic=`*(f: var Format, b: bool) = flag_template f, b, FLAG_ITALIC +template `bold=`*(f: var Format, b: bool) = flag_template f, b, FLAG_BOLD +template `underline=`*(f: var Format, b: bool) = flag_template f, b, FLAG_UNDERLINE +template `reverse=`*(f: var Format, b: bool) = flag_template f, b, FLAG_REVERSE +template `strike=`*(f: var Format, b: bool) = flag_template f, b, FLAG_STRIKE +template `overline=`*(f: var Format, b: bool) = flag_template f, b, FLAG_OVERLINE #TODO ????? func `==`*(a: FixedCell, b: FixedCell): bool = - return a.formatting == b.formatting and + return a.format == b.format and a.runes == b.runes and a.node == b.node @@ -75,8 +77,8 @@ func width*(line: FlexibleLine): int = func width*(cell: FixedCell): int = return cell.runes.width() -func newFormatting*(): Formatting = - return Formatting(fgcolor: defaultColor, bgcolor: defaultColor) +func newFormat*(): Format = + return Format(fgcolor: defaultColor, bgcolor: defaultColor) func findFormatN*(line: FlexibleLine, pos: int): int = var i = 0 @@ -86,21 +88,21 @@ func findFormatN*(line: FlexibleLine, pos: int): int = inc i return i -func findFormat*(line: FlexibleLine, pos: int): FormattingCell = +func findFormat*(line: FlexibleLine, pos: int): FormatCell = let i = line.findFormatN(pos) - 1 if i != -1: result = line.formats[i] else: result.pos = -1 -func findNextFormat*(line: FlexibleLine, pos: int): FormattingCell = +func findNextFormat*(line: FlexibleLine, pos: int): FormatCell = let i = line.findFormatN(pos) if i < line.formats.len: result = line.formats[i] else: result.pos = -1 -func subformats*(formats: seq[FormattingCell], pos: int): seq[FormattingCell] = +func subformats*(formats: seq[FormatCell], pos: int): seq[FormatCell] = var i = 0 while i < formats.len: if formats[i].pos >= pos: @@ -128,20 +130,18 @@ proc setLen*(line: var FlexibleLine, len: int) = proc add*(a: var FlexibleLine, b: FlexibleLine) = let l = a.str.len - a.formats.add(b.formats.map((x) => FormattingCell(formatting: x.formatting, node: x.node, pos: l + x.pos))) + a.formats.add(b.formats.map((x) => FormatCell(format: x.format, node: x.node, pos: l + x.pos))) a.str &= b.str proc addLine*(grid: var FlexibleGrid) = grid.add(FlexibleLine()) -proc addFormat*(line: var FlexibleLine, pos: int, format: Formatting) = - line.formats.add(FormattingCell(formatting: format, pos: line.str.len)) +proc addFormat*(line: var FlexibleLine, pos: int, format: Format) = + line.formats.add(FormatCell(format: format, pos: line.str.len)) -proc addFormat*(grid: var FlexibleGrid, y, pos: int, format: Formatting) = - grid[y].formats.add(FormattingCell(formatting: format, pos: grid[y].str.len)) - -proc addFormat*(grid: var FlexibleGrid, y, pos: int, format: Formatting, node: Node) = - grid[y].formats.add(FormattingCell(formatting: format, node: node, pos: pos)) +proc addFormat*(grid: var FlexibleGrid, y, pos: int, format: Format, computed: ComputedFormat = nil, node: Node = nil) = + if computed == nil or grid[y].formats.len == 0 or grid[y].formats[^1].computed != computed: + grid[y].formats.add(FormatCell(format: format, node: node, computed: computed, pos: pos)) proc addCell*(grid: var FlexibleGrid, y: int, r: Rune) = grid[y].str &= $r @@ -154,11 +154,11 @@ template inc_check(i: int) = if i >= buf.len: return i -proc handleAnsiCode(formatting: var Formatting, final: char, params: string) = +proc handleAnsiCode(format: var Format, final: char, params: string) = case final of 'm': if params.len == 0: - formatting = newFormatting() + format = newFormat() else: let sparams = params.split(';') try: @@ -167,17 +167,17 @@ proc handleAnsiCode(formatting: var Formatting, final: char, params: string) = while pi < ip.len: case ip[pi] of 0: - formatting = newFormatting() - of 1: formatting.bold = true - of 3: formatting.italic = true - of 4: formatting.underline = true - of 7: formatting.reverse = true - of 9: formatting.strike = true - of 22: formatting.bold = false - of 23: formatting.italic = false - of 27: formatting.reverse = false - of 29: formatting.strike = false - of 30..37: formatting.fgcolor = CellColor(rgb: false, color: uint8(ip[pi])) + format = newFormat() + of 1: format.bold = true + of 3: format.italic = true + of 4: format.underline = true + of 7: format.reverse = true + of 9: format.strike = true + of 22: format.bold = false + of 23: format.italic = false + of 27: format.reverse = false + of 29: format.strike = false + of 30..37: format.fgcolor = CellColor(rgb: false, color: uint8(ip[pi])) of 38: inc pi if pi < ip.len: @@ -189,7 +189,7 @@ proc handleAnsiCode(formatting: var Formatting, final: char, params: string) = let g = ip[pi] inc pi let b = ip[pi] - formatting.fgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) + format.fgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) else: #TODO inc pi @@ -197,9 +197,9 @@ proc handleAnsiCode(formatting: var Formatting, final: char, params: string) = else: break of 39: - formatting.fgcolor = defaultColor + format.fgcolor = defaultColor of 40..47: - formatting.bgcolor = CellColor(rgb: false, color: uint8(ip[0])) + format.bgcolor = CellColor(rgb: false, color: uint8(ip[0])) of 48: inc pi if pi < ip.len: @@ -211,22 +211,22 @@ proc handleAnsiCode(formatting: var Formatting, final: char, params: string) = let g = ip[pi] inc pi let b = ip[pi] - formatting.bgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) + format.bgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) else: #TODO inc pi continue else: break - of 49: formatting.bgcolor = defaultColor - of 53: formatting.overline = true - of 55: formatting.overline = false + of 49: format.bgcolor = defaultColor + of 53: format.overline = true + of 55: format.overline = false else: discard inc pi except ValueError: discard else: discard -proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int = +proc parseAnsiCode*(format: var Format, buf: string, fi: int): int = var i = fi if buf[i] != '\e': return i @@ -253,11 +253,11 @@ proc parseAnsiCode*(formatting: var Formatting, buf: string, fi: int): int = let final = buf[i] #final byte if 0x40 <= int(buf[i]) and int(buf[i]) <= 0x7E: - formatting.handleAnsiCode(final, params) + format.handleAnsiCode(final, params) return i -proc parseAnsiCode*(formatting: var Formatting, stream: Stream) = +proc parseAnsiCode*(format: var Format, stream: Stream) = if stream.atEnd(): return var c = stream.readChar() if 0x40 <= int(c) and int(c) <= 0x5F: @@ -284,37 +284,37 @@ proc parseAnsiCode*(formatting: var Formatting, stream: Stream) = #final byte if 0x40 <= int(c) and int(c) <= 0x7E: let final = c - formatting.handleAnsiCode(final, params) + format.handleAnsiCode(final, params) -proc processFormatting*(formatting: var Formatting, cellf: Formatting): string = +proc processFormat*(format: var Format, cellf: Format): string = for flag in FormatFlags: - if flag in formatting.flags and flag notin cellf.flags: + if flag in format.flags and flag notin cellf.flags: result &= SGR(FormatCodes[flag].e) - if cellf.fgcolor != formatting.fgcolor: + if cellf.fgcolor != format.fgcolor: var color = cellf.fgcolor if color.rgb: let rgb = color.rgbcolor result &= SGR(38, 2, rgb.r, rgb.g, rgb.b) elif color == defaultColor: result &= SGR() - formatting = newFormatting() + format = newFormat() else: result &= SGR(color.color) - if cellf.bgcolor != formatting.bgcolor: + if cellf.bgcolor != format.bgcolor: var color = cellf.bgcolor if color.rgb: let rgb = color.rgbcolor result &= SGR(48, 2, rgb.r, rgb.g, rgb.b) elif color == defaultColor: result &= SGR() - formatting = newFormatting() + format = newFormat() else: result &= SGR(color.color) for flag in FormatFlags: - if flag notin formatting.flags and flag in cellf.flags: + if flag notin format.flags and flag in cellf.flags: result &= SGR(FormatCodes[flag].s) - formatting = cellf + format = cellf diff --git a/src/layout/box.nim b/src/layout/box.nim index d7ae3400..44096c9a 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -23,17 +23,20 @@ type width*: int height*: int - InlineSpacing* = ref object of InlineAtom - word*: InlineWord - - InlineWord* = ref object of InlineAtom - str*: string + ComputedFormat* = ref object fontstyle*: CSSFontStyle fontweight*: int textdecoration*: CSSTextDecoration color*: CSSColor node*: Node + InlineSpacing* = ref object of InlineAtom + format*: ComputedFormat + + InlineWord* = ref object of InlineAtom + str*: string + format*: ComputedFormat + InlineRow* = ref object atoms*: seq[InlineAtom] relx*: int @@ -43,6 +46,7 @@ type InlineContext* = ref object relx*: int + rely*: int width*: int height*: int rows*: seq[InlineRow] @@ -61,6 +65,12 @@ type rely*: int margin_top*: int margin_bottom*: int + margin_left*: int + margin_right*: int + padding_top*: int + padding_bottom*: int + padding_left*: int + padding_right*: int compwidth*: int compheight*: Option[int] diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 45aef6de..b5876b5c 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -53,12 +53,13 @@ func computeShift(ictx: InlineContext, specified: CSSSpecifiedValues): int = proc newWord(state: var InlineState) = let word = InlineWord() + word.format = ComputedFormat() let specified = state.specified - word.color = specified{"color"} - word.fontstyle = specified{"font-style"} - word.fontweight = specified{"font-weight"} - word.textdecoration = specified{"text-decoration"} - word.node = state.node + word.format.color = specified{"color"} + word.format.fontstyle = specified{"font-style"} + word.format.fontweight = specified{"font-weight"} + word.format.textdecoration = specified{"text-decoration"} + word.format.node = state.node state.word = word proc finishRow(ictx: InlineContext) = @@ -69,6 +70,12 @@ proc finishRow(ictx: InlineContext) = ictx.width = max(ictx.width, oldrow.width) ictx.thisrow = InlineRow(rely: oldrow.rely + oldrow.height) +proc addSpacing(row: InlineRow, width, height: int, format: ComputedFormat) {.inline.} = + let spacing = InlineSpacing(width: width, height: height, format: format) + spacing.relx = row.width + row.width += spacing.width + row.atoms.add(spacing) + proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, specified: CSSSpecifiedValues) = var shift = ictx.computeShift(specified) ictx.whitespace = false @@ -82,10 +89,11 @@ proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, specified: CS if atom.width > 0 and atom.height > 0: if shift > 0: - let spacing = InlineSpacing(width: shift, height: atom.height) - spacing.relx = ictx.thisrow.width - ictx.thisrow.width += spacing.width - ictx.thisrow.atoms.add(spacing) + let format = if atom of InlineWord: + InlineWord(atom).format + else: + nil + ictx.thisrow.addSpacing(shift, atom.height, format) atom.relx += ictx.thisrow.width ictx.thisrow.width += atom.width @@ -163,16 +171,22 @@ proc computedDimensions(bctx: BlockContext, width: int, height: Option[int]) = if pwidth.auto: bctx.compwidth = width else: - #bctx.compwidth = pwidth.cells_w(bctx.viewport, width) bctx.compwidth = pwidth.px(bctx.viewport, width) - #let mlef = bctx.specified{"margin-left"}.cells_w(bctx.viewport, width) - #let mrig = bctx.specified{"margin-right"}.cells_w(bctx.viewport, width) - let mlef = bctx.specified{"margin-left"}.px(bctx.viewport, width) - let mrig = bctx.specified{"margin-right"}.px(bctx.viewport, width) - bctx.relx = mlef - bctx.compwidth -= mlef - bctx.compwidth -= mrig + bctx.margin_left = bctx.specified{"margin-left"}.px(bctx.viewport, width) + bctx.margin_right = bctx.specified{"margin-right"}.px(bctx.viewport, width) + + bctx.padding_top = bctx.specified{"padding-top"}.px(bctx.viewport, width) + bctx.padding_bottom = bctx.specified{"padding-bottom"}.px(bctx.viewport, width) + bctx.padding_left = bctx.specified{"padding-left"}.px(bctx.viewport, width) + bctx.padding_right = bctx.specified{"padding-right"}.px(bctx.viewport, width) + + if bctx.compwidth >= width: + bctx.compwidth -= bctx.margin_left + bctx.compwidth -= bctx.margin_right + + bctx.compwidth -= bctx.padding_left + bctx.compwidth -= bctx.padding_right let pheight = bctx.specified{"height"} if not pheight.auto: @@ -219,10 +233,17 @@ proc newInlineContext(bctx: BlockContext): InlineContext = # children, whence the separate procedure. proc arrangeBlocks(bctx: BlockContext) = var y = 0 + var x = 0 var margin_todo = 0 + y += bctx.padding_top + bctx.height += bctx.padding_top + + x += bctx.padding_left + template apply_child(child: BlockContext) = child.rely = y + child.relx = x + child.margin_left y += child.height bctx.height += child.height bctx.width = max(bctx.width, child.width) @@ -233,7 +254,6 @@ proc arrangeBlocks(bctx: BlockContext) = let child = bctx.nested[i] bctx.margin_top = child.margin_top - #let mtop = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth) let mtop = bctx.specified{"margin-top"}.px(bctx.viewport, bctx.compwidth) if mtop > bctx.margin_top or mtop < 0: bctx.margin_top = mtop - bctx.margin_top @@ -253,23 +273,46 @@ proc arrangeBlocks(bctx: BlockContext) = inc i bctx.margin_bottom = margin_todo - #let mbot = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth) let mbot = bctx.specified{"margin-bottom"}.px(bctx.viewport, bctx.compwidth) if mbot > bctx.margin_bottom or mbot < 0: bctx.margin_bottom = mbot - bctx.margin_bottom + bctx.height += bctx.padding_bottom + if bctx.compheight.issome: bctx.height = bctx.compheight.get + bctx.width += bctx.padding_left + bctx.width += bctx.padding_right + +proc arrangeInlines(bctx: BlockContext) = + bctx.width += bctx.padding_left + bctx.inline.relx += bctx.padding_left + + bctx.height += bctx.padding_top + bctx.inline.rely += bctx.padding_top + + bctx.height += bctx.padding_bottom + + bctx.width += bctx.padding_right + + bctx.width = min(bctx.width, bctx.compwidth) + proc alignBlock(box: BlockBox) proc alignInlineBlock(bctx: BlockContext, box: InlineBlockBox, parentcss: CSSSpecifiedValues) = if box.bctx.done: return alignBlock(box) + box.bctx.rely += box.bctx.margin_top box.bctx.height += box.bctx.margin_top box.bctx.height += box.bctx.margin_bottom + + box.bctx.relx += box.bctx.margin_left + box.bctx.width += box.bctx.margin_left + box.bctx.width += box.bctx.margin_right + box.ictx.addAtom(box.bctx, bctx.compwidth, parentcss) box.ictx.whitespace = false @@ -277,6 +320,15 @@ proc alignInline(bctx: BlockContext, box: InlineBox) = assert box.ictx != nil if box.newline: box.ictx.flushLine() + + let margin_left = box.specified{"margin-left"}.px(bctx.viewport, bctx.compwidth) + box.ictx.thisrow.width += margin_left + + let paddingformat = ComputedFormat(node: box.node) + let padding_left = box.specified{"padding-left"}.px(bctx.viewport, bctx.compwidth) + if padding_left > 0: + box.ictx.thisrow.addSpacing(padding_left, max(box.ictx.thisrow.height, 1), paddingformat) + for text in box.text: assert box.children.len == 0 box.ictx.renderText(text, bctx.compwidth, box.specified, box.node) @@ -294,6 +346,13 @@ proc alignInline(bctx: BlockContext, box: InlineBox) = else: assert false, "child.t is " & $child.t + let padding_right = box.specified{"padding-right"}.px(bctx.viewport, bctx.compwidth) + if padding_right > 0: + box.ictx.thisrow.addSpacing(padding_right, max(box.ictx.thisrow.height, 1), paddingformat) + + let margin_right = box.specified{"margin-right"}.px(bctx.viewport, bctx.compwidth) + box.ictx.thisrow.width += margin_right + proc alignInlines(bctx: BlockContext, inlines: seq[CSSBox]) = let ictx = bctx.newInlineContext() for child in inlines: @@ -312,9 +371,7 @@ proc alignInlines(bctx: BlockContext, inlines: seq[CSSBox]) = bctx.height += ictx.height if bctx.compheight.issome: bctx.height = bctx.compheight.get - bctx.width = max(ictx.width, ictx.width) - #bctx.margin_top = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth) - #bctx.margin_bottom = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth) + bctx.width = max(bctx.width, ictx.width) bctx.margin_top = bctx.specified{"margin-top"}.px(bctx.viewport, bctx.compwidth) bctx.margin_bottom = bctx.specified{"margin-bottom"}.px(bctx.viewport, bctx.compwidth) @@ -351,6 +408,7 @@ proc alignBlock(box: BlockBox) = if box.inlinelayout: # Box only contains inline boxes. box.bctx.alignInlines(box.children) + box.bctx.arrangeInlines() else: var blockgroup: seq[CSSBox] box.bctx.alignBlocks(box.children, blockgroup, box.node) diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim index 89ce4ae6..13cd7b0c 100644 --- a/src/render/renderdocument.nim +++ b/src/render/renderdocument.nim @@ -11,24 +11,24 @@ import layout/box import layout/engine import utils/twtstr -func formatFromWord(word: InlineWord): Formatting = - result.fgcolor = word.color.cellColor() - if word.fontstyle in { FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE }: +func formatFromWord(computed: ComputedFormat): Format = + result.fgcolor = computed.color.cellColor() + if computed.fontstyle in { FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE }: result.italic = true - if word.fontweight > 500: + if computed.fontweight > 500: result.bold = true - if word.textdecoration == TEXT_DECORATION_UNDERLINE: + if computed.textdecoration == TEXT_DECORATION_UNDERLINE: result.underline = true - if word.textdecoration == TEXT_DECORATION_OVERLINE: + if computed.textdecoration == TEXT_DECORATION_OVERLINE: result.overline = true - if word.textdecoration == TEXT_DECORATION_LINE_THROUGH: + if computed.textdecoration == TEXT_DECORATION_LINE_THROUGH: result.strike = true proc setRowWord(lines: var FlexibleGrid, word: InlineWord, x, y: int, term: TermAttributes) = var r: Rune let y = y div term.ppl - var x = x div term.ppc + var x = (x + word.relx) div term.ppc var i = 0 while x < 0: fastRuneAt(word.str, i, r) @@ -48,13 +48,15 @@ proc setRowWord(lines: var FlexibleGrid, word: InlineWord, x, y: int, term: Term let oformats = lines[y].formats.subformats(i) lines[y].setLen(i) - lines.addFormat(y, i, word.formatFromWord(), word.node) - var nx = cx if nx < x: + lines.addFormat(y, i, newFormat()) lines[y].str &= ' '.repeat(x - nx) + i += x - nx nx = x + lines.addFormat(y, i, word.format.formatFromWord(), word.format, word.format.node) + lines[y].str &= linestr nx += linestr.width() @@ -71,7 +73,7 @@ proc setSpacing(lines: var FlexibleGrid, spacing: InlineSpacing, x, y: int, term var r: Rune let y = y div term.ppl - var x = x div term.ppc + var x = (x + spacing.relx) div term.ppc let width = spacing.width div term.ppc var i = 0 @@ -94,16 +96,16 @@ proc setSpacing(lines: var FlexibleGrid, spacing: InlineSpacing, x, y: int, term let oformats = lines[y].formats.subformats(i) lines[y].setLen(i) - if spacing.word != nil: - lines.addFormat(y, i, spacing.word.formatFromWord(), spacing.word.node) - var nx = cx if nx < x: + lines.addFormat(y, i, newFormat()) lines[y].str &= ' '.repeat(x - nx) nx = x lines[y].str &= linestr nx += linestr.len + if spacing.format != nil: + lines.addFormat(y, i, spacing.format.formatFromWord(), spacing.format, spacing.format.node) i = 0 while cx < nx and i < ostr.len: @@ -117,6 +119,8 @@ proc setSpacing(lines: var FlexibleGrid, spacing: InlineSpacing, x, y: int, term proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockContext, x, y: int, term: TermAttributes) proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int, term: TermAttributes) = + let x = x + ctx.relx + let y = y + ctx.rely for row in ctx.rows: let x = x + row.relx let y = y + row.rely + row.height @@ -126,23 +130,23 @@ proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int, let y = y - atom.height if atom of BlockContext: let ctx = BlockContext(atom) - grid.renderBlockContext(ctx, x + ctx.relx, y + ctx.rely, term) + grid.renderBlockContext(ctx, x, y, term) elif atom of InlineWord: let word = InlineWord(atom) - grid.setRowWord(word, x + word.relx, y, term) + grid.setRowWord(word, x, y, term) elif atom of InlineSpacing: let spacing = InlineSpacing(atom) - grid.setSpacing(spacing, x + spacing.relx, y, term) + grid.setSpacing(spacing, x, y, term) proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockContext, x, y: int, term: TermAttributes) = - var x = x - var y = y + let x = x + ctx.relx + let y = y + ctx.rely if ctx.inline != nil: assert ctx.nested.len == 0 - grid.renderInlineContext(ctx.inline, x + ctx.inline.relx, y, term) + grid.renderInlineContext(ctx.inline, x, y, term) else: for ctx in ctx.nested: - grid.renderBlockContext(ctx, x + ctx.relx, y + ctx.rely, term) + grid.renderBlockContext(ctx, x, y, term) const css = staticRead"res/ua.css" let uastyle = css.parseStylesheet() diff --git a/src/render/rendertext.nim b/src/render/rendertext.nim index b5054e7b..15a58c4c 100644 --- a/src/render/rendertext.nim +++ b/src/render/rendertext.nim @@ -4,7 +4,7 @@ import io/cell import utils/twtstr proc renderPlainText*(text: string): FlexibleGrid = - var format = newFormatting() + var format = newFormat() template add_format() = if af: af = false @@ -38,7 +38,7 @@ proc renderPlainText*(text: string): FlexibleGrid = discard result.pop() proc renderStream*(stream: Stream): FlexibleGrid = - var format = newFormatting() + var format = newFormat() template add_format() = if af: af = false |