Hints on how to unhint, aka We're not comparing apples and oranges; it's more like apples and apple seeds!

by Michael S. Kaplan, published on 2008/03/05 10:16 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2008/03/05/7995329.aspx

Please read the disclaimer; content not approved by Microsoft!

Over in the microsoft.public.win32.programmer.international newsgroup, prevodcilac's question was:

Is there way to disable font hinting in Uniscribe, while using for example ScriptPlace???

I know how to disable it for GetGlyphOutline, but not for Uniscribe....

Now the one thing that both GDI and Uniscribe have in common is their use of device contexts to store information like the font that can be used to draw text.

In this particular case, both GDI's GetGlyphOutline and Uniscribe's ScriptPlace happen to take an HDC, a handle to a device context -- which contains the HFONT that is used to identify the font that the function will use for its work....

And that HFONT comes from a call to a function like CreateFontIndirect, which takes a LOGFONT. And that LOGFONT has an lfQuality member, defined as follows:

Specifies the output quality. The output quality defines how carefully the graphics device interface (GDI) must attempt to match the logical-font attributes to those of an actual physical font. It can be one of the following values.




Windows NT 4.0 and later: Font is always antialiased if the font supports it and the size of the font is not too small or too large.

Windows 95 Plus!, Windows 98/Me: The display must greater than 8-bit color, it must be a single plane device, it cannot be a palette display, and it cannot be in a multiple display monitor setup. In addition, you must select a TrueType font into a screen DC prior to using it in a DIBSection, otherwise antialiasing does not occur.


Windows XP: If set, text is rendered (when possible) using ClearType antialiasing method. See Remarks for more information.


Appearance of the font does not matter.


Appearance of the font is less important than when PROOF_QUALITY is used. For GDI raster fonts, scaling is enabled, which means that more font sizes are available, but the quality may be lower. Bold, italic, underline, and strikeout fonts are synthesized if necessary.


Windows 95/98/Me, Windows NT 4.0 and later: Font is never antialiased.


Character quality of the font is more important than exact matching of the logical-font attributes. For GDI raster fonts, scaling is disabled and the font closest in size is chosen. Although the chosen font size may not be mapped exactly when PROOF_QUALITY is used, the quality of the font is high and there is no distortion of appearance. Bold, italic, underline, and strikeout fonts are synthesized if necessary.

If neither ANTIALIASED_QUALITY nor NONANTIALIASED_QUALITY is selected, the font is antialiased only if the user chooses smooth screen fonts in Control Panel.

This particular parameter is what defines the kind of anti-aliasing/hinting that is going to happen in text drawing operations, such as the ones used by Uniscribe....

The fun question of course, should be obvious.

Given the fact that GetGlyphOutline both takes an HDC which can have this defined and also has a GGO_UNHINTED uFormat flag that can be passed, is why would GGO_UNHINTED even be needed?

Well, there are some hints in looking at a few of the flags that GetGlyphOutline can take -- note the many hinting differences above not captured in the below - it is almost like we are talking about two different technologies:

GGO_BEZIER Windows 2000/XP: The function retrieves the curve data as a cubic Bézier spline (not in quadratic spline format).
GGO_NATIVE The function retrieves the curve data points in the rasterizer's native format and uses the font's design units.
GGO_UNHINTED Windows 2000/XP: The function only returns unhinted outlines. This flag only works in conjunction with GGO_BEZIER and GGO_NATIVE.

Something else to consider -- GetGlyphOutline withy GGO_UNHINTED is not exactly giving you a letter you could then put on the screen or something. It is giving you the specific information within the font itself -- the outlines (sans hints) that are provided within the font. But what comes out of that LOGFONT setting is a lot more -- some more info on how much more in blog posts like Chris Jackson's Windows Forms Font Hinting with TextRenderingHint (for concepts, not for his GDI+ preference!), or Bill Hill's MSDN Magazine article It's Not Just Fonts, which talks a great deal about what is behind hinting and the many different levels at which hinting takes place.

So you can think of what GetGlyphOutline's GGO_UNHINTED provides as the very first level of hinting, the hints that are closest to the font itself. The bulk of the later possible levels cannot be turned on and off individually by any means except for indirectly by the lfQuality type settings, the DPI settings, and.or the size of the letters (the font size has a definite influenec here, with many types of hinting such as Cleartype disappearing at larger sizes and or higher DPI display resolution settings.

So it is not that we are talking about apples and oranges.

We are talking about apples and apple seeds!

And then developer David Brown had a slightly different take on the question, which led to some additonal thoughts that I'd like to quote as is since (a) they seem too clever to just cast aside and (b) in case they aren't relevant someone else gets the "blame" for the new direction of parts of the answer! :-)

I’m not clear where Uniscribe comes into this question as stated, though I have a possible interpretation and a suggestion further below.

You see the answer to: "how to get the same effect as GetGlyphOutline with the GGO_UNHINTED flag in their Uniscribe operations so that their Uniscribe-produced text has no hinting." should be the same as the answer to: "how to get the same effect as GetGlyphOutline with the GGO_UNHINTED flag in their ExtTextOut operations so that their ExtTextOut-produced text has no hinting."

In other words, Uniscribe doesn’t do anything that is hinting specific – it just calls GDI, both to get metrics and to render to a dc.

What I think we need to know is, how does the customer want to render the glyphs?

Is it obtaining glyph paths using GetGlyphOutline, and then rendering the paths themselves? Maybe they haven’t been using ExtTextOut at all?

If this is the case then it makes sense that they are asking about Uniscribe – they would have been doing OK until they needed to add support for complex scripts.

If this is the case, the answer is a little more complex than just passing a flag, because, while they have been avoiding ExtTextOut in the non-complex script cases, for complex scripts they cannot avoid calling ScriptTextOut. (This is because some complex script specific code happens in ScriptTextOut.)

Assuming all the above is where the customer is going, (a bit of a long shot, but I can’t think what else may be wanted), I would suggest that they proceed as follows:

1) In order to ‘disable hinting’, select the fonts at large sizes. Scale all the fonts up the same, such that the smallest is 1024 pixels per em. (i.e. lfHeight = -1024).
2) Render the text to an off-screen DC
3) Use BeginPath/EndPath to capture the glyph outlines.
4) Render the captured glyph outlines using the inverse scale to that chosen above.

(Aside, TrueType fonts contain an outline and an interpreted program that moves the points on the outline. This interpreted program is often referred to as ‘hinting’, however it is not always restricted to adjusting the shape for lower resolutions. For example there are a number of East Asian fonts in which the glyph outlines are provided with all the strokes positioned at the glyph origin, and it is necessary to run the interpreted program to move them to their correct positions. The effect of GGO_UNHINTED is not necessarily as expected. Selecting the font at a high pixels per em size is a better way to get a resolution independent outline.)

That aside is kind of what I was talking about before with the apple vs. apple seed thing, with one being really just a subset -- the first level -- of the other. And it even gives a better answer than the GetGlyphOutline route as well.

So in the end there may be enough hints on how to unhint? :-)


This blog brought to you by(U+1789, aka KHMER LETTER NYO)

no comments

go to newer or older post, or back to index or month or day