Draw string and right to left text

BlitzMax Forums/BlitzMax Programming/Draw string and right to left text

Robb(Posted 2008) [#1]
I'm writing a multi-lingual app that needs to display text via the drawtext command however I am having serious issues when I need to display right to left text such as arabic or hebrew.

Firstly, although the text appears correctly in the IDE, drawtext writes the text in the wrong direction (the letters of the word remain correct however they are written from left to right so the word is incorrect)

I added a function to reverse the letters of the string before displaying it with drawtext and while the order is then correct, another issue occurs. For arabic in particular the letters are drawn in their isolated forms and the flow of the word is destroyed.

I believe this is happening because of the vowel marks found in Arabic and Hebrew (Harakat and Niqqud). When I draw hebrew script the niqqud marks are displayed in the wrong place.

Is there any known way of fixing this error? Support for these two languages is an important part of my app.

I'd post some test code but the forum mangles the arabic and hebrew text :p


tonyg(Posted 2008) [#2]
Have you considered a custom bitmap font system rather than drawtext?


skidracer(Posted 2008) [#3]
I'm interested in what support is required, if you can build modules you may want to try the following cludge and perhaps post or send me a screen-shot of what is still wrong.

brl.mod/max2d.mod/imagefont.bmx[83]:
	Global reversefont
	
	Method Draw( text$,x#,y#,ix#,iy#,jx#,jy# )

		For Local i=0 Until text.length
		
			Local n=CharToGlyph( text[i] )
			If n<0 Continue
			
			Local glyph:TImageGlyph=LoadGlyph(n)
			Local image:TImage=glyph._image
			
			If reversefont
				x:-glyph._advance*ix
				y:-glyph._advance*jx
			EndIf
			
			If image
				Local frame:TImageFrame=image.Frame(0)
				If frame
					Local tx#=glyph._x*ix+glyph._y*iy
					Local ty#=glyph._x*jx+glyph._y*jy			
					frame.Draw 0,0,image.width,image.height,x+tx,y+ty
				EndIf
			EndIf
			
			If Not reversefont
				x:+glyph._advance*ix
				y:+glyph._advance*jx
			EndIf
		Next
		
	End Method


after replacing the Draw method with the above rebuild modules and test like so:

Graphics 640,480

TImageFont.reversefont=True

DrawText "Hello",200,0
Flip

WaitKey 



Robb(Posted 2008) [#4]
Thanks for the replies.

I tried the code you suggested however it produces the same error as my own string reverse code.

This image should show what I mean.


The top pair show the arabic error. The upper word shows how the text should be displayed and the lower shows how Blitz draws it. Each letter in arabic has a different version depending on where in the word it is and blitz only seems to be drawing the isolated letters.

The second pair show the hebrew error. This one isnt so bad but the vowel markers on the lower word are not in the right place. If I use a font other than times new roman then these marks are drawn even further left as a separate character altogether.


Brucey(Posted 2008) [#5]
blitz only seems to be drawing the isolated letters.

That's because it's splitting the string into individual letters to get the glyph, and then draw it on the screen.


smilertoo(Posted 2008) [#6]
if you want it to pick letters based on what letter its next to you're going to have to write a routine to handle every option.


Warpy(Posted 2008) [#7]
So to fix this, you'd probably have to use an external library that can render text for you, such as Cairo, which I note brucey's written a wrapper for, or do it the really hard way and work it all out yourself.


skidracer(Posted 2008) [#8]
Robb, is it possible for you to email me some source code featuring those test strings, as I would like to see Blitz support both scripts natively if possible.


Robb(Posted 2008) [#9]
Thanks for all of the replies. I had wondered if it was the draw routine itself that was separating the string because the IDE displays it perfectly.

Skidracer, I've sent you an email :-D


skidracer(Posted 2008) [#10]
I've just tested with Brucey's Cairo module and unfortunately same deal, from the cairo docs:


The functions with text in their name form cairo's toy text API. The toy API takes UTF-8 encoded text and is limited in its functionality to rendering simple left-to-right text with no advanced features. That means for example that most complex scripts like Hebrew, Arabic, and Indic scripts are out of question. No kerning or correct positioning of diacritical marks either. The font selection is pretty limited too and doesn't handle the case that the selected font does not cover the characters in the text. This set of functions are really that, a toy text API, for testing and demonstration purposes. Any serious application should avoid them.

The functions with glyphs in their name form cairo's low-level text API. The low-level API relies on the user to convert text to a set of glyph indexes and positions. This is a very hard problem and is best handled by external libraries, like the pangocairo that is part of the Pango text layout and rendering library. Pango is available from http://www.pango.org/.



I think instead of tackling Pango support ( unfortunately lgpl and glib dependent ) it may be easier to use native OS text functions for solving this problem.


Warpy(Posted 2008) [#11]
As far as I can tell you might have to require Pango eventually on linux anyway, if [a http://en.wikipedia.org/wiki/Wikipedia:Enabling_complex_text_support_for_Indic_scripts#GNOME]this wikipedia help page[/a] is correct.


Brucey(Posted 2009) [#12]
FYI, I have created a module which formats strings for displaying correctly using DrawText.

There's a small example which demonstrates usage.