![]() |
|
Setting a pixel size for a font in FreeType2 |
SiegeLord
Member #7,827
October 2006
![]() |
This thread is an attempt to fix a certain bug in the TTF addon in A5. This is taken outside of the usual mailing list discussion so that people who don't subscribe to it can offer some insight. Here's how things work right now: The user calls al_ttf_load_font with a specific size passed to it. This size is then given to FT_Set_Pixel_Sizes to scale the glyphs to the target size. The passed size parameter is stored, and is returned when al_font_text_height is called. However, this does not result in the correct behaviour. For example, drawing a font that was loaded with size 18, and then drawing a rectangle that is 18 pixels high results in this sort of output on my machine:
Now, there is another function, FT_Set_Char_Size, which can also scale glyphs. If I use this function as follows: FT_Set_Char_Size(face, size * 64, 0, 96, 0), where I set the DPI to be 96, the bug goes away and the glyphs are rendered identically in Allegro and in OpenOffice. The documentation says that FT_Set_Pixel_Sizes assumes the DPI of 72, which naturally leads to smaller looking glyphs. Now, so here is the question. Will assuming 96 DPI always result in this correct behaviour? The internet suggested that on Mac's the 72 DPI is used instead. I had another way to solve this, going from the other direction. Instead of making the glyphs bigger, I would measure the actual pixel height of the font, by measuing the ascent of some capital character, like 'M', and using that as the height of the font as reported by al_font_text_height. This last solution does not seem satisfactory to me, however. In the end, the solution of this bug should exhibit these two properties: al_ttf_load_font should produce the same pixel height for fonts loaded on different computers; and, al_font_text_height should return a value that approximately represents the actual height of the font. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Thomas Harte
Member #33
April 2000
![]() |
Quote: I had another way to solve this, going from the other direction. Instead of making the glyphs bigger, I would measure the actual pixel height of the font, by measuing the ascent of some capital character, like 'M', and using that as the height of the font as reported by al_font_text_height. This is, sort of, what FT_Set_Pixel_Sizes does. It sets the size in pixels of the EM, which is a metric that was once the dimensions of a capital M in the front but is now an arbitrary shape set by the font designer. I'm not sure how you're comparing to OpenOffice, but if you're getting the correct size on your computer by assuming 96 dpi then it's just because your computer uses 96 dpi. 96 dpi is the default value in Windows, but the user can set whatever dpi they want through the control panel. 72 dpi was the standard default under olde Mac OS but will vary depending on your screen size and resolution. The problem is as described in the FreeType FAQ. Modern fonts just aren't built in a way that allows you to meaningfully set a bounding rectangle size that would work for all glyphs. The problem is the complete fiction of Allegro's style of font drawing (ie, every glyph in a unique box, every box placed end to end so that they meet but don't overlap). It's ridiculous, it doesn't work, and that's why the way TTF fonts are made is incompatible with it. The best you'll be able to do is set a size, run through whatever subset of the glyphs you're going to support (and you won't be able to support all of them in the bounding boxes/no overlap programmers' system without most of them appearing tiny and spaced out) and work out the bounds you got. Then scale up your initial arguments and do it again. [My site] [Tetrominoes] |
SiegeLord
Member #7,827
October 2006
![]() |
Hmm, but will FT_Set_Pixel_Sizes result in the same bitmap sizes on different computers when given identical inputs? If so, is there a way to determine the size of the em square in pixels given that fixed DPI? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Mark Oates
Member #1,146
March 2001
![]() |
In this particular case, the font size includes the ascender and the descender. normally, -- |
Thomas Harte
Member #33
April 2000
![]() |
FT_Set_Pixel_Sizes sets the size of the em in pixels, so should produce identical results on all computers. Just in case anyone comes along who wants to disagree, I made a quick graphic of some random characters in the LinoType/Apple version of Helvetica: http://www.allegro.cc/files/attachment/596904 Check out how some of the non-Latin characters are substantially taller than the capital M. Also, I've realised that what I said in my last post is horridly worded so as to be misleading. The size of an em is directly related to the font size in points. The size of glyphs relative to the em is arbitrary and related to the particular font you are using. For example, I'm aware that in the standard Microsoft Windows set, Arial is visibly different from Times New Roman. EDIT: Times New Roman versus Arial Ms at the same point size — Times New Roman is wider but shorter, but both fonts have the same sized em. http://www.allegro.cc/files/attachment/596905 [My site] [Tetrominoes] |
SiegeLord
Member #7,827
October 2006
![]() |
Hmm. But what is the size of the em? If you pass the point size of 18 to FT_Set_Pixel_Sizes will you get the em square to be 18 pixels high? I am thinking that returning the em size is the most logical value to be returned by al_font_text_height. Note, I am not saying that this is the value that will be used for rendering purposes, that uses it's own mechanism to determine per-glyph bitmap sizes. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Thomas Harte
Member #33
April 2000
![]() |
It's the same as the nominal size of the font. So if you display text in a 12 point font then you are telling it to size the em so that it is 12/72ths of an inch. [My site] [Tetrominoes] |
Elias
Member #358
May 2000
|
Quote: The problem is the complete fiction of Allegro's style of font drawing (ie, every glyph in a unique box, every box placed end to end so that they meet but don't overlap). That's not at all how it works in A5.. all character placement is done by freetype (at least that was my intention with the ttf addon). Also al_get_text_width() works perfectly as far as I know. The problem is just al_get_text_height(). Maybe we should have two separate functions:
The first one would return the actual bounding box height of the string passed in, in pixels. It's easy to get that from freetype I think. The second one would behave like the current text_height, and simply return whatever would normally be used as line spacing. (I assume this is what is passed to FT_Set_Pixel_Sizes.) Anyway, I don't have much time to experiment with this myself right now. [edit] But the real problem then is, where do you draw your text so it fits inside the bounding box. Maybe remove al_get_text_width/height and instead have something like: al_get_text_bounding_box(font, string, &left, &top, &right, &bottom) and then if you draw the text at x, y, it will exactly fit into a rectangle from x+left/y+top to x+right/y+bottom. -- |
SiegeLord
Member #7,827
October 2006
![]() |
Quote: Maybe we should have two separate functions: Yeah, I was just thinking the same myself. It looks like the best course of action. Both values are useful to have, but are clearly not very related to each other as Thomas Harte pointed out. I like the naming scheme too. EDIT: Reflecting your edit, Elias, I think the current font height function should stay, as its value reflects the 'single spacing' spacing for multi-line texts. The bounding box trick does make more sense, but it shouldn't be the only function there is. EDIT2: Oh, I misread what you said. Nvm. I like the idea. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Ron Novy
Member #6,982
March 2006
![]() |
Arg... This never came up with alfont in 4.2... The only thing I will add here though is that you may have to add 1 to the text height returned. IIRC FreeType uses 16.16 fixed point rendering for anti-aliasing and the height might get rounded down when it should be rounded up. I had a few crashes because of this... At least I think that's what the problem was. The +1 to the height did fix it in the cases when it did crash though. ---- |
Evert
Member #794
November 2000
![]() |
Quote: The problem is the complete fiction of Allegro's style of font drawing (ie, every glyph in a unique box, every box placed end to end so that they meet but don't overlap). It's ridiculous, it doesn't work, and that's why the way TTF fonts are made is incompatible with it. And that's why A5 doesn't do it that way. Quote: Maybe we should have two separate functions: * al_get_text_height(font, string) We probably should (that also makes get_text_height() to match get_text_width()), but what does al_get_text_height() return? Does it include the ascender and descender? Normally if you print text, you want the base of the characters to align. Quote: But the real problem then is, where do you draw your text so it fits inside the bounding box. Maybe remove al_get_text_width/height and instead have something like: al_get_text_bounding_box(font, string, &left, &top, &right, &bottom) and then if you draw the text at x, y, it will exactly fit into a rectangle from x+left/y+top to x+right/y+bottom. In that case have it in addition, since all three have their use. Yes, you can get the other two from this, but that's not pretty. It also doesn't solve the problem of getting text to align properly. So, what I think we need:
|
Thomas Harte
Member #33
April 2000
![]() |
Actually, I think I don't understand what we're talking about at all - would the best solution not be just to explicitly credit FreeType with the handling, provide maybe a couple of functions similar to ye olde Allegro and just let people go straight to FreeType for anything more complicated than "this is the size of an em, draw this text on this baseline"? [My site] [Tetrominoes] |
Evert
Member #794
November 2000
![]() |
Quote: would the best solution not be just to explicitly credit FreeType with the handling, provide maybe a couple of functions similar to ye olde Allegro and just let people go straight to FreeType for anything more complicated than "this is the size of an em, draw this text on this baseline"?
Probably. The discussion is just about the basic "this is the size of an em, draw this text on this baseline": you (possibly) probably want to know the size of the ascender and descender, and reliably set the size of the em such that you get predictable results on different platforms. |
Thomas Harte
Member #33
April 2000
![]() |
Quote: The discussion is just about the basic "this is the size of an em, draw this text on this baseline": you (possibly) probably want to know the size of the ascender and descender, and reliably set the size of the em such that you get predictable results on different platforms. The size of the ascender and descender are members of the FT_Face struct, which I assume this add on will expose access to. Actually bothering to check it out reveals that it also contains a bounding box that is large enough to hold any glyph in the font. It also contains a 'height' field, which tells you how far to advance in y between one line of text and the next. I was therefore confused when you suggested "Maybe functions to get the ascender and descender for a given font?" - this makes it sound like at least some part of the add-on will just be things that the developers believe would make FreeType syntactically more pretty, above and beyond the specifics of providing the generic FreeType to Allegro glue that otherwise everyone would have to implement on their own. I'm pretty sure that ye olde Allegro draws fonts with it's usual linear-framebuffer-of-old top left corner/English reading order-type coordinates. It has no concept of a baseline whatsoever. [My site] [Tetrominoes] |
Ron Novy
Member #6,982
March 2006
![]() |
So is FreeType used on every platform? Since FreeType supports other types of fonts why not just call it the FreeType add on instead? This way you could include direct access to FreeType structures and functions... ---- |
Thomas Harte
Member #33
April 2000
![]() |
FreeType is pure-C and platform neutral, so it should be usable everywhere Allegro is + a whole bunch more places. In addition to TrueType, it also handles Adobe Type 1 fonts (which were popular pre-TrueType and remain popular in Postscript circles), OpenType fonts (which are a successor to TrueType that merges in significant Type 1 functionality) and a whole bunch of otherwise little used fringe formats (CFF, SFNT, X11's PCF, Windows' FNT, BDR and PFR). The only slightly interesting thing about some of those obscure formats is that at least PCF and FNT are bitmap formats. [My site] [Tetrominoes] |
Elias
Member #358
May 2000
|
Right now, text is drawn at y + bitmap_top, where y is what the user passes in and bitmap_top comes from Freetype: Quote: bitmap_top This is the bitmap's top bearing expressed in integer pixels. Remember that this is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive.
Quote: So, what I think we need: * A way to get the height and width of a string so that it fits within a bounding box I think we indeed should have all those. Now whether it's a good idea to tell users to simply directly access FT_Face and FT_Glyph I'm not sure - it certainly would be a lot easier for end-users if Allegro itself could provide the info. And not sure in cases where you need more than the above you really should bother to even use the TTF/Freetype addon instead of using Freetype it directly. There's also still the bitmap-font addon - so only those ALLEGRO_FONT objects loaded by this addon are handled by Freetype. -- |
Thomas Harte
Member #33
April 2000
![]() |
Quote: Now whether it's a good idea to tell users to simply directly access FT_Face and FT_Glyph I'm not sure I think part of the answer will be whether Allegro 5 will expect users to do struct access elsewhere. Is stuff like bitmap->h and bitmap->w going to survive? Thinking about it more thoroughly, you could probably justify wrapper functions around access to the various fields that return numbers in the FreeType fixed point format since it doesn't match any of the C or Allegro integral types, given that the number of wrapper functions would be so few. [My site] [Tetrominoes] |
Evert
Member #794
November 2000
![]() |
Quote: I think part of the answer will be whether Allegro 5 will expect users to do struct access elsewhere. No, it doesn't. Quote: Is stuff like bitmap->h and bitmap->w going to survive? No.* *) Actually, that will still work (at the moment and if you include the header that exposes the struct elements), but it shouldn't be used. |
|