2

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!

Mike Weir
  • 3,094
  • 1
  • 30
  • 46

1 Answers1

0

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.

djangodude
  • 5,362
  • 3
  • 27
  • 39
  • Ahh, I sort of figured something like that. How would I go about picking a font in a similar way windows would automatically via TextOut? – Mike Weir Jan 31 '19 at 00:47
  • I'd recommend posting that as a separate question with details on what you are trying to do (i.e. use only one font, or show a lot of characters no matter how many fonts are used, or something else). – djangodude Jan 31 '19 at 00:50
  • It'll still answer this question. Any suggestions or direction would help tremendously. – Mike Weir Jan 31 '19 at 00:51
  • Maybe modify the existing question with more details on what you're trying to do, constraints, etc.. What I mean is: what is the source of your text (is it fixed/known or could be anything)? Are you able to install additional fonts or are you constrained to whatever is on the system where your code is running?, etc. etc. because my suggestions would change depending upon the answers to those questions. – djangodude Jan 31 '19 at 01:04
  • The characters and the font is specified by the user. I'd simply like some way to make sure GetCharABCWidthsFloat() returns what I'd expect it to when using TextOut(). So, some way to determine if a particular character exists in the font, and if it doesn't, some way to know what font Windows automatically reverts to so I can use GetCharABCWidthsFloat() against it. – Mike Weir Jan 31 '19 at 18:20
  • I've modified the question to clarify my hypothesis that you re-affirmed. But to be clear, to answer the question, a solution would be most helpful: not just a reason for the problem. – Mike Weir Jan 31 '19 at 22:16