New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Displaying unicode or different language like Bengali doesn't work. #598
Comments
The building fonts do not support all languages and Bengali is one that is not included sorry. If you download a TTF don’t file and specify its path in the FYNE_FONT environment variable then you should be able to use the characters you want. “Noto Sans Bengali” would match the builtin fonts well. |
Okay, I tried with FYNE_FONT variable and it now shows letters instead of blank boxes but it's broken. I tried with few popular Bengali fonts. The result is same. |
Can you expand more please on “its broken”? If the letters are displayed what else do you expect? |
I think I used the term "letter" wrong, it's more of a font is broken. Meaning it can not render the font properly. |
As someone who knows the language can you explain what the differences are - or what a possible cause may be? It looks to me like characters are supposed to combine in some way - but that is an uneducated guess. |
Well that problem happens with some other cases like in chrome because of when the proper font is not installed on the system. But in this case I'm not sure. |
I can't read Bengali but it seems this problem is related to "text shaping" and to support it you need something like HarfBuzz |
My previous comment was a guess and now after run the demo, it seems text rendering for languages known as "complex scripts" hadn't implemented at all. |
For non-complex scripts such as Japanese or Chinese, etc. it would be enough to be able to embed a custom font in the binary using, e.g. go-bindata, if only fyne had a way to set that font other than setting FYNE_FONT. Edit: additionally support for .odf and .ttc fonts might be very useful. |
Applications can provide their own font by implementing a custom theme (like https://github.com/andydotxyz/beebui). |
Also I agree we should aim for full internationalisation in 2.0 |
Rendering "non-complex scripts" (e.g., for English, Russian, or Korean) can be done with a naïve text shaper that simply queries the font file for a glyph on a rune-by-rune basis, as long as one supplies an appropriate font file. One annoying limitation is that the SFNT format (used by TTF/OTF files) is limited to 216 glyphs, which is not enough to support all languages + emoji. Thus, even a text shaper that is limited to non-complex scripts will need to implement "font fallback" behavior in practice if one wants to properly render strings containing arbitrary languages. For the Gio project we implemented this with support for OpenType Collection files like these giant merged Noto fonts that I prepared. Alternatively, you can use the installed system fonts and read the fallback order from the system configuration (in most Linux distributions this is handled by fontconfig). The Gio project has recently run into the same text shaping limitations for "complex scripts" (e.g., for Arabic or Bengali) that are discussed in this GitHub issue. See gio#146 for a more detailed write-up and suggested path forward. Fyne will need to walk a similar path to resolve this issue. To summarize: The key components for a solution are using HarfBuzz to compute glyphs and offsets, implementing an algorithm similar to the Pango library for preparing calls to There are a few possible paths forward discussed in gio#146, summarized below:
None of these options are without drawbacks. However, resolving the HarfBuzz linking problem in one way or another would be very beneficial for a lot of Go projects—not just Fyne and Gio, but pretty much anything that needs to render arbitrary text. |
If you resign yourself to linking HB, you can simply link fribidi (with no dependencies its fairly nice) for bidi. |
I looked at HarfBuzz and I think 50% of the code is C(C++) support, like memory management, etc., that we don't need in Go, because the language provides it for us, furthermore, the HarfBuzz api isn't all that great, it suffers from being very C-like due to memory allocation problems. In Go we have the standard library "unicode", "golang.org/x/text/language", and "x/image/font". HarfBuzz uses Ragel parsers which can also be generated as Go language in stead of C. The remaining few thousands lines of code should not be too hard for a manual conversion, at least not for the basic shaping API. This could look something like this: buffer = gotesh.Buffer(text)
buffer.SetDirection(gotesh.LeftToRight)
buffer.SetScript(language.Bengali.Script());
buffer.SetLanguage(language.Bengali);
glyphInfo, glyphPosition, err := buffer.Shape(fontFace,features); Nothing there yet, but go here if you like the challenge ;) |
Unfortunately statically linking fribidi is not an option due to licensing. |
Quite right @Nik-U - we have the fallback in place so when someone loads, for example, a Japanese font, they still see the english text that the project includes etc. I think that realistically there are multiple steps -> user defined font -> app defined font -> language font -> toolkit fallback. We have avoided doing system lookups this far because a consistent experience was deemed important and some distros (particularly some lightweight Linux ones) don't even ship vector fonts by default. I did consider a massive combined font file - but this resulted in around 200MB once Japanese and Chinese (traditional and simplified) were added - which is clearly more than we can reasonably embed in binaries. |
On investigating the issue, I'd say that HarfBuzz, etc, are not the right idea, while, in stead, Graphite is: https://scripts.sil.org/cms/scripts/page.php?site_id=projects&item_id=graphite_home . In stead of having to program the language rules manually, graphite compiles them directly into the font. All that is needed is to implement a VM. That would be even easier to do in Go. |
Move from iterating on rune to glyphID. Fixes fyne-io#598
The rendering issues referred to here should be resolved in v2.3.0. The code that follows seems to render well: package main
import (
"os"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
os.Setenv("FYNE_FONT", "/Users/andy/Downloads/shruti.ttf")
a := app.New()
w := a.NewWindow("Hello")
hello := widget.NewLabel("િદ્ધની")
w.SetContent(container.NewVBox(
hello,
))
w.ShowAndRun()
} |
Great job for porting the whole of haarfbuzz from C++ to Go! You are a master amongst masters! |
I appreciate the enthusiasm, but honestly all of the thanks belong to @benoitkugler for the porting work and @whereswaldon for building most of the https://github.com/go-text/typesetting project that made this possible! |
Sorry, I had that mixed up. Honor to those who deserve it! Giants indeed! |
I'm trying to make an application using Fyne, where I need to display Bengali. But didn't find a way to display it. Is there a way to display Unicode/different language?
The text was updated successfully, but these errors were encountered: