diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-11 16:36:10 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-11 16:36:10 +0100 |
commit | e6c81a12d2234f76b2a49efe14a29fa248ed1499 (patch) | |
tree | c417cbc3f7ca473c86efd35620e552f986294e43 /src/layout | |
parent | dbdb1c0d9a2969606d665a3b7ca76c1b88545402 (diff) | |
download | chawan-e6c81a12d2234f76b2a49efe14a29fa248ed1499.tar.gz |
layout: skip newlines between full-width characters
Crucially, *only* between full-width characters. So "あ\nあ" is rendered as "ああ", but "あ\na" remains "あ a" (with a space inbetween).
Diffstat (limited to 'src/layout')
-rw-r--r-- | src/layout/engine.nim | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim index b4d61864..7de2585e 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -214,6 +214,7 @@ type minwidth: LayoutUnit space: AvailableSpace whitespacenum: int + whitespaceIsLF: bool whitespaceFragment: InlineFragment word: InlineAtom wordstate: InlineAtomState @@ -228,6 +229,11 @@ type fragment: InlineFragment firstLine: bool startOffsetTop: Offset + # we do not want to collapse newlines over tag boundaries, so these are + # in state + lastrw: int # last rune width of the previous word + firstrw: int # first rune width of the current word + prevrw: int # last processed rune's width func whitespacepre(computed: CSSComputedValues): bool = computed{"white-space"} in {WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP} @@ -263,6 +269,9 @@ func size(ictx: var InlineContext): var Size = func computeShift(ictx: InlineContext, state: InlineState): LayoutUnit = if ictx.whitespacenum == 0: return 0 + if ictx.whitespaceIsLF and state.lastrw == 2 and state.firstrw == 2: + # skip line feed between double-width characters + return 0 if not state.computed.whitespacepre: if ictx.currentLine.atoms.len == 0 or ictx.currentLine.atoms[^1].t == INLINE_SPACING: @@ -635,6 +644,9 @@ proc checkWrap(ictx: var InlineContext, state: var InlineState, r: Rune) = return let shift = ictx.computeShift(state) let rw = r.width() + state.prevrw = rw + if ictx.word.str.len == 0: + state.firstrw = rw case state.computed{"word-break"} of WORD_BREAK_NORMAL: if rw == 2 or ictx.wrappos != -1: # break on cjk and wrap opportunities @@ -663,15 +675,20 @@ proc processWhitespace(ictx: var InlineContext, state: var InlineState, if ictx.whitespacenum < 1: ictx.whitespacenum = 1 ictx.whitespaceFragment = state.fragment + ictx.whitespaceIsLF = c == '\n' + if c != '\n': + ictx.whitespaceIsLF = false of WHITESPACE_PRE_LINE: if c == '\n': ictx.flushLine(state) elif ictx.whitespacenum < 1: + ictx.whitespaceIsLF = false ictx.whitespacenum = 1 ictx.whitespaceFragment = state.fragment of WHITESPACE_PRE, WHITESPACE_PRE_WRAP: #TODO whitespace type should be preserved here. (it isn't, because # it would break tabs in the current buffer model.) + ictx.whitespaceIsLF = false if c == '\n': ictx.flushLine(state) elif c == '\t': @@ -683,6 +700,8 @@ proc processWhitespace(ictx: var InlineContext, state: var InlineState, else: inc ictx.whitespacenum ictx.whitespaceFragment = state.fragment + # set the "last word's last rune width" to the previous rune width + state.lastrw = state.prevrw func initInlineContext(bctx: var BlockContext, space: AvailableSpace, bfcOffset: Offset, root: RootInlineFragment): InlineContext = |