Re: Serious bug in gdk_draw_text() ?



Stephen Ma <stephenma telus net> writes:

> When an XFree86 3.3.6 server is used with certain fonts from XFree86
> 4.1, the version clash causes many GTK programs to display squares
> instead of letters and digits.  Many applications are affected,
> including Gnumeric 0.69, Pan 0.10, XChat 1.8.2, etc.

Well, don't do that then :-)

> The root cause lies either in the old X server or in the new fonts.
> 
> However, I'm wondering why the following code in Gdk has remained
> basically untouched since at least version 0.99.  
> The code appears in gdk_draw_text() in gtk 1.2, and in
> gdk_x11_draw_text() in the latest CVS tree:

Backwards compatibility. There is no way we can change an interface
within a stable branch like 1.2.x, and there is no point in changing
it in current CVS for GTK+-2.0, since text drawing now goes through
Pango and the GdkFont is just there for backwards compatibility.
 
>   XFontStruct *xfont = (XFontStruct *) font_private->xfont;
>   XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
>   if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
>   {
>     XDrawString (drawable_private->xdisplay, drawable_private->xwindow,
> 		 gc_private->xgc, x, y, text, text_length);
>   }
>   else
>   {
>     XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow,
> 		   gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
>   }
> 
> As you can see, the problem is that, roughly speaking, if the font has
> more than 256 glyphs, the function silently assumes that you're
> passing it a string of 16-bit characters, and calls XDrawString16()
> instead of XDrawString().
> 
> Since gdk_draw_text_wc() has been officially doing the Unicode thing
> for a long while, I'm wondering why gdk_draw_text() needs do to it
> too.

Actually, gdk_draw_text_wc() draws text represented as C library
wide characters. On Linux, this encoding is ISO-10646 / Unicode,
but that isn't true for most systems.

gdk_draw_text() using a 16-bit font is something else ... what it
does (and what apps depend on it doing) is to interpret the
string (via a cast) as direct indices into the 16-bit font.

This corresponds to the way that gdk_draw_text() interprets its
argument as direct indices into a 8-bit font.

Yes, this is a somewhat strange interface, and I wouldn't accept a
patch that made it do it this way now, but we added it a long time ago
and I didn't know better :-). We probably should also have fixed it
for GTK+-1.2, even though that would have broken source compatibility
but that wasn't done either; it certainly doesn't make sense to
change it at this point.
 
> One of the fonts which cause gdk_draw_text() to misbehave is:
> 
>   -adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*
> 
> which corresponds to file
> 
>   /usr/X11R6/lib/X11/fonts/75dpi/helvR12-ISO8859-1.pcf.gz
> 
> in XFree86 4.x.  I want to emphasize again that squares get displayed
> only when you use an old Xserver (3.3.6) with the new fonts (4.x).

Apps, can be fixed by using a proper pattern.

 -adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1

The original pattern is completely nonsensical - it says,
I want -adobe-helvetica- in some random character set encoding.

XFree86-4.1 has been made to prefer iso8859-1 in such cases,
but XFree86-3.3.6

Another way of fixing applications to use gdk_load_fontset() rather
than gdk_load_font(). gdk_load_fontset() uses the Xlib
internationalization machinery. And the Xlib internationalization
machinery knows how to pick the correct encoding for your locale.

But when you use gdk_load_font() you are saying "my string contains
direct indices into the font, either 8-bit, for a 8-bit encoded
font, or 16-bit for a 16-bit encoded font." If you wild carded
the encoding for the font, then it's most likely that the encoding
that you picked doesn't correspond to the your locale, and if
you are unlucky (as you are with XFree86-3.3.6), you may get a 16-bit
font when you were expecting a 8-bit font.

Regards,
                                        Owen




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]