Fonts getting corrupted in x11drv
The attached sample program demonstrates a bug in font handling that can lead to corrupted fonts. Compile with "winegcc -g sysfont.c -lgdi32 -lcomdlg32". Run the resulting a.out, and you will see the letter "C" in the top left corner of the window, rendered in the system font. Click anywhere in the client area of the window and the letter will change its shape, even though it is still using the stock SYSTEM_FONT. The left click action creates a device context for the default printer and immediately deletes it. As part of the deletion of that device context, DeleteDC selects the stock SYSTEM_FONT into the device context. Since printer device contexts insist on scalable fonts, the existing (bitmapped) GDI font for the system font is unable to serve, so a new one is created, which ends up being based on the Tahoma (TrueType) font. On the next paint loop, when the test program calls SetFont it is the new, scalable font (based on Tahoma) that is found. The Tahoma font has different glyph codes to the System font, such that 'C' is glyph code 36 in the System font and 38 in Tahoma. Accordingly, x11drv identifies the glyph as not having been uploaded (it has uploaded glyph 36 before), and uploads it as glyph 38 based on its outline in Tahoma. The problem gets worse later on because some glyphs in the glyphset have been uploaded according to their "System" font positions (or in this case ,the same character has been uploaded in its position in both fonts). Rendering a character that uses the other glyph code results in the wrong character. You can get a mix of Tahoma and System characters appearing on the screen with the System characters displaying the shape of the wrong character. Every fix I look at seems like a horrible hack. Perhaps find_in_cache should only return bitmap fonts if the device can use them. If the caller then finds there is no bitmap font that matches it can then look for scalable fonts in the cache. -- Troy Rollo - wine(a)troy.rollo.name
* On Thu, 25 May 2006, Troy Rollo wrote:
The attached sample program demonstrates a bug in font handling that can lead to corrupted fonts. Compile with "winegcc -g sysfont.c -lgdi32 -lcomdlg32".
I'am running wine from a local src tree, so I had to compile this way: $ tools/winegcc/winegcc -Btools/winebuild/ -B/usr/bin/ -g sysfont.c -Ldlls -Llibs -Iinclude -mwindows
Run the resulting a.out, and you will see the letter "C" in the top left corner of the window, rendered in the system font. Click anywhere in the client area of the window and the letter will change its shape,
And in my case it didn't happen.
* On Thu, 25 May 2006, Saulius Krasuckas wrote:
I'am running wine from a local src tree, so I had to compile this way:
$ tools/winegcc/winegcc -Btools/winebuild/ -B/usr/bin/ -g sysfont.c -Ldlls -Llibs -Iinclude -mwindows
Sorry, -B/usr/bin is a leftover from my experiments and isn't needed here at all... I compiled app by running this: $ tools/winegcc/winegcc -Btools/winebuild/ -g sysfont.c -Ldlls -Llibs -Iinclude -mwindows BTW, now the issue is seen on my box too. Heh, it reminds my of my own bugreport [*]. Could this be related, Troy? [*] http://bugs.winehq.org/show_bug.cgi?id=5248
On Thursday 25 May 2006 20:51, Saulius Krasuckas wrote:
BTW, now the issue is seen on my box too. Heh, it reminds my of my own bugreport [*]. Could this be related, Troy?
No, your problem is definitely different. -- Troy Rollo - wine(a)troy.rollo.name
On Thu, May 25, 2006 at 04:49:04PM +1000, Troy Rollo wrote:
The attached sample program demonstrates a bug in font handling that can lead to corrupted fonts. Compile with "winegcc -g sysfont.c -lgdi32 -lcomdlg32". Run the resulting a.out, and you will see the letter "C" in the top left corner of the window, rendered in the system font. Click anywhere in the client area of the window and the letter will change its shape, even though it is still using the stock SYSTEM_FONT.
The left click action creates a device context for the default printer and immediately deletes it. As part of the deletion of that device context, DeleteDC selects the stock SYSTEM_FONT into the device context. Since printer device contexts insist on scalable fonts, the existing (bitmapped) GDI font for the system font is unable to serve, so a new one is created, which ends up being based on the Tahoma (TrueType) font. On the next paint loop, when the test program calls SetFont it is the new, scalable font (based on Tahoma) that is found.
Nice catch! This should fix it. Huw. -- Huw Davies huw(a)codeweavers.com --- dlls/gdi/freetype.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) e50bddf2d422b99e526979561713474cd489ba90 diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c index 62b55ce..f76138e 100644 --- a/dlls/gdi/freetype.c +++ b/dlls/gdi/freetype.c @@ -234,6 +234,7 @@ typedef struct { DWORD hash; LOGFONTW lf; FMAT2 matrix; + BOOL can_use_bitmap; } FONT_DESC; typedef struct tagHFONTLIST { @@ -2124,6 +2125,7 @@ static BOOL fontcmp(GdiFont font, FONT_D if(font->font_desc.hash != fd->hash) return TRUE; if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE; if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE; + if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE; return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName); } @@ -2147,6 +2149,7 @@ static void calc_hash(FONT_DESC *pfd) hash ^= two_chars; if(!*pwc) break; } + hash ^= !pfd->can_use_bitmap; pfd->hash = hash; return; } @@ -2160,6 +2163,7 @@ static GdiFont find_in_cache(HFONT hfont memcpy(&fd.lf, plf, sizeof(LOGFONTW)); memcpy(&fd.matrix, pxf, sizeof(FMAT2)); + fd.can_use_bitmap = can_use_bitmap; calc_hash(&fd); /* try the in-use list */ @@ -2286,6 +2290,7 @@ GdiFont WineEngCreateFontInstance(DC *dc memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2)); memcpy(&ret->font_desc.lf, &lf, sizeof(LOGFONTW)); + ret->font_desc.can_use_bitmap = can_use_bitmap; calc_hash(&ret->font_desc); hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); hflist->hfont = hfont;
participants (3)
-
Huw Davies -
Saulius Krasuckas -
Troy Rollo