Recently I came across a bug that the text (English) was not correctly drawn with ExtTextOut() (using ETO_GLYPH_INDEX) when Calibri was set as the font. More specifically, if the text contains “fi”, “ti”, “ft”, “ff”, “tt”, it either shows a “?” in the end, or no show at all.
The steps to draw the text is as follows:
- Get glyph information by calling GetCharacterPlacement() and pass in a GCP_RESULTS struct.
- Draw text with ExtTextOut() using the GCP_RESULTS returned from step 1.
It turned out that those character combinations (“fi”,”ti”…) are drawn as one glyph instead of two. As a result,
the returnd GCP_RESULTS in step 1 is not consistent: the number of glyphs in nGlyphs fields does not match the count of glyphs returned in lpGlyphs.
Setting GCP_LIGATE in step 1 fixed the mismatch problem. However, those special letters are still drawn as a single glyphs as seen below:
If we look into the returned GCP_RESULTS object, we clearly see that the count of characters (15 in the example) in the string does not match the count of glyphs (10 in the example). While this is common in languages such as Hindi, it is not correct behavior for English text.
The sample project can be found in my last post.
Here’s some observations that are not obvious about TextOut() and ExtTextOut():
- TextOut() and ExtTextOut() have some built-in font fallback and visual reorder mechanism when used without any “special settings”. As seen in line 1 and 2, the text contains English, Chinese and Hebrew characters and “Calibri” is selected as the font. “Calibri” does not have glyphs for Chinese and Hebrew, yet all characters show up correctly. Also note that Hebrew text is in correct visual order as Hebrew is a right-to-left language.
- Specify character spacing with SetTextCharacterExtra() is considered as “special settings”, which does not work well with languages that are not supported by the font or required visual reordering. Line 3 and 4 shows that Chinese and Hebrew characters are represented by “?” instead of glyphs since the font does not support.
- Drawing glyphs with ExtTextOut() has similar results, but the missing glyphs will not be shown at all. Line 5 shows that Chinese and Hebrew are completely missing (without even the “?”).
- Character spacing can be specified by manipulating the lpDx array in the GCP_RESULTS structure. As seen in the sample code, we can get all information about the glyphs for the text by calling GetCharacterPlacement() and pass in a GCP_RESULTS structure. the lpDx point to an array of “glyph width” that can be used by ExtTextOut(). Increase the values in the array results in increased character space as shown in line 6. The vertical line marks the end of each glyph.
- Word spacing can be achieved by picking out white space character and add additional values to its glyph width as shown in line 7.
- With a font that has all the glyphs (e.g., Arial Unicode MS), we see all the characters with the specified character and word spacing. However, the visual order of Hebrew text is wrong:
The sample project can be downloaded here. To compile the sample project:
- download WTL from: http://sourceforge.net/projects/wtl/ and unzip the file into a folder.
- change project property and point to the folder that has the WTL header files (see next two images)