-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Text Refactor
Andy Williams edited this page Apr 15, 2021
·
12 revisions
The next major release (probably Abelour) will feature a refactor of the text handling parts to address the issues and limitations encountered.
Text handling and typesetting is one of the hardest and most complex piece of a UI toolkit. The current implementation was a good first step, but as the project has matured and developers have shared their feedback, it is clear that we're ready to take the next step.
- No rich text support; eg bulleted/numbered lists, headings, paragraphs, images, links
- Hard to convey semantic meaning of text; eg cannot configure widgets to be H1-H6, Subtitle, Body, Caption, et al. (https://gophers.slack.com/archives/CK5U4BU87/p1607524897399600, https://gophers.slack.com/archives/CK5U4BU87/p1610012275206000)
- No support for mixing styles; eg neither widget.Label nor widget.Entry cannot show a clickable hyperlink
- Difficult for devs to customize existing widgets; eg cannot create center-aligned, widget.Entry (https://gophers.slack.com/archives/CB4QUBXGQ/p1554989104009500, https://gophers.slack.com/archives/CK5U4BU87/p1603126884485900) <- Andy is not sure this is a problem to solve, as most of our widgets are not customisable in this way.
- Difficult for devs to create custom text widgets and access toolkit behaviour such as wrapping, selecting, and editing. For example, a dev cannot render multiple editable lines in a custom font without re-implementing textProvider and Entry.
- Performance is low as the entire text must be rendered - could be improved with "collectionification" (applying lessons learned from caches in collection widgets) - applies to TextGrid as well
The goal of this project is to develop a text handling solution that will have;
- Extensibility - developers can create custom widgets and leverage the text handling utilities
- Functionality - developers can provide a rich user experience
- Testability & Performance - developers can test and benchmark their apps across all supported languages, locales, and regions.
Possibly out of scope for a refactor project, but we need to keep in mind:
- Accessibility - users can read and write text via accessibility tools (eg screen readers)
- Internationalization - users can configure an app to their mother-tongue
Libraries of note that we should checkout to understand the complexities ahead:
- Harfbuzz - https://harfbuzz.github.io/
- Pango - https://pango.gnome.org/
- Partially completed Go library https://github.com/benoitkugler/textlayout (a manual port or harfbuzz and other features)
- Content Hinting - enable devs to hint at the content of a UI Text element to leverage platforms APIs for providing suggestions (from dictionary or contacts), check spelling, keyboard tayloring (numeric vs alphanumeric, action button type, input language)
- Mathematical expressions
- Wrapping Binding - takes a mode, width, and string binding as inputs, then splits the text from the binding into lines less than or equal to the given length depending on the wrapping mode, providing as output a list binding which can be bound to a text line list collection. <- Andy notes here that whatever we do should not require binding, but could have binding helpers.
- Using a
strings.Builder
orbytes.Buffer
for providing an efficient way to append a lot of information to the string (like when typing). It would also open up for havingcanvas.Text
be anio.Writer
(andio.Reader
In the case of the buffer). - Text Measurement Cache - measuring text is a time consuming operation and is called frequently, we could see a performance increase by caching the result for a given input (text, font, size, and style).
- Adding
MeasureTextDistanceToBaseline
function (or something like this) alongsideMeasureText
or driver equivalent to enable future alignment according to widgets text baseline. - String Bundling - to assist in internationalization
fyne bundle
or a newfyne translate
could be used to bundle string resources into the binary in such a way that they can be keyed with language tag (eg. "en-US") and ID (eg. "welcome_message") - We will need to support at a minimum RTL (right to left) as well as the default LTR, but bi-directional will be required for a complete solution
- Shaping is exceptionally hard - I recommend everyone become familiar with Harfbuzz and pango
- Gio project is keen to collaborate on these problems so a shared solution could be created for Go text rendering (https://gophers.slack.com/archives/CM87SNCGM/p1617180821092100)