diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/css/values.nim | 73 | ||||
-rw-r--r-- | src/layout/box.nim | 4 | ||||
-rw-r--r-- | src/layout/engine.nim | 163 | ||||
-rw-r--r-- | src/render/renderdocument.nim | 13 |
4 files changed, 188 insertions, 65 deletions
diff --git a/src/css/values.nim b/src/css/values.nim index fb1d6d63..926a9392 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -28,12 +28,13 @@ type PROPERTY_TEXT_DECORATION, PROPERTY_WORD_BREAK, PROPERTY_WIDTH, PROPERTY_HEIGHT, PROPERTY_LIST_STYLE_TYPE, PROPERTY_PADDING, PROPERTY_PADDING_TOP, PROPERTY_PADDING_LEFT, PROPERTY_PADDING_RIGHT, - PROPERTY_PADDING_BOTTOM, PROPERTY_WORD_SPACING + PROPERTY_PADDING_BOTTOM, PROPERTY_WORD_SPACING, PROPERTY_VERTICAL_ALIGN, + PROPERTY_LINE_HEIGHT 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_WORD_BREAK, VALUE_LIST_STYLE_TYPE, VALUE_VERTICAL_ALIGN CSSGlobalValueType* = enum VALUE_NOGLOBAL, VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET @@ -69,6 +70,11 @@ type LIST_STYLE_TYPE_LOWER_ROMAN, LIST_STYLE_TYPE_UPPER_ROMAN, LIST_STYLE_TYPE_JAPANESE_INFORMAL + CSSVerticalAlign2* = enum + VERTICAL_ALIGN_BASELINE, VERTICAL_ALIGN_SUB, VERTICAL_ALIGN_SUPER, + VERTICAL_ALIGN_TEXT_TOP, VERTICAL_ALIGN_TEXT_BOTTOM, VERTICAL_ALIGN_MIDDLE, + VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM + type CSSLength* = object num*: float64 @@ -78,6 +84,10 @@ type CSSColor* = object rgba: RGBAColor termcolor: int + + CSSVerticalAlign* = object + length*: CSSLength + keyword*: CSSVerticalAlign2 CSSSpecifiedValue* = ref object t*: CSSPropertyType @@ -102,6 +112,8 @@ type wordbreak*: CSSWordBreak of VALUE_LIST_STYLE_TYPE: liststyletype*: CSSListStyleType + of VALUE_VERTICAL_ALIGN: + verticalalign*: CSSVerticalAlign of VALUE_NONE: discard CSSSpecifiedValues* = ref array[CSSPropertyType, CSSSpecifiedValue] @@ -132,6 +144,8 @@ const PropertyNames = { "padding-left": PROPERTY_PADDING_LEFT, "padding-right": PROPERTY_PADDING_RIGHT, "word-spacing": PROPERTY_WORD_SPACING, + "vertical-align": PROPERTY_VERTICAL_ALIGN, + "line-height": PROPERTY_LINE_HEIGHT, }.toTable() const ValueTypes = [ @@ -159,12 +173,14 @@ const ValueTypes = [ PROPERTY_PADDING_RIGHT: VALUE_LENGTH, PROPERTY_PADDING_BOTTOM: VALUE_LENGTH, PROPERTY_WORD_SPACING: VALUE_LENGTH, + PROPERTY_VERTICAL_ALIGN: VALUE_VERTICAL_ALIGN, + PROPERTY_LINE_HEIGHT: VALUE_LENGTH, ] const InheritedProperties = { PROPERTY_COLOR, PROPERTY_FONT_STYLE, PROPERTY_WHITE_SPACE, PROPERTY_FONT_WEIGHT, PROPERTY_TEXT_DECORATION, PROPERTY_WORD_BREAK, - PROPERTY_LIST_STYLE_TYPE, PROPERTY_WORD_SPACING + PROPERTY_LIST_STYLE_TYPE, PROPERTY_WORD_SPACING, PROPERTY_LINE_HEIGHT } func getPropInheritedArray(): array[CSSPropertyType, bool] = @@ -520,8 +536,10 @@ func cssColor(d: CSSDeclaration): CSSColor = func cellColor*(color: CSSColor): CellColor = return CellColor(rgb: true, rgbcolor: RGBColor(color.rgba)) +func isToken(d: CSSDeclaration): bool {.inline.} = d.value.len > 0 and d.value[0] of CSSToken + func cssLength(d: CSSDeclaration): CSSLength = - if d.value.len > 0 and d.value[0] of CSSToken: + if isToken(d): let tok = CSSToken(d.value[0]) case tok.tokenType of CSS_PERCENTAGE_TOKEN: @@ -535,7 +553,7 @@ func cssLength(d: CSSDeclaration): CSSLength = raise newException(CSSValueError, "Invalid length") func cssWordSpacing(d: CSSDeclaration): CSSLength = - if d.value.len > 0 and d.value[0] of CSSToken: + if isToken(d): let tok = CSSToken(d.value[0]) case tok.tokenType of CSS_DIMENSION_TOKEN: @@ -546,8 +564,6 @@ func cssWordSpacing(d: CSSDeclaration): CSSLength = else: discard raise newException(CSSValueError, "Invalid word spacing") -func isToken(d: CSSDeclaration): bool = d.value.len > 0 and d.value[0] of CSSToken - func getToken(d: CSSDeclaration): CSSToken = (CSSToken)d.value[0] func cssGlobal*(d: CSSDeclaration): CSSGlobalValueType = @@ -667,12 +683,49 @@ func cssListStyleType(d: CSSDeclaration): CSSListStyleType = of "japanese-informal": return LIST_STYLE_TYPE_JAPANESE_INFORMAL raise newException(CSSValueError, "Invalid list style") +func cssVerticalAlign(d: CSSDeclaration): CSSVerticalAlign = + if isToken(d): + let tok = getToken(d) + if tok.tokenType == CSS_IDENT_TOKEN: + case $tok.value + of "baseline": result.keyword = VERTICAL_ALIGN_BASELINE + of "sub": result.keyword = VERTICAL_ALIGN_SUB + of "super": result.keyword = VERTICAL_ALIGN_SUPER + of "text-top": result.keyword = VERTICAL_ALIGN_TEXT_BOTTOM + of "middle": result.keyword = VERTICAL_ALIGN_MIDDLE + of "top": result.keyword = VERTICAL_ALIGN_TOP + of "bottom": result.keyword = VERTICAL_ALIGN_BOTTOM + else: + raise newException(CSSValueError, "Invalid vertical align") + return result + else: + result.keyword = VERTICAL_ALIGN_BASELINE + result.length = cssLength(d) + return result + raise newException(CSSValueError, "Invalid vertical align") + +func cssLineHeight(d: CSSDeclaration): CSSLength = + if isToken(d): + let tok = CSSToken(d.value[0]) + case tok.tokenType + of CSS_NUMBER_TOKEN: + return cssLength(tok.nvalue * 100, "%") + of CSS_IDENT_TOKEN: + if $tok.value == "normal": + return CSSLength(auto: true) + else: + return cssLength(d) + raise newException(CSSValueError, "Invalid line height") + proc getValueFromDecl(val: CSSSpecifiedValue, d: CSSDeclaration, vtype: CSSValueType, ptype: CSSPropertyType) = case vtype of VALUE_COLOR: val.color = cssColor(d) of VALUE_LENGTH: - if ptype == PROPERTY_WORD_SPACING: + case ptype + of PROPERTY_WORD_SPACING: val.length = cssWordSpacing(d) + of PROPERTY_LINE_HEIGHT: + val.length = cssLineHeight(d) else: val.length = cssLength(d) of VALUE_FONT_STYLE: val.fontstyle = cssFontStyle(d) @@ -685,6 +738,7 @@ proc getValueFromDecl(val: CSSSpecifiedValue, d: CSSDeclaration, vtype: CSSValue of VALUE_TEXT_DECORATION: val.textdecoration = cssTextDecoration(d) of VALUE_WORD_BREAK: val.wordbreak = cssWordBreak(d) of VALUE_LIST_STYLE_TYPE: val.liststyletype = cssListStyleType(d) + of VALUE_VERTICAL_ALIGN: val.verticalalign = cssVerticalAlign(d) of VALUE_NONE: discard func getInitialColor(t: CSSPropertyType): CSSColor = @@ -696,7 +750,7 @@ func getInitialColor(t: CSSPropertyType): CSSColor = func getInitialLength(t: CSSPropertyType): CSSLength = case t - of PROPERTY_WIDTH, PROPERTY_HEIGHT, PROPERTY_WORD_SPACING: + of PROPERTY_WIDTH, PROPERTY_HEIGHT, PROPERTY_WORD_SPACING, PROPERTY_LINE_HEIGHT: return CSSLength(auto: true) else: return CSSLength() @@ -756,6 +810,7 @@ func equals*(a, b: CSSSpecifiedValue): bool = of VALUE_TEXT_DECORATION: return a.textdecoration == b.textdecoration of VALUE_WORD_BREAK: return a.wordbreak == b.wordbreak of VALUE_LIST_STYLE_TYPE: return a.liststyletype == b.liststyletype + of VALUE_VERTICAL_ALIGN: return a.verticalalign == b.verticalalign of VALUE_NONE: return true return false diff --git a/src/layout/box.nim b/src/layout/box.nim index 44096c9a..aa897ae6 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -20,8 +20,10 @@ type InlineAtom* = ref object of RootObj relx*: int + rely*: int width*: int height*: int + vertalign*: CSSVerticalAlign ComputedFormat* = ref object fontstyle*: CSSFontStyle @@ -43,6 +45,7 @@ type rely*: int width*: int height*: int + lineheight*: int #line-height property InlineContext* = ref object relx*: int @@ -62,7 +65,6 @@ type nested*: seq[BlockContext] specified*: CSSSpecifiedValues viewport*: Viewport - rely*: int margin_top*: int margin_bottom*: int margin_left*: int diff --git a/src/layout/engine.nim b/src/layout/engine.nim index b5876b5c..986d6723 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -1,5 +1,6 @@ -import unicode +import math import options +import unicode import layout/box import html/tags @@ -34,11 +35,17 @@ type InlineState = object func whitespacepre(specified: CSSSpecifiedValues): bool {.inline.} = specified{"white-space"} in {WHITESPACE_PRE, WHITESPACE_PRE_WRAP} +func cellwidth(viewport: Viewport): int {.inline.} = + viewport.term.ppc + func cellwidth(ictx: InlineContext): int {.inline.} = - ictx.viewport.term.ppc + ictx.viewport.cellwidth + +func cellheight(viewport: Viewport): int {.inline.} = + viewport.term.ppl func cellheight(ictx: InlineContext): int {.inline.} = - ictx.viewport.term.ppl + ictx.viewport.cellheight # Whitespace between words func computeShift(ictx: InlineContext, specified: CSSSpecifiedValues): int = @@ -51,6 +58,11 @@ func computeShift(ictx: InlineContext, specified: CSSSpecifiedValues): int = return spacing.px(ictx.viewport) return 0 +func computeLineHeight(viewport: Viewport, specified: CSSSpecifiedValues): int = + if specified{"line-height"}.auto: + return viewport.cellheight + return specified{"line-height"}.px(viewport, viewport.cellheight) + proc newWord(state: var InlineState) = let word = InlineWord() word.format = ComputedFormat() @@ -62,9 +74,47 @@ proc newWord(state: var InlineState) = word.format.node = state.node state.word = word -proc finishRow(ictx: InlineContext) = - if ictx.thisrow.height != 0: +proc finishRow(ictx: InlineContext, specified: CSSSpecifiedValues, force = false) = + if ictx.thisrow.atoms.len != 0 or force: let oldrow = ictx.thisrow + + var baseline = if oldrow.height < oldrow.lineheight: + let lines = oldrow.lineheight div ictx.cellheight + ceilDiv(lines, 2) * ictx.cellheight + else: + 0 + + # line-height is the minimum line height + oldrow.height = max(oldrow.height, oldrow.lineheight) + + for atom in oldrow.atoms: + case atom.vertalign.keyword + of VERTICAL_ALIGN_BASELINE: + let len = atom.vertalign.length.px(ictx.viewport, oldrow.lineheight) + baseline = max(baseline, atom.height + len) + of VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM: + oldrow.height = max(atom.height, oldrow.height) + of VERTICAL_ALIGN_MIDDLE: + baseline = max(baseline, atom.height div 2) + else: + baseline = max(baseline, atom.height) + oldrow.height = max(baseline, oldrow.height) + + for atom in oldrow.atoms: + let diff = case atom.vertalign.keyword + of VERTICAL_ALIGN_BASELINE: + let len = atom.vertalign.length.px(ictx.viewport, oldrow.lineheight) + baseline - atom.height - len + of VERTICAL_ALIGN_MIDDLE: + baseline - atom.height div 2 + of VERTICAL_ALIGN_TOP: + 0 + of VERTICAL_ALIGN_BOTTOM: + oldrow.height - atom.height + else: + baseline - atom.height + atom.rely += diff + ictx.rows.add(oldrow) ictx.height += oldrow.height ictx.width = max(ictx.width, oldrow.width) @@ -82,20 +132,23 @@ proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, specified: CS # Line wrapping if specified{"white-space"} notin {WHITESPACE_NOWRAP, WHITESPACE_PRE}: if ictx.thisrow.width + atom.width + shift > maxwidth: - ictx.finishRow() + ictx.finishRow(specified) # Recompute on newline shift = ictx.computeShift(specified) ictx.whitespace = false if atom.width > 0 and atom.height > 0: + atom.vertalign = specified{"vertical-align"} + if shift > 0: let format = if atom of InlineWord: InlineWord(atom).format else: nil - ictx.thisrow.addSpacing(shift, atom.height, format) + ictx.thisrow.addSpacing(shift, ictx.cellheight, format) atom.relx += ictx.thisrow.width + ictx.thisrow.lineheight = max(ictx.thisrow.lineheight, computeLineHeight(ictx.viewport, specified)) ictx.thisrow.width += atom.width ictx.thisrow.height = max(ictx.thisrow.height, atom.height) ictx.thisrow.atoms.add(atom) @@ -108,9 +161,9 @@ proc addWord(state: var InlineState) = state.newWord() # Start a new line, even if the previous one is empty -proc flushLine(ictx: InlineContext) = - ictx.thisrow.height = max(ictx.thisrow.height, ictx.cellheight) - ictx.finishRow() +proc flushLine(ictx: InlineContext, specified: CSSSpecifiedValues) = + ictx.thisrow.lineheight = computeLineHeight(ictx.viewport, specified) + ictx.finishRow(specified, true) proc checkWrap(state: var InlineState, r: Rune) = if state.specified{"white-space"} in {WHITESPACE_NOWRAP, WHITESPACE_PRE}: @@ -120,11 +173,11 @@ proc checkWrap(state: var InlineState, r: Rune) = of WORD_BREAK_BREAK_ALL: if state.ictx.thisrow.width + state.word.width + shift + r.width() * state.ictx.cellwidth > state.maxwidth: state.addWord() - state.ictx.finishRow() + state.ictx.finishRow(state.specified) state.ictx.whitespace = false of WORD_BREAK_KEEP_ALL: if state.ictx.thisrow.width + state.word.width + shift + r.width() * state.ictx.cellwidth > state.maxwidth: - state.ictx.finishRow() + state.ictx.finishRow(state.specified) state.ictx.whitespace = false else: discard @@ -135,7 +188,7 @@ proc processWhitespace(state: var InlineState, c: char) = state.ictx.whitespace = true of WHITESPACE_PRE_LINE, WHITESPACE_PRE, WHITESPACE_PRE_WRAP: if c == '\n': - state.ictx.flushLine() + state.ictx.flushLine(state.specified) else: state.ictx.whitespace = true @@ -163,9 +216,6 @@ proc renderText*(ictx: InlineContext, str: string, maxwidth: int, specified: CSS state.addWord() -proc finish(ictx: InlineContext) = - ictx.finishRow() - proc computedDimensions(bctx: BlockContext, width: int, height: Option[int]) = let pwidth = bctx.specified{"width"} if pwidth.auto: @@ -207,7 +257,7 @@ proc newBlockContext(parent: BlockContext, box: BlockBox): BlockContext = result = newBlockContext_common(parent, box) proc newInlineBlockContext(parent: BlockContext, box: InlineBlockBox): BlockContext = - newBlockContext_common(parent, box) + result = newBlockContext_common(parent, box) # Anonymous block box. proc newBlockContext(parent: BlockContext): BlockContext = @@ -231,7 +281,7 @@ proc newInlineContext(bctx: BlockContext): InlineContext = # Blocks' positions do not have to be arranged if alignBlocks is called with # children, whence the separate procedure. -proc arrangeBlocks(bctx: BlockContext) = +proc arrangeBlocks(bctx: BlockContext, selfcontained: bool) = var y = 0 var x = 0 var margin_todo = 0 @@ -258,6 +308,11 @@ proc arrangeBlocks(bctx: BlockContext) = if mtop > bctx.margin_top or mtop < 0: bctx.margin_top = mtop - bctx.margin_top + if selfcontained: + margin_todo = bctx.margin_top + bctx.height += margin_todo + y += margin_todo + apply_child(child) inc i @@ -277,6 +332,9 @@ proc arrangeBlocks(bctx: BlockContext) = if mbot > bctx.margin_bottom or mbot < 0: bctx.margin_bottom = mbot - bctx.margin_bottom + if selfcontained: + bctx.height += bctx.margin_bottom + bctx.height += bctx.padding_bottom if bctx.compheight.issome: @@ -285,10 +343,18 @@ proc arrangeBlocks(bctx: BlockContext) = bctx.width += bctx.padding_left bctx.width += bctx.padding_right -proc arrangeInlines(bctx: BlockContext) = +proc arrangeInlines(bctx: BlockContext, selfcontained: bool) = + bctx.margin_top = bctx.specified{"margin-top"}.px(bctx.viewport, bctx.compwidth) + bctx.margin_bottom = bctx.specified{"margin-bottom"}.px(bctx.viewport, bctx.compwidth) + bctx.width += bctx.padding_left bctx.inline.relx += bctx.padding_left + if selfcontained: + bctx.inline.rely += bctx.margin_top + bctx.height += bctx.margin_top + bctx.height += bctx.margin_bottom + bctx.height += bctx.padding_top bctx.inline.rely += bctx.padding_top @@ -298,28 +364,24 @@ proc arrangeInlines(bctx: BlockContext) = bctx.width = min(bctx.width, bctx.compwidth) -proc alignBlock(box: BlockBox) +proc alignBlock(box: BlockBox, selfcontained = false) -proc alignInlineBlock(bctx: BlockContext, box: InlineBlockBox, parentcss: CSSSpecifiedValues) = +proc alignInlineBlock(bctx: BlockContext, box: InlineBlockBox) = 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 + alignBlock(box, true) 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.addAtom(box.bctx, bctx.compwidth, box.specified) box.ictx.whitespace = false proc alignInline(bctx: BlockContext, box: InlineBox) = assert box.ictx != nil if box.newline: - box.ictx.flushLine() + box.ictx.flushLine(bctx.specified) let margin_left = box.specified{"margin-left"}.px(bctx.viewport, bctx.compwidth) box.ictx.thisrow.width += margin_left @@ -327,7 +389,7 @@ proc alignInline(bctx: BlockContext, box: InlineBox) = 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) + box.ictx.thisrow.addSpacing(padding_left, box.ictx.cellheight, paddingformat) for text in box.text: assert box.children.len == 0 @@ -342,7 +404,7 @@ proc alignInline(bctx: BlockContext, box: InlineBox) = of DISPLAY_INLINE_BLOCK: let child = InlineBlockBox(child) child.ictx = box.ictx - bctx.alignInlineBlock(child, box.specified) + bctx.alignInlineBlock(child) else: assert false, "child.t is " & $child.t @@ -355,25 +417,25 @@ proc alignInline(bctx: BlockContext, box: InlineBox) = proc alignInlines(bctx: BlockContext, inlines: seq[CSSBox]) = let ictx = bctx.newInlineContext() - for child in inlines: - case child.t - of DISPLAY_INLINE: - let child = InlineBox(child) - child.ictx = ictx - bctx.alignInline(child) - of DISPLAY_INLINE_BLOCK: - let child = InlineBlockBox(child) - child.ictx = ictx - bctx.alignInlineBlock(child, bctx.specified) - else: - assert false, "child.t is " & $child.t - ictx.finish() + if inlines.len > 0: + for child in inlines: + case child.t + of DISPLAY_INLINE: + let child = InlineBox(child) + child.ictx = ictx + bctx.alignInline(child) + of DISPLAY_INLINE_BLOCK: + let child = InlineBlockBox(child) + child.ictx = ictx + bctx.alignInlineBlock(child) + else: + assert false, "child.t is " & $child.t + ictx.finishRow(bctx.specified) + bctx.height += ictx.height if bctx.compheight.issome: bctx.height = bctx.compheight.get 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) template flush_group() = if blockgroup.len > 0: @@ -402,19 +464,19 @@ proc alignBlocks(bctx: BlockContext, blocks: seq[CSSBox], blockgroup: var seq[CS blockgroup.add(child) else: discard #TODO -proc alignBlock(box: BlockBox) = +proc alignBlock(box: BlockBox, selfcontained = false) = if box.bctx.done: return if box.inlinelayout: # Box only contains inline boxes. box.bctx.alignInlines(box.children) - box.bctx.arrangeInlines() + box.bctx.arrangeInlines(selfcontained) else: var blockgroup: seq[CSSBox] box.bctx.alignBlocks(box.children, blockgroup, box.node) let bctx = box.bctx flush_group() - box.bctx.arrangeBlocks() + box.bctx.arrangeBlocks(selfcontained) box.bctx.done = true proc getBox(specified: CSSSpecifiedValues): CSSBox = @@ -443,7 +505,10 @@ proc getTextBox(box: CSSBox): InlineBox = new(result) result.t = DISPLAY_INLINE result.inlinelayout = true - result.specified = box.specified.inheritProperties() + if box.specified{"display"} == DISPLAY_INLINE: + result.specified = box.specified + else: + result.specified = box.specified.inheritProperties() proc getPseudoBox(bctx: BlockContext, specified: CSSSpecifiedValues): CSSBox = let box = getBox(specified) diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim index 13cd7b0c..732bcf47 100644 --- a/src/render/renderdocument.nim +++ b/src/render/renderdocument.nim @@ -27,7 +27,9 @@ func formatFromWord(computed: ComputedFormat): Format = proc setRowWord(lines: var FlexibleGrid, word: InlineWord, x, y: int, term: TermAttributes) = var r: Rune - let y = y div term.ppl + var y = (y + word.rely) div term.ppl + if y < 0: y = 0 + var x = (x + word.relx) div term.ppc var i = 0 while x < 0: @@ -72,7 +74,9 @@ proc setRowWord(lines: var FlexibleGrid, word: InlineWord, x, y: int, term: Term proc setSpacing(lines: var FlexibleGrid, spacing: InlineSpacing, x, y: int, term: TermAttributes) = var r: Rune - let y = y div term.ppl + var y = (y + spacing.rely) div term.ppl + if y < 0: y = 0 + var x = (x + spacing.relx) div term.ppc let width = spacing.width div term.ppc @@ -123,11 +127,8 @@ proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int, let y = y + ctx.rely for row in ctx.rows: let x = x + row.relx - let y = y + row.rely + row.height + let y = y + row.rely for atom in row.atoms: - # This aligns atoms with the baseline. - # (other alignment types in progress) - let y = y - atom.height if atom of BlockContext: let ctx = BlockContext(atom) grid.renderBlockContext(ctx, x, y, term) |