GetCharABCWidthsFloat works for most of UNICODE, except CJKV characters

282 views Asked by At

I am attempting to render a series of UNICODE characters onto a spritesheet. This all works quite well for most characters, including Cyrillic ones.

When using GetCharABCWidthsFloat with certain CJKV characters however, the ABCFLOAT::abcfB parameter provides a value lower than expected. It does not account for underhangs or overhangs, which is the exact purpose of the ABCs:

The B spacing is the width of the drawn portion of the character glyph.

Source: ABCFLOAT | Microsoft Docs

As you can see, all characters do not overlap left-to-right, except the last few characters:

Tight

I get around this by creating a customizable padding option, to handle such cases, but this bloats the rest of the glyphs and thus requires a larger surface:

Loose

Font being used is Arial. For the character , ABC returns (2, 10, 2), which sums to a advance of 14 pixels, when in fact, 17 pixels are needed.

I use TextOut to actually render the glyphs, but I do wonder if there is someone out there who's experienced this and came up with a universal solution.

Using functions like GetTextExtentPoint32W or DrawTextEx to get the rectangle does not allow precise per-character placement, which is the whole point of the ABC. And some unmentioned functions only work with TrueType fonts.

I question if certain characters shift to a different font under certain conditions, causing the results to be inaccurate. If that is the case, is there a way to determine if a character is not available for a font, knowing what Windows does automatically so I can reproduce the behaviour? That is, is there some sort of way to determine when a character should fall back on another font, and a way to determine what that font should be?

I have been on this problem for quite some time, so anyone with experience with these APIs would be greatly welcomed!

1

There are 1 answers

6
djangodude On

From the documentation on GetCharABCWidthsFloat:

The ABC widths of the default character are used for characters outside the range of the currently selected font.

Arial contains a lot of characters, including Cyrillic, but it does not contain CJKV ideographs. Other text-related calls may give you the false impression that it does have those characters (through a default/fallback font mechanism).

Before using (maybe before getting) the ABCFLOAT, you should first check that the characters you want metrics for are within the range of the currently selected font.