text: ensure runereader behaves same as string

This commit fixes a subtle discrepancy in the handling of text input
within the shaper. Text provided as an io.RuneReader with a trailing
newline would generate an extra (empty) line of text, whereas the
same input provided as a string would not.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2022-12-15 08:50:02 -05:00
committed by Elias Naur
parent 2db1a7bfb9
commit bfb47538aa
2 changed files with 34 additions and 5 deletions
+2
View File
@@ -223,6 +223,7 @@ func (l *Shaper) layoutText(params Parameters, minWidth, maxWidth int, lc system
} }
done = endByte == len(str) done = endByte == len(str)
} }
if startByte != endByte || len(l.paragraph) > 0 {
l.txt.append(l.layoutParagraph(params, minWidth, maxWidth, lc, str[startByte:endByte], l.paragraph)) l.txt.append(l.layoutParagraph(params, minWidth, maxWidth, lc, str[startByte:endByte], l.paragraph))
if truncating { if truncating {
params.MaxLines = maxLines - len(l.txt.lines) params.MaxLines = maxLines - len(l.txt.lines)
@@ -230,6 +231,7 @@ func (l *Shaper) layoutText(params Parameters, minWidth, maxWidth int, lc system
done = true done = true
} }
} }
}
if done { if done {
return return
} }
+27
View File
@@ -1,6 +1,7 @@
package text package text
import ( import (
"strings"
"testing" "testing"
nsareg "eliasnaur.com/font/noto/sans/arabic/regular" nsareg "eliasnaur.com/font/noto/sans/arabic/regular"
@@ -40,6 +41,32 @@ func TestWrappingTruncation(t *testing.T) {
} }
} }
// TestShapingNewlineHandling checks that the shaper's newline splitting behaves
// consistently and does not create spurious lines of text.
func TestShapingNewlineHandling(t *testing.T) {
// Use a test string containing multiple newlines to ensure that they are shaped
// as separate paragraphs.
textInput := "\n"
ltrFace, _ := opentype.Parse(goregular.TTF)
collection := []FontFace{{Face: ltrFace}}
cache := NewShaper(collection)
cache.LayoutString(Parameters{
Alignment: Middle,
PxPerEm: fixed.I(10),
}, 200, 200, english, textInput)
if lineCount := len(cache.txt.lines); lineCount > 1 {
t.Errorf("shaping string %q created %d lines", textInput, lineCount)
}
cache.Layout(Parameters{
Alignment: Middle,
PxPerEm: fixed.I(10),
}, 200, 200, english, strings.NewReader(textInput))
if lineCount := len(cache.txt.lines); lineCount > 1 {
t.Errorf("shaping reader %q created %d lines", textInput, lineCount)
}
}
// TestCacheEmptyString ensures that shaping the empty string returns a // TestCacheEmptyString ensures that shaping the empty string returns a
// single synthetic glyph with ascent/descent info. // single synthetic glyph with ascent/descent info.
func TestCacheEmptyString(t *testing.T) { func TestCacheEmptyString(t *testing.T) {