[openbox] Patches: Xft and i18n enhancements

Ben Jansens ben at orodu.net
Wed Apr 2 21:10:38 EST 2003


On Thu, Apr 03, 2003 at 02:44:43AM +0200, Mike FABIAN wrote:
> Here are some patches to improve Xft support and Internationalisation of
> openbox.
> 
> Please review.
> 
> I found the following problems which I tried to solve:
> 
> 1) None of the translations work in UTF-8 locales,
> --------------------------------------------------
>    and Japanese, Chinese, Korean never work with Xft
>    -------------------------------------------------
> 
> When Xft is disabled and XmbDrawString is used, UTF-8 strings are
> expected by XmbDrawString but as the Japanese translations in
> openbox.cat are in EUC-JP encoding and no conversion to UTF-8 is
> performed in this case, Japanese just displays as Garbage in
> ja_JP.UTF-8 locale. The same problem exists in other UTF-8 locales
> like de_DE.UTF-8 for example.
> 
> If Xft is enabled, it doesn't work either, because XftDrawString8 is
> always used, which will work neither for EUC-JP encoded Japanese
> strings nor for UTF-8 encoded strings. Currently it works only for
> 8bit locales when Xft is enabled.
> 
> There are already XftDrawStringUtf8() functions in the source code,
> but they are all within
> 
>      #ifdef XFT_UTF8
>           [...]
>      #else
> 
> and XFT_UTF8 is never defined because there is no proper configure
> check for XftDrawStringUtf8 yet. There were already some comments
> in configure.in about XftDrawStringUtf8, but not working check was
> done.
> 
> I fixed this with the attached openbox-2.2.3-configure-utf8.diff.
> 
> Now, when Xft is enabled and XFT_UTF8 is defined, XftDrawStringUtf8 is
> used, but the translations still display as garbage because the
> openbox.cat files are not in UTF-8 and no translation is performed.
> 
> I fixed this by converting all translations to UTF-8 before building
> openbox with the attached script nls-iconv.
> 
> Now the translations work in all locales with Xft enabled when
> XftDrawStringUtf8 is supported.
> 
> But now it won't work anymore in non-UTF-8 locales with Xft disabled
> when only XmbDrawString is available. To fix this, I added some helper
> functions which convert from UTF-8 to locale encoding and the other
> way round.
> 
> I implemented these conversions using iconv and nl_langinfo(CODESET)
> which may not be available on every platform.
> I have not yet added a configure check for iconv and nl_langinfo,
> it may be necessary to improve this to make it more portable.
> 
> But somehow conversion is necessary.
> 
> One could of course switch to using gettext instead of catgets for the
> translations. gettext can automatically convert to locale encoding.
> But locale encoding wouldn't work with XftDrawStringUtf8() and there
> is no locale specific variant of XftDrawString. Even if one 
> switched to gettext it would probably still be easiest to keep the strings
> which are fed into BFont::drawString in UTF-8 always
> (bind_textdomain_codeset() could be used to set the output of gettext
> to UTF-8).
> 
> But apart from translations there are other files read by openbox, for
> example ~/.openbox/menu. I have Japanese and in UTF-8 encoding in
> ~/.openbox/menu which always works fine when XftDrawStringUtf8() is used
> but needs to converted to EUC-JP when XmbDrawString() is used and the
> locale is ja_JP.eucJP. Here a conversion function is needed as well.
> 
> It is probably best to require files like ~/.openbox/menu to be either
> UTF-8 or ASCII only, because this makes it much easier. Allowing other
> encodings would make it necessary to introduce tags in these files to
> indicate the encoding parse these tags and convert. I believe it is
> much simpler just to require all files read by openbox to be UTF-8
> encoded (or ASCII only) always.
> 
> Other remaining stuff where a conversion is necessary:
> 
> The time string printed in the Toolbar is created in Toolbar.cc by
> 
>     if (! strftime(tlocal, 1024, screen->getStrftimeFormat(), tt))
> 
> and strftime creates it's output in locale encoding. I.e.  "10:48 PM"
> in a Japanese locale will have "AM" replaced by the Japanese word for
> "Afternoon", which will be in EUC-JP encoding when running in
> ja_JP.eucJP locale and UTF-8 encoding when running in ja_JP.UTF-8
> locale.
> 
> I fixed this by converting the output of strftime from locale encoding
> to UTF-8.
> 
> The inverse problem occurs with the output when the "--help" option
> is used
> 
>     openbox --help
> 
> and
> 
>     bsetroot --help 
> 
> also use translated messages from openbox.cat. As I have converted all
> openbox.cat files to UTF-8, these messages looked OK in UTF-8 locales
> but not in non-UTF-8 locales.  I fixed this by converting from UTF-8
> to locale encoding here.
> 
> 2) harcoded fonts for Xft won't work automatically for many languages.
> ----------------------------------------------------------------------
> 
> Currently the Fonts are opened with XftFontOpen() when using Xft.
> 
> That way it is not possible to specify generic aliases for Fonts like
> "sans", "serif" or "monospaced" in the openbox style files which has several
> disadvantages.
> 
> If you specify a really existing font family like "Luxi Sans", the
> "Luxi Sans" font will be used if it exists, even if it doesn't have
> enough glyphs for the language used. A family name specified directly
> has highest priority. Therefore you will see garbage when using
> Japanese and specifying a font like "Luxi Sans" or "Arial".
> 
> But if the following method to open a Xft font is used:
> 
>    XftPattern *pattern;
>    pattern = XftNameParse(_family.c_str());
>    pattern = XftFontMatch(_display, _screen->getScreenNumber(), pattern, NULL);
>    _xftfont = XftFontOpenPattern(_display, pattern);
> 
> one can also specify one of the generic aliases "sans", "serif", or
> "monospaced" as the family name and a font suitable for the language
> used will be selected automatically according to the rules in
> /etc/fonts/fonts.conf. For example if "sans" is specified and the
> language is Japanese and /etc/fonts/fonts.conf contains 
> 
>     <!--
>       Accept deprecated 'sans' alias, replacing it with 'sans-serif'
>     -->
>             <match target="pattern">
>                     <test qual="any" name="family">
>                             <string>sans</string>
>                     </test>
>                     <edit name="family" mode="assign">
>                             <string>sans-serif</string>
>                     </edit>
>             </match>
> 
>      [...]
> 
>             <alias>
>                     <family>sans-serif</family>
>                     <prefer>
>                             <family>Verdana</family>
>                             <family>Bitstream Vera Sans</family>
>                             <family>Nimbus Sans L</family>
>                             <family>Luxi Sans</family>
>                             <family>Arial</family>
>                             <family>Helvetica</family>
>                             <family>Kochi Gothic</family>
>                             <family>AR PL KaitiM GB</family>
>                             <family>AR PL KaitiM Big5</family>
>                             <family>Baekmuk Gulim</family>
>                             <family>Baekmuk Dotum</family>
>                             <family>SimSun</family>
>                             <family>HanyiSong</family>
>                             <family>ZYSong18030</family>
>                     </prefer>
>             </alias>
> 
> The Japanese font "Kochi Gothic" will be selected automatically
> because it is the first font in the list of preferred faces for
> sans-serif which supports Japanese.  If the language is English and
> the Microsoft Webfonts are installed, "Verdana" will be used, if they
> are not installed, the next existing font in this list which supports
> English is used.
> 
> I.e. apart from the advantage that a suitable font for the language
> used is automatically selected, a generic alias like "sans" has also
> the advantage that it selects the preferred sans-serif font
> automatically. A user can easily add
> 
>             <alias>
>                     <family>sans-serif</family>
>                     <prefer>
>                             <family>Arial</family>
>                     </prefer>
>             </alias>
>      
> into his personal ~/.fonts.conf file and will get "Arial" in all
> applications which specify "sans" or "sans-serif". I.e. if all Openbox
> style files specify "sans" and not specific fonts like "Arial", it is
> much easier for a user to choose his favorite font and one will get
> more consistent results throughout the system because other
> applications like KDE3 or Gnome2 also usually use generic aliases like
> "sans" by default, therfore editing a few lines into ~/.fonts.conf
> affects almost everything.
> 
> I attached a patch for the openbox style files to use the generic
> alias "sans" (openbox-2.2.3-styles.diff).
> 
> 3) many options possible in Xft font patterns cannot be used currently
> ----------------------------------------------------------------------
> 
> When fonts are opened using XftFontOpenPattern() as described above,
> many options can easily be specified in the style files
> which could not be used with the way Xft fonts were opened before.
> For example one can specify a font like:
> 
>     *xft.font:	sans:size=20:slant=100:weight=200:antialiasing=false:hinting=true
> 
> I.e. the xft.size option and the "bold" and "italic" parameters of
> xft.flags are superfluous. One can already specify that and more in
> xft.font when XftFontOpenPattern() is used.
> 
> I think it makes sense to remove xft.size and keep xft.flags only for
> extra options like "shadow" which cannot be expressed in the font
> pattern directly.
> 
> My patch doesn't yet remove xft.size and the "bold" and "italic"
> parameters of xft.flags, but effectively disables this already.
> 
> ----------------------------------------------------------------------
> 
> What do you think about these patches?
> 
> Maybe something like that can be applied to Openbox?
> 

