[Mono-dev] Complex script / international support in Winforms/libgdiplus
jonathan.l.anderson at gmail.com
Thu Jan 22 22:34:35 EST 2009
I posted a note on mono-devel a couple months ago about possible work on
libgdiplus to get pango support working well. I've been working on
doing just that for a little while now, and I'm getting close to having
something that does reasonably well within the gdi+ framework. I don't
have all the formatting options supported yet, but then again, it
doesn't look like the current cairo text module does either.
With getting pango working, it will be able to render complex scripts
correctly to support languages like Arabic, Thai, Hebrew, Burmese, etc.
I'm currently doing some volunteer work for SIL Internatioal
(www.sil.org) where we do lots of work with minority and complex
scripts, so this support is essential for widespread adoption of mono,
which we're using to do ports of windows forms apps.
However, I've discovered that getting pango working in libgdiplus is
only part of the story for getting good complex script support in
winforms. With pango in libgdiplus, you get well-rendered strings for
any controls that just draw a whole string, which is most controls,
although some need work on right-to-left support. The TextBox control
and any controls that share the TextBoxBase implementation
(MaskedTextBox, RtfTextBox) are where the biggest problems are.
The problem is that the implementation of the TextBox makes some very
basic assumptions that don't work for complex scripts, i.e. the width of
a string is not necessarily equal to the sum of the widths of the
individual characters. This can even be true for Latin fonts that use
kerning and ligatures like ae, ff, and fi. Also, separate code points
can form one grapheme (one rendered symbol). All this causes problems
with selection, caret placement, and line breaking.
Now, all that being said, I've been working on the TextBox as well to
improve the implementation. I'm not done yet, so I don't have any good
code to post here yet. One of the problems that I'm working against is
that the gdi+ interface doesn't supply the information needed to do the
TextBox correctly, that is, if I want to work with libgdiplus to make
the pango calls, I'll need to add some linux-specific functions that I
can call for text metrics. I noticed there are some other functions in
libgdiplus with "_linux" in the names, so I'm assuming that this won't
be a huge problem - otherwise, a lot of code for the cairo/pango
interaction would have to be copied into winforms.
I'm doing the extra text metrics by adding methods in the
TextBoxTextRenderer class, which seemed to be the best place to do that.
For the Windows side of things, I'm having it make calls to gdi, which
provides some better metrics than gdi+, although not quite everything
I'd like. I can fill in the rest by making best guesses which won't be
any worse than the current situation. Since complex script rendering
through gdi gets passed into uniscribe on Windows, I think that gdi may
be a good place to start, but it would probably be best to use uniscribe
directly at some point in the future for the best complex script support
in Windows. One of the problems with the vanilla gdi interface is
handling drawing bits of text in different colors like you could get
with the RtfTextBox or with any selection, whereas uniscribe provides
methods to do that sort of thing.
I just wanted to let everyone know that I'm working on this, and I
wanted to see if the direction I'm taking using TextBoxTextRenderer and
libgdiplus seemed appropriate. Also, as I'll have a good bit of code
for both libgdiplus and winforms that will depend on each other, what's
the best way for me to get it into the project once I've got it working.
I know I'll need to have all the current unit tests passing with new
code, and quite possibly some new tests. Also, I may implement the new
libgdiplus calls in cairo-text.c as well as a fallback, although they'd
be no better than the current stuff.
Thanks for reading all that,
More information about the Mono-devel-list