From 36a39f7d38b123b147b7a8aed27f3fbd36866900 Mon Sep 17 00:00:00 2001 From: Chris Waldon Date: Thu, 20 Jul 2023 14:46:49 -0400 Subject: [PATCH] text: handle shaping string containing only newline This commit ensures that we properly handle the case in which an input string is only a newline character. We now make a run of text by shaping a space rune and then drop the glyph/rune data from the space (keeping the line height and such). The prior behavior would shape zero runes, resulting in no output runs, and thus our logic for synthesizing a glyph for the newline would never execute while iterating the runs. I tried to restructure to instead catch whether there were zero runs after the iteration, but it came out much uglier and harder to understand that way. Signed-off-by: Chris Waldon --- text/gotext.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/text/gotext.go b/text/gotext.go index 3fb0994f..700370b2 100644 --- a/text/gotext.go +++ b/text/gotext.go @@ -525,10 +525,23 @@ func calculateYOffsets(lines []line) { // LayoutRunes shapes and wraps the text, and returns the result in Gio's shaped text format. func (s *shaperImpl) LayoutRunes(params Parameters, txt []rune) document { hasNewline := len(txt) > 0 && txt[len(txt)-1] == '\n' + justNewline := false if hasNewline { txt = txt[:len(txt)-1] + if len(txt) == 0 { + // If we only have a newline, shape a space to get line metrics. + txt = []rune{' '} + justNewline = true + } } ls, truncated := s.shapeAndWrapText(params, replaceControlCharacters(txt)) + if justNewline { + // We shaped a space to get proper line metrics, but we need to drop + // the rune/glyph info since it isn't actually part of the text. + ls[0][0].Glyphs = ls[0][0].Glyphs[:0] + ls[0][0].Runes.Count = 0 + ls[0][0].Advance = 0 + } didTruncate := truncated > 0 || (params.forceTruncate && params.MaxLines == len(ls))