When I started hacking on Openbox 2, I really didn't have the slightest clue
what was going on with locales vs UTF-8 etc, so when I started adding UTF-8
support, I went about things all wrong. Not to mention the use of catgets.

I appreciate the informative email. I have since learnt the err of how xft
fonts were handled in the Openbox 2 styles, how they're opened, and about
such font aliases. Openbox 3 is going to be much better for this.
 a) I am using gettext instead of catgets
 b) All translations will be read in UTF-8:
    bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
 c) Not using Xlib font routines at all. Only using the Xft2 font routines,
    so UTF-8 can always be drawn.
 d) All strings will be treated as UTF-8, so menus etc will all need to be in
 	UTF-8 format.
 e) The few strings I get from window hints for display, which are not in
    UTF-8 are immediately converted to UTF-8 using the glib conversion
	routines.
 f) Fonts are specified in the rc file using simply a string, so the font
    you choose can be as fancy or as simple as you want. The fallback font
	will be "sans" or a variation of "sans" so multiple languages should
	perform better here too.
 g) I think that's it. I'd appreciate if someone with some
    multibyte/non-english fonts and skills could try out openbox3 from CVS
	in the near future. (Its having some build issues at the moment, as I'm
	removing the use of automake, but in the next few days everything should
	be rocking again.)

Thanks,
Ben
-- 
I am damn unsatisfied to be killed in this way.

http://www.icculus.org/openbox/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://icculus.org/pipermail/openbox/attachments/20030402/84db7bf8/attachment.pgp>


More information about the openbox mailing list