From 7321a7891add84e62d70392680011ca243ce3701 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 19 Jul 2024 12:16:45 -0400 Subject: [PATCH 1/3] Correctly shape input before truncating Partial fix for #4998 --- widget/richtext.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/widget/richtext.go b/widget/richtext.go index 73af8ce5ba..791aec1eed 100644 --- a/widget/richtext.go +++ b/widget/richtext.go @@ -1118,10 +1118,11 @@ func truncateLimit(s string, text *canvas.Text, limit int, ellipsis []rune) (int RunStart: 0, RunEnd: len(ellipsis), Direction: di.DirectionLTR, - Face: face.Fonts.ResolveFace('…'), + Face: face.Fonts.ResolveFace(ellipsis[0]), Size: float32ToFixed266(text.TextSize), } shaper := &shaping.HarfbuzzShaper{} + segmenter := &shaping.Segmenter{} conf := shaping.WrapConfig{} conf = conf.WithTruncator(shaper, in) @@ -1131,9 +1132,13 @@ func truncateLimit(s string, text *canvas.Text, limit int, ellipsis []rune) (int in.Text = runes in.RunEnd = len(runes) - out := shaper.Shape(in) + ins := segmenter.Split(in, face.Fonts) + outs := make([]shaping.Output, len(ins)) + for i, in := range ins { + outs[i] = shaper.Shape(in) + } - l.Prepare(conf, runes, shaping.NewSliceIterator([]shaping.Output{out})) + l.Prepare(conf, runes, shaping.NewSliceIterator(outs)) wrapped, done := l.WrapNextLine(limit) count := wrapped.Line[0].Runes.Count From d96c578e90807c164488af9ecc20ff7009e02428 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 30 Aug 2024 15:21:54 +0100 Subject: [PATCH 2/3] Correctly count the runes in a multi-run wrap Fixes #4998 --- widget/richtext.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/widget/richtext.go b/widget/richtext.go index 791aec1eed..be29331cbf 100644 --- a/widget/richtext.go +++ b/widget/richtext.go @@ -1141,7 +1141,10 @@ func truncateLimit(s string, text *canvas.Text, limit int, ellipsis []rune) (int l.Prepare(conf, runes, shaping.NewSliceIterator(outs)) wrapped, done := l.WrapNextLine(limit) - count := wrapped.Line[0].Runes.Count + count := 0 + for _, run := range wrapped.Line { + count += run.Runes.Count + } full := done && count == len(runes) if !full && len(ellipsis) > 0 { count-- From 93d4d60309d47aa5c0e253148269c0e72750c169 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 1 Sep 2024 15:45:56 +0100 Subject: [PATCH 3/3] Correct ellipse tests numbers --- widget/hyperlink_test.go | 2 +- widget/richtext_test.go | 16 ++++++++-------- widget/select_test.go | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/widget/hyperlink_test.go b/widget/hyperlink_test.go index a86a5c56fd..164d51db63 100644 --- a/widget/hyperlink_test.go +++ b/widget/hyperlink_test.go @@ -204,7 +204,7 @@ func TestHyperlink_Truncate(t *testing.T) { hyperlink.Truncation = fyne.TextTruncateEllipsis hyperlink.Refresh() texts = richTextRenderTexts(&hyperlink.provider) - assert.Equal(t, "TestingWi…", texts[0].Text) + assert.Equal(t, "TestingWit…", texts[0].Text) } func TestHyperlink_CreateRendererDoesNotAffectSize(t *testing.T) { diff --git a/widget/richtext_test.go b/widget/richtext_test.go index 82229686a8..f207c31dc5 100644 --- a/widget/richtext_test.go +++ b/widget/richtext_test.go @@ -575,7 +575,7 @@ func TestText_lineBounds(t *testing.T) { text: "foobar foobar", trunc: fyne.TextTruncateEllipsis, want: [][2]int{ - {0, 8}, + {0, 9}, }, ellipses: 1, }, @@ -688,8 +688,8 @@ func TestText_lineBounds(t *testing.T) { trunc: fyne.TextTruncateEllipsis, want: [][2]int{ {0, 6}, - {7, 15}, - {28, 36}, + {7, 16}, + {28, 37}, }, ellipses: 2, }, @@ -757,8 +757,8 @@ func TestText_lineBounds(t *testing.T) { trunc: fyne.TextTruncateEllipsis, want: [][2]int{ {0, 6}, - {7, 14}, - {26, 33}, + {7, 15}, + {26, 34}, {39, 39}, }, ellipses: 2, @@ -909,8 +909,8 @@ func TestText_lineBounds(t *testing.T) { trunc: fyne.TextTruncateEllipsis, want: [][2]int{ {0, 6}, - {7, 15}, - {28, 36}, + {7, 16}, + {28, 37}, {42, 42}, }, ellipses: 2, @@ -1041,7 +1041,7 @@ func TestText_lineBounds_variable_char_width(t *testing.T) { text: "iiiiiiiiiimmmmmmmmmm", trunc: fyne.TextTruncateEllipsis, want: [][2]int{ - {0, 8}, + {0, 9}, }, }, { diff --git a/widget/select_test.go b/widget/select_test.go index 9503b36448..70c176bca3 100644 --- a/widget/select_test.go +++ b/widget/select_test.go @@ -100,7 +100,7 @@ func TestSelect_ClipValue(t *testing.T) { r2 := cache.Renderer(text) assert.Equal(t, 1, len(r2.Objects())) - assert.Equal(t, "some…", r2.Objects()[0].(*canvas.Text).Text) + assert.Equal(t, "some …", r2.Objects()[0].(*canvas.Text).Text) } func TestSelect_Disable(t *testing.T) {