We need to support rendering bitmap fonts for languages such as Arabic, Hebrew which the rendering of a text starts from right to left.
For that I can contribute but I need some help from the graceful stuff of this framework.
RtL rendering is only half of what needs to be done. The problem with Arabic and Hebrew is that they also use ligatures, which means an entirely new glyph that replaces two adjacent glyphs.
I'd appreciate any contributions in this direction, but keep in mind that this is indeed a very hard problem to solve. I had to solve it once for a commercial product, and it took me about a month to get all the things right. This was on desktop machines, so performance wasn't that big of an issue.
Let me know what info you need from our end.
I have a working example after a massive hard working on building an ArabicStringTransformer.
I used the classes from the framework for the rendering:
BitmapFont
BitmapFontCache
wow that sounds fantastic! can you share your work?
On Oct 6, 2013 6:49 PM, "ashrafsa" [email protected] wrote:
I have a working example after a massive hard working on building an
ArabicStringTransformer.—
Reply to this email directly or view it on GitHubhttps://github.com/libgdx/libgdx/issues/787#issuecomment-25771583
.
@ashrafsa Could you please share with us those changes ?
I'm working on a game in LibGdx and I have added support for RTL text.
I have RTL text flipped properly and I have TextFields that mostly work with RTL input too.
I'd love to share that code if it would help.
Would be nice if you could create a PR or a diff or upload your code somewhere, so it doesn't get lost :)
Here is a gist:
https://gist.github.com/EtK2000/9be88488d70e9bf399b18cff444a9036
When I finish all the TODOs I'll create a PR.
RTL languages like Arabic not just direction from RIGHT to LEFT, but how connect their letters with each other and some letters as a block with 2 or more letters.
So, I do it with fully supporting RTL language.
https://github.com/CrowniAPIs/libGDX-RTL-Language
@CrowniAPIs that's fantastic work!
I really hope this will be added in.. it would also help for ajapanese and chinese since those languages also have glyphs transforming as you type.
@CrowniAPIs that is very interesting! Can you explain how it works?
@NathanSweet
There is four types of Arabic letters:
1X. No connection with any glyphs. _(one letter has 0 connection shape)._
2X. Connection with previous glyph only. _(one letter has 2 connection shapes)._
3X. Connection with previous and next glyph with change it into new glyph as block of two or more letters. _(one letter has 2 connection shapes)._
4X. Connection with previous and next glyph. _(one letter has 4 connection shapes)._
I created ArCharCode which contains all char integer code and own case for each one.
In ArFont which is logic, I checked every char input what is its case. Then according to its case I added correct glyph into array. Finally glyphs array converts to string after reverse it.
.... Sorry for my bad English ....
@CrowniAPIs does this have support for other languages that combine letters, or only Arabic?
@EtK2000 In fact I don't know about connection cases of other RTL languages like Japanese and Chinese. So, If I know these languages cases, I think its easy to support them.
@CrowniAPIs Thanks. BitmapFont has a getGlyphs
method, which is used by GlyphLayout. This allows the font to specify the glyphs for a string. Maybe you can extend BitmapFont and put the logic there?
CJK languages can be displayed as LTR and are already supported.
@NathanSweet Good to hear that. I will add new branch as a default branch instead of master and put new code with my logic to do that with inheritance of BitmapFont
directly. I think your hint is better than my thinking in exist code. Thanks.
I hope that will be added into libGDX as a default support.
Great! To have the best chance of being merged, ideally it is self contained and doesn't affect much other code/API.
I misspoke, the getGlyphs
method is actually on BitmapFontData, not BitmapFont. I'd expect you would have an ArabicBitmapFontData.
There is also BitmapFontData getWrapIndex
. The default implementation uses isBreakChar
and isWhitespace
, but you can also replace getWrapIndex
, like what is done for Chinese in this test (thhe SimplifiedChinese class is in the same file):
https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/extensions/FreeTypeIncrementalTest.java#L55-L59
For testing wrapping, there is BitmapFontTest, just make this condition true:
https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/BitmapFontTest.java#L96
There isn't a great separation between the BitmapFontData and the getGlyphs
/getWrapIndex
methods. For example, if you wanted to do Arabic with FreeType, FreeTypeFontGenerator generateFont
takes a FreeTypeBitmapFontData, so you'd need to subclass FreeTypeBitmapFontData to provide the Arabic getGlyphs
/getWrapIndex
methods. Maybe instead of providing ArabicBitmapFontData, it can just be an Arabic class with static methods, eg:
BitmapFont font = new BitmapFont(new BitmapFontData(fontFile, true) {
public void getGlyphs (GlyphRun run, CharSequence str, int start, int end, boolean tightBounds) {
Arabic.getGlyphs(run, str, start, end, tightBounds);
}
public int getWrapIndex (Array<Glyph> glyphs, int start) {
return Arabic.getWrapIndex(glyphs, start);
}
}, fontRegion, true);
FreeTypeFontGenerator generator = ...
FreeTypeFontParameter parameters = ...
BitmapFont freeTypeFont = generator.generateFont(parameters, new FreeTypeBitmapFontData() {
public void getGlyphs (GlyphRun run, CharSequence str, int start, int end, boolean tightBounds) {
Arabic.getGlyphs(run, str, start, end, tightBounds);
}
public int getWrapIndex (Array<Glyph> glyphs, int start) {
return Arabic.getWrapIndex(glyphs, start);
}
});
Later we could refactor this to be nicer, eg:
BitmapFontData fontData = new BitmapFontData(fontFile, true);
fontData.setShaping(new ArabicShaping());
BitmapFont font = new BitmapFont(fontData, fontRegion, true);
"Shaping" is the process of converting Unicode text to glyph indices and positions. Your way of handling shaping for Arabic sounds fine, if it indeed covers everything needed for Arabic. For other languages, and as an alternative solution for Arabic, we would do the same but using HarfBuzz.
@NathanSweet THANK YOU VERY MUCH. I will do it soon. THANK YOU AGAIN.
@CrowniAPIs hi, are you still working on it? I need this too... thx
@CrowniAPIs I see your repository from December 2017. Are you still working on this / planning to merge it in?
Most helpful comment
Great! To have the best chance of being merged, ideally it is self contained and doesn't affect much other code/API.
I misspoke, the
getGlyphs
method is actually on BitmapFontData, not BitmapFont. I'd expect you would have an ArabicBitmapFontData.There is also BitmapFontData
getWrapIndex
. The default implementation usesisBreakChar
andisWhitespace
, but you can also replacegetWrapIndex
, like what is done for Chinese in this test (thhe SimplifiedChinese class is in the same file):https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/extensions/FreeTypeIncrementalTest.java#L55-L59
For testing wrapping, there is BitmapFontTest, just make this condition true:
https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/BitmapFontTest.java#L96
There isn't a great separation between the BitmapFontData and the
getGlyphs
/getWrapIndex
methods. For example, if you wanted to do Arabic with FreeType, FreeTypeFontGeneratorgenerateFont
takes a FreeTypeBitmapFontData, so you'd need to subclass FreeTypeBitmapFontData to provide the ArabicgetGlyphs
/getWrapIndex
methods. Maybe instead of providing ArabicBitmapFontData, it can just be an Arabic class with static methods, eg:Later we could refactor this to be nicer, eg:
"Shaping" is the process of converting Unicode text to glyph indices and positions. Your way of handling shaping for Arabic sounds fine, if it indeed covers everything needed for Arabic. For other languages, and as an alternative solution for Arabic, we would do the same but using HarfBuzz.