Hi
When trying to run a program I get these messages:
trace:font:GetTextMetricsW text metrics: Weight = 400 FirstChar = 32 AveCharWidth = 6 Italic = 0 LastChar = 65532 MaxCharWidth = 35 UnderLined = 0 DefaultChar = 0 Overhang = 0 StruckOut = 0 BreakChar = 32 CharSet = 0 PitchAndFamily = 27 -------------------- InternalLeading = 3 Ascent = 13 Descent = 3 Height = 16 trace:font:X11DRV_SelectFont hdc=0x74, hfont=0xa6 trace:font:X11DRV_SelectFont dc->gdiFont = 0x40378f28 trace:ole:OLEFontImpl_SetRatio (0x47d85a60)->(96, 2540) trace:ole:OLEFontImpl_get_hFont (0x47d85a60)->(0x408bf0bc) trace:ole:OLEFontImpl_get_Size (0x47d85a60)->(0x408bf034) err:local:LOCAL_GetBlock not enough space in GDI heap 10c7 for 116 bytes trace:ole:OLEFontImpl_get_hFont Returning (nil) wine: Unhandled exception (thread 0009), starting debugger...
I had a look at this LOCAL_GetBlock function. There is already code with some FIXME comments, but it's all #ifdef 0'd out. So that means it's not tested or not even supposed to work. Is there something else I could do to increase my GDI heap?
Thanks
bye Fabi
When trying to run a program I get these messages:
err:local:LOCAL_GetBlock not enough space in GDI heap 10c7 for 116 bytes trace:ole:OLEFontImpl_get_hFont Returning (nil) wine: Unhandled exception (thread 0009), starting debugger...
I had a look at this LOCAL_GetBlock function. There is already code with some FIXME comments, but it's all #ifdef 0'd out. So that means it's not tested or not even supposed to work. Is there something else I could do to increase my GDI heap?
I think that wouldn't help much. I made more traces to find this:
trace:font:DumpGdiFontList ---------- gdiFont Cache ---------- trace:gdi:GetObjectW 0xd82 92 0x408bf718 trace:gdi:GDI_GetObjPtr (0xd82): enter 2 trace:gdi:GDI_ReleaseObj (0xd82): leave 2 trace:font:DumpGdiFontList gdiFont=0x40383250 hfont=0xd82 (L"MS Sans Serif") trace:gdi:GetObjectW 0xa6 92 0x408bf718 trace:gdi:GDI_GetObjPtr (0xa6): enter 2 trace:gdi:GDI_ReleaseObj (0xa6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40378f30 hfont=0xa6 (L"System")
Looks good, two fonts, but then later:
trace:font:DumpGdiFontList ---------- gdiFont Cache ---------- trace:gdi:GetObjectW 0x14c6 92 0x408bf718 trace:gdi:GDI_GetObjPtr (0x14c6): enter 2 trace:gdi:GDI_ReleaseObj (0x14c6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40385938 hfont=0x14c6 (L"MS Sans Serif") trace:gdi:GetObjectW 0xd82 92 0x408bf718 trace:gdi:GDI_GetObjPtr (0xd82): enter 2 trace:gdi:GDI_ReleaseObj (0xd82): leave 2 trace:font:DumpGdiFontList gdiFont=0x40383250 hfont=0xd82 (L"MS Sans Serif") trace:gdi:GetObjectW 0xa6 92 0x408bf718 trace:gdi:GDI_GetObjPtr (0xa6): enter 2 trace:gdi:GDI_ReleaseObj (0xa6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40378f30 hfont=0xa6 (L"System")
Already two times MS Sans Serif...
trace:font:DumpGdiFontList ---------- gdiFont Cache ---------- trace:gdi:GetObjectW 0x23d6 92 0x408bf70c trace:gdi:GDI_GetObjPtr (0x23d6): enter 2 trace:gdi:GDI_ReleaseObj (0x23d6): leave 2 trace:font:DumpGdiFontList gdiFont=0x403b06f8 hfont=0x23d6 (L"MS Sans Serif") ... all in all 32 fonts MS Sans Serif. ... trace:gdi:GetObjectW 0xa6 92 0x408bf70c trace:gdi:GDI_GetObjPtr (0xa6): enter 2 trace:gdi:GDI_ReleaseObj (0xa6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40378f30 hfont=0xa6 (L"System")
trace:font:DumpGdiFontList ---------- gdiFont Cache ---------- trace:gdi:GetObjectW 0x2dfe 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x2dfe): enter 2 trace:gdi:GDI_ReleaseObj (0x2dfe): leave 2 trace:font:DumpGdiFontList gdiFont=0x403dabf8 hfont=0x2dfe (L"MS Sans Serif") ... 32 Fonts MS Sans Serif ... trace:gdi:GetObjectW 0x23e6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x23e6): enter 2 trace:gdi:GDI_ReleaseObj (0x23e6): leave 2 trace:font:DumpGdiFontList gdiFont=0x403a3b80 hfont=0x23e6 (L"Arial") trace:gdi:GetObjectW 0x23d6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x23d6): enter 2 trace:gdi:GDI_ReleaseObj (0x23d6): leave 2 trace:font:DumpGdiFontList gdiFont=0x403b06f8 hfont=0x23d6 (L"MS Sans Serif") ... another 32 Fonts MS Sans Serif ... trace:gdi:GetObjectW 0xa6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0xa6): enter 2 trace:gdi:GDI_ReleaseObj (0xa6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40378f30 hfont=0xa6 (L"System")
Or some time much later even this:
trace:font:DumpGdiFontList ---------- gdiFont Cache ---------- trace:gdi:GetObjectW 0xf48e 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0xf48e): enter 2 trace:gdi:GDI_ReleaseObj (0xf48e): leave 2 trace:font:DumpGdiFontList gdiFont=0x47d7c160 hfont=0xf48e (L"MS Sans Serif") ... 180 Fonts MS Sans Serif ... trace:gdi:GetObjectW 0x9a82 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x9a82): enter 2 trace:gdi:GDI_ReleaseObj (0x9a82): leave 2 trace:font:DumpGdiFontList gdiFont=0x4400be90 hfont=0x9a82 (L"Courier") trace:gdi:GetObjectW 0x9a7a 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x9a7a): enter 2 trace:gdi:GDI_ReleaseObj (0x9a7a): leave 2 trace:font:DumpGdiFontList gdiFont=0x4400a678 hfont=0x9a7a (L"MS Sans Serif") ... another 208 Fonts MS Sans Serif ... trace:gdi:GetObjectW 0x23e6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x23e6): enter 2 trace:gdi:GDI_ReleaseObj (0x23e6): leave 2 trace:font:DumpGdiFontList gdiFont=0x403a3b80 hfont=0x23e6 (L"Arial") trace:gdi:GetObjectW 0x23d6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0x23d6): enter 2 trace:gdi:GDI_ReleaseObj (0x23d6): leave 2 trace:font:DumpGdiFontList gdiFont=0x403b06f8 hfont=0x23d6 (L"MS Sans Serif") ... another 32 Fonts MS Sans Serif ... trace:gdi:GetObjectW 0xa6 92 0x408bf6e8 trace:gdi:GDI_GetObjPtr (0xa6): enter 2 trace:gdi:GDI_ReleaseObj (0xa6): leave 2 trace:font:DumpGdiFontList gdiFont=0x40378f30 hfont=0xa6 (L"System")
Now is this an error in my application (VB6 with lots of controls and ocx's) or one in wine? Does my app really create so many fonts or should each only appear once in this list because they're all the same? They do have different handles/addresses but that could be wine too. Of course it works on Windows but that could just be pure luck :) Is there some way to tell on Windows if it really uses so much GDI heap? Being a VB app it's not that easy to debug low-level.
Thanks
bye Fabi
On Thu, 05 Feb 2004 16:26:36 +0100, you wrote:
Now is this an error in my application (VB6 with lots of controls and ocx's) or one in wine? Does my app really create so many fonts or should each only appear once in this list because they're all the same? They do have different handles/addresses but that could be wine too. Of course it works on Windows but that could just be pure luck :) Is there some way to tell on Windows if it really uses so much GDI heap? Being a VB app it's not that easy to debug low-level.
If you work with Win2K/XP, you can use NTobjects a free tool from www.smidgeonsoft.com. It shows you for each process the number of each type of GDI objects, compare that with the number that you observe in your wine logs.
Rein.
At 17:42 05.02.2004 +0100, Rein Klazes wrote:
Now is this an error in my application (VB6 with lots of controls and ocx's) or one in wine? Does my app really create so many fonts or should each only appear once in this list because they're all the same? They do have different handles/addresses but that could be wine too. Of course it works on Windows but that could just be pure luck :) Is there some way to tell on Windows if it really uses so much GDI heap? Being a VB app it's not that easy to debug low-level.
If you work with Win2K/XP, you can use NTobjects a free tool from www.smidgeonsoft.com. It shows you for each process the number of each type of GDI objects, compare that with the number that you observe in your wine logs.
That's a nice page, interesting looking tools. I tried it out and if the app is running it has 39 fonts and the other items (Pen, Brush, Bitmap) even less. So this looks like wine reserves unnecessarily too many fonts. I'll see if I find something more.
Thanks.
bye Fabi
Now is this an error in my application (VB6 with lots of controls and ocx's) or one in wine? Does my app really create so many fonts or should each only appear once in this list because they're all the same? They do have different handles/addresses but that could be wine too. Of course it works on Windows but that could just be pure luck :) Is there some way to tell on Windows if it really uses so much GDI heap? Being a VB app it's not that easy to debug low-level.
If you work with Win2K/XP, you can use NTobjects a free tool from www.smidgeonsoft.com. It shows you for each process the number of each type of GDI objects, compare that with the number that you observe in your wine logs.
That's a nice page, interesting looking tools. I tried it out and if the app is running it has 39 fonts and the other items (Pen, Brush, Bitmap) even less. So this looks like wine reserves unnecessarily too many fonts. I'll see if I find something more.
After fiddling around and creating some test programs I found that in wine a font is created for every control. Even a simple dialog with just four labels or textboxes in it will have 4 times a MS Sans Serif font. So this looks like another problem concerning wine and VB (Man, I hate this VB...). On Windows it uses only one font MS Sans Serif. As my original application which I want to make work uses many dialogs and controls it's now obvious why it runs out of GDI memory.
I'm now trying to find out who decides if a new font has to be created or if an old one can be used. If anyone knows about this (in VB) please let me know.
Thanks
bye Fabi
If you work with Win2K/XP, you can use NTobjects a free tool from www.smidgeonsoft.com. It shows you for each process the number of each type of GDI objects, compare that with the number that you observe in your wine logs.
That's a nice page, interesting looking tools. I tried it out and if the app is running it has 39 fonts and the other items (Pen, Brush, Bitmap) even less. So this looks like wine reserves unnecessarily too many fonts. I'll see if I find something more.
After fiddling around and creating some test programs I found that in wine a font is created for every control. Even a simple dialog with just four labels or textboxes in it will have 4 times a MS Sans Serif font. So this looks like another problem concerning wine and VB (Man, I hate this VB...). On Windows it uses only one font MS Sans Serif. As my original application which I want to make work uses many dialogs and controls it's now obvious why it runs out of GDI memory.
I'm now trying to find out who decides if a new font has to be created or if an old one can be used. If anyone knows about this (in VB) please let me know.
I hacked some more and need an advice. I changed font.cpp: CreateFontIndirectW a bit. Instead of always allocating a new gdi object it has a list of already allocated font objects and first tests if there was already a font allocated with the same logical properties (LOGFONTW). If so it just returns the existing HFONT and doesn't allocate a new one. With this change my VB app with the many controls comes up and is almost usable. Some fonts on the registers of the tab control look quite strange. But besides that it works.
Now is this a reasonable change (apart from its hacky implementation now :) ? Is the function CreateFontIndirect allowed to do something like this? Are there more things I should test than just the ones in the LOGFONTW struct? If anybody is interested in a screenshot (the funny fonts go down by about 20 degrees :) just raise your hand.
Maybe the caching needs to be done at another place. I have already seen the GdiFontList in freetype.c. But then it's already too late (and only works for ttf I guess). Another possibility may be to create the font but then free it again if a similar is found.
Thanks
bye Fabi
On Mon, Feb 09, 2004 at 05:03:40PM +0100, Fabian Cenedese wrote:
I hacked some more and need an advice. I changed font.cpp: CreateFontIndirectW a bit. Instead of always allocating a new gdi object it has a list of already allocated font objects and first tests if there was already a font allocated with the same logical properties (LOGFONTW). If so it just returns the existing HFONT and doesn't allocate a new one. With this change my VB app with the many controls comes up and is almost usable. Some fonts on the registers of the tab control look quite strange. But besides that it works.
Now is this a reasonable change (apart from its hacky implementation now :) ? Is the function CreateFontIndirect allowed to do something like this? Are there more things I should test than just the ones in the LOGFONTW struct? If anybody is interested in a screenshot (the funny fonts go down by about 20 degrees :) just raise your hand.
No, this isn't right. You can convince yourself of this by a quick test program on Windows; initialize a LOGFONT and then call CreateFontIndirect twice, you'll get two different hfonts back.
I suspect your leak happens in the olefont implementation. You want to check that each hfont is destroyed when the IOleFont interface is released.
Huw.
I hacked some more and need an advice. I changed font.cpp: CreateFontIndirectW a bit. Instead of always allocating a new gdi object it has a list of already allocated font objects and first tests if there was already a font allocated with the same logical properties (LOGFONTW). If so it just returns the existing HFONT and doesn't allocate a new one. With this change my VB app with the many controls comes up and is almost usable. Some fonts on the registers of the tab control look quite strange. But besides that it works.
Now is this a reasonable change (apart from its hacky implementation now :) ? Is the function CreateFontIndirect allowed to do something like this? Are there more things I should test than just the ones in the LOGFONTW struct? If anybody is interested in a screenshot (the funny fonts go down by about 20 degrees :) just raise your hand.
No, this isn't right. You can convince yourself of this by a quick test program on Windows; initialize a LOGFONT and then call CreateFontIndirect twice, you'll get two different hfonts back.
I suspect your leak happens in the olefont implementation. You want to check that each hfont is destroyed when the IOleFont interface is released.
I also sometimes had this in mind as I couldn't find OLEFontImpl_Release calling OLEFontImpl_Destroy in my logs. The reference pointer never seems to become 0. So I will have a look into this.
Thanks
bye Fabi
At 16:39 09.02.2004 +0000, Huw D M Davies wrote:
On Mon, Feb 09, 2004 at 05:03:40PM +0100, Fabian Cenedese wrote:
I hacked some more and need an advice. I changed font.cpp: CreateFontIndirectW a bit. Instead of always allocating a new gdi object it has a list of already allocated font objects and first tests if there was already a font allocated with the same logical properties (LOGFONTW). If so it just returns the existing HFONT and doesn't allocate a new one. With this change my VB app with the many controls comes up and is almost usable. Some fonts on the registers of the tab control look quite strange. But besides that it works.
Now is this a reasonable change (apart from its hacky implementation now :) ? Is the function CreateFontIndirect allowed to do something like this? Are there more things I should test than just the ones in the LOGFONTW struct? If anybody is interested in a screenshot (the funny fonts go down by about 20 degrees :) just raise your hand.
No, this isn't right. You can convince yourself of this by a quick test program on Windows; initialize a LOGFONT and then call CreateFontIndirect twice, you'll get two different hfonts back.
My idea for caching the handles in CreateFontIndirect came from this:
GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) --snip-- if(ret->hfont == hfont && !memcmp(&ret->xform, &dc->xformWorld2Vport, offsetof(XFORM, eDx))) {
Here it not only tests the properties but also the handles. So if the handles are different (as they are now from CreateFontIndirect) it will always create a new font. But removing this check didn't help either :)
I suspect your leak happens in the olefont implementation. You want to check that each hfont is destroyed when the IOleFont interface is released.
When are the fonts released? If a control creates a font and uses it until the dialog gets closed it doesn't help much. There will still be too many fonts while running. Or should the control create a font every time it has to draw anything and will release it again after? I can see releases but the reference counter never reaches 0 until the end of the program where all remaining fonts are cleaned up.
Sorry for asking, I don't know much about ole, fonts and stuff :)
bye Fabi
I suspect your leak happens in the olefont implementation. You want to check that each hfont is destroyed when the IOleFont interface is released.
When are the fonts released? If a control creates a font and uses it until the dialog gets closed it doesn't help much. There will still be too many fonts while running. Or should the control create a font every time it has to draw anything and will release it again after? I can see releases but the reference counter never reaches 0 until the end of the program where all remaining fonts are cleaned up.
I didn't really get further. Everything looks normal if these assumptions and observations are correct:
- The freetype engine will cache every font for every different handle. - And as CreateFontIndirect returns a different handle on every call the engine will also cache as many fonts (if they are used). - The VB runtime will create a font for every control as they can be different. (At least it looks like that with dozens of calls to CreateFontIndirect and therefore many different font handles). - A font will only get deleted from cache if the program does so, not from wine itself. - As there is no error in the end about references not being 0 or so I guess that every GetObject also has a matching ReleaseObject. But the timing may be different to windows. (Tested with a simple app which works ok but still uses as many fonts as there are controls even if all are the same).
Is there a possibility to increase the GDI heap? Like that I could at least test if the app works ok besides this font problem. I ran it again on Windows and looked at the resources. It only uses 40 fonts while running, but I don't know about the startup. Comparing this to the wine stats it seems that Windows can use the same fonts for different controls. Or it does release and reallocate them on demand.
So I'm out of powder again. If anybody wants to test it I can send the application.
Thanks
bye Fabi