Determining the y placement of a character for rendering text

1.4k views Asked by At

I have been working on my own bitmap font renderer and while I believe I may have the character spacing correctly, I am not sure how I can determine the the y placement of the character. For example, if the letter 'a' had a y placement of 0, then what would '*' or ',' have? I have been using the winapi function GetCharABCWidthsFloatW to determine the spacing between characters, is there another function I can use to determine some sort of a y offset?

I am doing a best fit on my bitmap images, so they are not always the same size.

4

There are 4 answers

1
demorge On

Each character itself should be offset in y-direction by the text rendering APIs correctly (TextOut, DrawText, etc), so you should have a constant offset. I always get the metrics of the string "Ag" using GetTextExtentPoint32 to obtain the metrics in general, in addition you could try GetTextMetrics.

0
arx On

If I understand correctly: the bitmaps for each glyph are the same height initially. You then trim all the spare space around each glyph to create a minimal bitmap for each character.

The answer in this case is simple. When you create the trimmed bitmap, remember how many pixels you remove from the left and the top (or the left and the bottom, depending on how you are positioning the glyphs). When you draw the bitmaps you can adjust the coordinates using the saved values.

However, if you are trying to use the font metrics to determine how much to trim from each bitmap, you can't.

2
Alexis Wilke On

The GetTextMetrics is the correct answer. But demorge may have wanted to say that the fields you need to use for the Y coordinate is tmAscent (look at the structure.)

The total height is tmHeight. tmAscent is the distance from the top to the baseline. And tmDescent is the distance between the baseline and the bottom of the font.

So in most cases you want to add tmAscent if you (x, y) coordinate reference the top-left corner of the text. If the y coordinate is the bottom, then subtract tmDescent (the + or - also depends on whether you inverted the viewport, but you can test and see what you get.)

That information works whether you write an "a", a "*", or a "j". The baseline is the same for all the characters.

0
M2tM On

General font information:

What you are looking for is how to normalize text placement to the "baseline" or the "origin" (same concept). You can do this with the ascent (ascender) or descent (descender) depending on your coordinate system.

http://www.freetype.org/freetype2/docs/tutorial/step2.html

That provides a pretty good set of example images related to typography.

General bitmap font information:

Now, with regards to a bitmap image the easiest way to make sure they are all lined up properly is to have the same height for each character's bitmap representation in your sprite sheet (widths should be different however based on the actual character width). If you do this, then you can simply line everything up based on that shared height.

If you are clipping the excess whitespace around a character however, you will need to store the clipped values in some structure along with the glyph so that you can determine the offset. If an API is doing this for you, they will likely have ascender/descender, origin/baseline, or line-height type method where you can get the full dimensions based on a character so you can do this properly.

Api specific information
Edit: Based on other answers here are the relevant links for your API specific question:

GetTextMetrics:
http://msdn.microsoft.com/en-us/library/dd144941(v=vs.85).aspx

TEXTMETRIC struct:
http://msdn.microsoft.com/en-us/library/dd145132(v=vs.85).aspx

tmAscent or tmDescent can be used to help offset your y coordinate.