Prev: Targetting earlier Windows from VS2008
Next: Deadly embrace between SetUnhandledExceptionFilter() and threadrundown(???) in Server 2003
From: Paul N on 22 Jan 2010 11:01 On 21 Jan, 00:06, David Given <d...(a)cowlark.com> wrote: > - firstly, it's not doing any kind of font substitution. If I try to > draw a character that's not in the font (which right now is > SYSTEM_FIXED_FONT) I just get a black square. That's not what I want. > Does Windows GDI do any kind of automatic font substitution, and if so, > how do I turn it on? I'm not an expert on this, but I had a similar problem. There seems to be a bug in Windows. What is supposed to happen is that, when it is going to display some text, it checks through it to see if there are any characters it can't handle with its current font ("font" may not be the correct technical term here...) and it switches in a different one which can handle the characters. However, for a number of characters (ones I've found so far include club, heart, spade, diamond and Euro) it thinks it can handle them but it can't and displays them as short vertical lines. A solution suggested by Alf Steinbach is to do: SaveDC(hdc); SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); before you display the characters and RestoreDC(hdc, -1); after. This changes to a font which is very ugly but does display properly. An alternatively technique which seems to work is to include a nul character in the characters to be printed - this seems to trigger the "get all the characters" font without actually displaying anything. Eg buff[0] = *p; buff[1] = 0; TextOutW(dc, xs, xy, p, 2); I take no responsibility for the latter!! Hope this helps. Paul.
From: David Given on 22 Jan 2010 19:46 On 22/01/10 00:07, David Given wrote: [...] > This does sound like my best bet. I can do all the complicated work to > try and determine which font to use for a glyph lazily, the first time > the app tries to draw the glyph (it has to be lazy because I don't know > what Unicode subset the app will be using). Well, I've done that; it wasn't as much code as I thought, actually. What *was* a hideous amount of code was the Panose matching for the font substitution engine --- getting Panose information from Windows is like pulling hen's teeth! Not to mention that some fonts just don't have any Panose information, so I just have to make it up. So I now have code where it'll build a cache of individual bitmaps, each containing a single glyph in a particular style. The first time the app wants to render a particular glyph it'll enumerate down a list of fonts sorted by Panose difference from the user's selected font until it find one which supports the glyph. Once the cache is populated, the screen can be redrawn very quickly (and flicker-free, too) by blitting bitmaps from the cache onto the screen. I believe I'm very close to achieving redraw nirvana, which is to touch every pixel in the window exactly once. Unfortunately, what I'm discovering is that GetGlyphIndicesW() is outright *lying* to me about whether a font contains a particular glyph or not. Specifically, it's telling me that some fonts --- FixedSys [*], for example --- contain all glyphs. As I result, I'm still getting glyph-not-found blocks instead of the Unicode characters I'm looking for. Does anyone know of a more accurate way of determining whether a font contains a genuine representation of a particular glyph? [*] Yes, I know you're going to tell me not to use fonts like FixedSys if I want to do Unicode. Unfortunately this is fundamentally a console application; I'm having to write my own console because the standard Windows console has lousy Unicode support. As such, I know damned well that my users are going to want to use all the traditional bitmap console fonts like FixedSys. So I still have to make it work. -- ┌─── dg@cowlark.com ───── http://www.cowlark.com ───── │ │ life←{ ↑1 ⍵∨.^3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵ } │ --- Conway's Game Of Life, in one line of APL
From: [Jongware] on 25 Jan 2010 06:09 David Given wrote: > On 22/01/10 00:07, David Given wrote: > [...] >> This does sound like my best bet. I can do all the complicated work to >> try and determine which font to use for a glyph lazily, the first time >> the app tries to draw the glyph (it has to be lazy because I don't know >> what Unicode subset the app will be using). > > Well, I've done that; it wasn't as much code as I thought, actually. > >[..] Once the cache is populated, the screen > can be redrawn very quickly (and flicker-free, too) by blitting bitmaps > from the cache onto the screen. I believe I'm very close to achieving > redraw nirvana, which is to touch every pixel in the window exactly once. "Nirvana ... mmmmmhhhh ..." (Homer Simpson) Yes, that's what I was hoping for. Using your own caching system will defeat Windows' built-in routines with their massive overhead. The only case where Windows *could* have been faster is if it would use back-door techniques, such as caching & blitting from video memory. (And apparently it does not. Should I copyright that idea right now?) Be sure to test your caching on a few different video cards (or with different settings on the same card). You never know -- you might have to include an "unchached" fallback routine. > Unfortunately, what I'm discovering is that GetGlyphIndicesW() is > outright *lying* to me about whether a font contains a particular glyph > or not. Specifically, it's telling me that some fonts --- FixedSys [*], > for example --- contain all glyphs. As I result, I'm still getting > glyph-not-found blocks instead of the Unicode characters I'm looking for. > > Does anyone know of a more accurate way of determining whether a font > contains a genuine representation of a particular glyph? GetFontUnicodeRanges perhaps? The MSDN suggests it returns Unicode /ranges/ rather than individual /characters/, but that could actually be an advantage, as (for example) all Hebrew characters would come from one and the same font, all Arabics from another, etc. > [*] Yes, I know you're going to tell me not to use fonts like FixedSys > if I want to do Unicode. Unfortunately this is fundamentally a console > application; I'm having to write my own console because the standard > Windows console has lousy Unicode support. As such, I know damned well > that my users are going to want to use all the traditional bitmap > console fonts like FixedSys. So I still have to make it work. Heh :-) [Jw]
From: David Given on 2 Feb 2010 18:27
On 25/01/10 11:09, [Jongware] wrote: [...] > GetFontUnicodeRanges perhaps? The MSDN suggests it returns Unicode > /ranges/ rather than individual /characters/, but that could actually be > an advantage, as (for example) all Hebrew characters would come from one > and the same font, all Arabics from another, etc. Yeah, yeah, I know I'm replying to an ancient post, but I've finally fixed my problem and wish to comment for the record. Thusly: GetGlyphIndicesW() *does not work*. Apparently Microsoft have said so. It returns inaccurate results. GetFontUnicodeRanges() *does* work, but it doesn't do what it says on the tin --- it doesn't return Unicode Ranges, as specified by Unicode, but instead it returns the full coverage of the Unicode font as a list of ranges consisting of offset and length. So it does give you complete code point granularity. This is not obvious until you look at the documentation in some detail. (How can MSDN be both so detailed and so useless at the same time?) So now it's all working. Well, mostly --- I still have problems with Unicode code points that don't fit in a 16-bit value, and there are a few oddities like being unable to create instances of the Terminal font despite the font chooser letting me select it, but it's all vastly improved. If anyone knows the Panose descriptor for FixedSys, please let me know... -- ┌─── dg@cowlark.com ───── http://www.cowlark.com ───── │ │ life←{ ↑1 ⍵∨.^3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵ } │ --- Conway's Game Of Life, in one line of APL |