Skip to content

TextTruncateEllipsis abnormally truncates strings with multi-byte UTF-8 characters #4283

Closed
@glenvan

Description

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

I found something odd with widget.Label when using .Truncate = fyne.TextTruncateEllipsis and multi-byte UTF-8 characters: a number of trailing characters are missing or not rendered according to the number of bytes in the multi-byte character.

For example, a two-byte chacter like 'Š' will trim 1 character from the end of the string, a three-byte character like '∞' will trim two characters, and a four-byte character like '🪃' will trim three characters from the end of the string.

Note that I'm not talking about long labels that need to be truncated based on available screen size – I'm talking about any label. It just needs to have multi-byte characters present and be using fyne.TextTruncatedEllipsis.

How to reproduce

  1. label := widget.NewLabel("∞ is more than 12345") or use your favorite multi-byte UTF-8 character
  2. label.Truncation = fyne.TextTruncateEllipsis
  3. Add the label to your layout and run

Screenshots

Example code in action:

UTF-8 Multi-byte Ellipsis Truncation (macOS 13 6)

UTF-8 Multi-byte Ellipsis Truncation (Windows 10)

Example code

package main

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()

	w := a.NewWindow("UTF-8 Multi-byte Ellipsis Truncation")
	w.SetMaster()

	labelTruncateOff := widget.NewLabel("TextTruncateOff")
	labelTruncateOff.TextStyle.Bold = true
	labelTruncateClip := widget.NewLabel("TextTruncateClip")
	labelTruncateClip.TextStyle.Bold = true
	labelTruncateEllipsis := widget.NewLabel("TextTruncateEllipsis")
	labelTruncateEllipsis.TextStyle.Bold = true
	labelTruncateEllipsis.TextStyle.Italic = true

	label1Byte := widget.NewLabel("1-byte")
	label1Byte.TextStyle.Bold = true
	label2Byte := widget.NewLabel("2-byte")
	label2Byte.TextStyle.Bold = true
	label3Byte := widget.NewLabel("3-byte")
	label3Byte.TextStyle.Bold = true
	label4Byte := widget.NewLabel("4-byte")
	label4Byte.TextStyle.Bold = true

	// Note: Monospace is used here because it seems to support more of unicode than the bundled
	// Noto fonts, it's not critical to reproduce the issue

	testLabel1 := widget.NewLabel("x 0123456789")
	testLabel1.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel1.Truncation = fyne.TextTruncateOff

	testLabel2 := widget.NewLabel("Š 0123456789")
	testLabel2.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel2.Truncation = fyne.TextTruncateOff

	testLabel3 := widget.NewLabel("∞ 0123456789")
	testLabel3.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel3.Truncation = fyne.TextTruncateOff

	testLabel4 := widget.NewLabel("🪃 0123456789")
	testLabel4.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel4.Truncation = fyne.TextTruncateOff

	testLabel5 := widget.NewLabel("x 0123456789")
	testLabel5.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel5.Truncation = fyne.TextTruncateClip

	testLabel6 := widget.NewLabel("Š 0123456789")
	testLabel6.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel6.Truncation = fyne.TextTruncateClip

	testLabel7 := widget.NewLabel("∞ 0123456789")
	testLabel7.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel7.Truncation = fyne.TextTruncateClip

	testLabel8 := widget.NewLabel("🪃 0123456789")
	testLabel8.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel8.Truncation = fyne.TextTruncateClip

	testLabel9 := widget.NewLabel("x 0123456789")
	testLabel9.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel9.Truncation = fyne.TextTruncateEllipsis

	testLabel10 := widget.NewLabel("Š 0123456789")
	testLabel10.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel10.Truncation = fyne.TextTruncateEllipsis

	testLabel11 := widget.NewLabel("∞ 0123456789")
	testLabel11.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel11.Truncation = fyne.TextTruncateEllipsis

	testLabel12 := widget.NewLabel("🪃 0123456789")
	testLabel12.TextStyle = fyne.TextStyle{Monospace: true}
	testLabel12.Truncation = fyne.TextTruncateEllipsis

	w.SetContent(container.NewStack(container.NewGridWithColumns(
		4,
		widget.NewLabel(" "),
		labelTruncateOff,
		labelTruncateClip,
		labelTruncateEllipsis,
		label1Byte,
		testLabel1,
		testLabel5,
		testLabel9,
		label2Byte,
		testLabel2,
		testLabel6,
		testLabel10,
		label3Byte,
		testLabel3,
		testLabel7,
		testLabel11,
		label4Byte,
		testLabel4,
		testLabel8,
		testLabel12,
	)))

	w.ShowAndRun()
}

Fyne version

2.4.0

Go compiler version

1.21.1

Operating system and version

Windows 10, macOS Ventura 13.6

Additional Information

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions