From: Paul N on
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
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
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
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