|
View previous topic :: View next topic
|
| Author |
Message |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Mon Mar 09, 2009 10:09 pm Post subject: public domain truetype font rendering |
 |
|
Edit: Updated to version 0.5. See here.
http://nothings.org/stb/stb_truetype.h
I needed this for the product I'm working on at RAD, but it's not something that is going to differentiate us, so Jeff agreed to release it as "open source".
1700 lines of code (500 of which are really documentation), loads TrueType fonts, renders them to anti-aliased bitmaps, a simple bad but lightweight/convenience system to bake a bunch of characters into a bitmap and then render them as-if-point-sampled even-if-bilinear-filtering-enabled.
Obviously Freetype exists and it has a reasonable license (although it requires credits-in-documentation, which I have grumbled about before), so if you don't feel constrainted by that, you may want to stick with it. In fact, stb_truetype.h is currently lacking some very important features, like font hinting, which makes its output inferior to Freetype. On the other hand, it's one file you drop in and it just works (hopefully).
Note: unlike stb_image, this file is released as a header file library. To compile it, you need to make one of the C/C++ files that includes it force it to generate the actual implementation, which you do by defining "STB_TRUETYPE_IMPLEMENTATION" before including it. Even the private/static symbols in the file are prefixed with "stbtt", so you should be able to do this in a "regular" source file without causing any problems. (This is actually my preferred way of making one-file libraries.)
Finally, I have to warn you: i've only tested this on Microsoft fonts. There are probably a lot of TrueType fonts it won't work on. Fixing this should be easy, so just point me at the non-working font and I'll fix it (or you can try yourself if you hit an assert). I just didn't want to try to support the gazillions of possible modes and encodings in the file, not all of which are well-documented, without knowing what actually exists in the wild--what people actually need. (To be more explicit, TrueType supports the same data being encoded multiple times in the file in different ways. So it doesn't make sense for me to try to recognize lots of different ways if, in fact, it turns out in practice there's one way that they all always do.)
I only intend to support TrueType fonts, not Type 1 fonts or bitmap fonts embedded in .ttf files. I don't know how hard supporting Type 1 would be.
I haven't tested compiling as C++, or big-endian machines, but I expect them to work with minor and no fixes respectively.
Last edited by sean on Wed Dec 14, 2011 11:58 am; edited 2 times in total |
|
| Back to top |
|
 |
casey Site Admin
Joined: 18 Dec 2004 Posts: 1835 Location: Seattle
|
| |
Posted: Tue Mar 10, 2009 7:28 am Post subject: |
 |
|
AWESOME!
- Casey |
|
| Back to top |
|
 |
grusbanan
Joined: 15 Jul 2008 Posts: 6 Location: Sweden
|
| |
Posted: Tue Mar 10, 2009 8:35 am Post subject: |
 |
|
Yes, very kick-ass!
(I did get some signed/unsigned char errors out of the box with VS2008, but that's to be expected.) |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Tue Mar 10, 2009 8:46 am Post subject: |
 |
|
| grusbanan wrote: | Yes, very kick-ass!
(I did get some signed/unsigned char errors out of the box with VS2008, but that's to be expected.) |
Let me know what they are and I'll fix them. Just need the line numbers. |
|
| Back to top |
|
 |
grusbanan
Joined: 15 Jul 2008 Posts: 6 Location: Sweden
|
| |
Posted: Tue Mar 10, 2009 8:49 am Post subject: |
 |
|
Ok. That would be:
1595 - cannot convert from 'stbtt_uint8 *' to 'char *'
1629 - cannot convert parameter 1 from 'stbtt_uint8 *' to 'const char *'
1648 - cannot convert parameter 1 from 'stbtt_uint8 *' to 'const char *' |
|
| Back to top |
|
 |
cbloom
Joined: 31 Jul 2008 Posts: 17
|
| |
Posted: Wed Mar 11, 2009 6:51 pm Post subject: |
 |
|
| somebody should make this compute distance fields so you can use it with the Valve texkill method. |
|
| Back to top |
|
 |
grusbanan
Joined: 15 Jul 2008 Posts: 6 Location: Sweden
|
| |
Posted: Wed Mar 11, 2009 6:56 pm Post subject: |
 |
|
| Quote: | | somebody should make this compute distance fields so you can use it with the Valve texkill method. |
Yeah. That's exactly what I'm testing this with.
Oh, and I haven't found any fonts that dont render yet. Plain excellent. |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Wed Mar 11, 2009 7:41 pm Post subject: |
 |
|
| grusbanan wrote: | Ok. That would be:
1595 - cannot convert from 'stbtt_uint8 *' to 'char *'
1629 - cannot convert parameter 1 from 'stbtt_uint8 *' to 'const char *'
1648 - cannot convert parameter 1 from 'stbtt_uint8 *' to 'const char *' |
Fixed (in theory) and posted as version 0.2. |
|
| Back to top |
|
 |
Mike Nelson
Joined: 20 Jan 2006 Posts: 26 Location: Seattle
|
| |
Posted: Sat May 02, 2009 11:14 pm Post subject: |
 |
|
I was able to dump this into a linux opengl app today with very little effort. I used arialbd.ttf from corefonts which seem to be the same fonts as Microsoft's.
Great work, Sean. Thanks! |
|
| Back to top |
|
 |
memon
Joined: 04 Sep 2006 Posts: 13
|
| |
Posted: Mon Jul 13, 2009 10:18 am Post subject: |
 |
|
Thanks for the awesome code!
One thing I noticed was the the example baking code does not render the glyphs correctly. I tested the openGL code bit. The following picture shows the problem (above: before, below: fixored, nice and crisp!)
http://www.edu.lahti.fi/~memon/stash/render_quad_problem.png
The solution is to to remove all the 0.5 from the getBakedQuad function (sans that d3d vs. ogl thing). I'm not sure what they are really supposed to do, but at least the texture coord generation will squash the rectangle by 1 pixels in both dimensions. |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Mon Jul 13, 2009 4:45 pm Post subject: |
 |
|
Uh... I can't figure out why I did that either. I think that might have been entirely untested code?
I mean, it's a weird choice that there isn't even a scale factor, and the fact it's snapping to int coordinates and stuff... I guess the idea is you're supposed to bake them at the exact res you want, but still.
Hrmm, Sean of 3 months ago, what were you thinking?!??
So yeah, I agree, without actually testing it, it looks to me like all the 0.5s except d3d_bias and those computing round_x/round_y should go away.
I'm not sure why it would squish, though, since it's adding and subtracting .5 to both the texture coordinates and the screen coordinates, so if they're 1:1 they should work out the same, shouldn't they? (Obviously if you scale stuff it comes out different.) |
|
| Back to top |
|
 |
memon
Joined: 04 Sep 2006 Posts: 13
|
| |
Posted: Tue Jul 14, 2009 4:13 pm Post subject: |
 |
|
| Snapping to int coords is good idea or else you get smudgy fonts. I think the example is actually inflating the rectangle by half a pixel in each direction, so it actually gets bigger not smaller as I thought. |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Tue Jul 14, 2009 5:42 pm Post subject: |
 |
|
Ok, I checked, and the reason is because I copied it from code that may actually scale these up or down slightly with bilerp.
In my implementation, I pad each character with a row/column of blank texels on all sides. The non-offset coordinates put the edges of the rectangle at the exact edge of the nearest neighbor sample, or halfway between samples for bilerping.
In the bilerping case, this can lead to visible edges, so I move the rectangle edges out to the center of the padding texels. As long as you displace the texture coordinates and the screen-draw coordinates the same amount, it doesn't affect the appearance of the character in the 1:1 case.
So my guess is that your screen isn't actually 1:1... maybe you have a distorted aspect ratio because of widescreen or 5:4 vs 4:3?
(By 1:1 I mean the coordinates that you're specifying the rectangle in correspond directly with pixels; an increase of 1 in the coordinate moves by exactly one screen pixel.)
Anyway, it's still better for sample code to just get rid of the 0.5s since they're confusing. |
|
| Back to top |
|
 |
memon
Joined: 04 Sep 2006 Posts: 13
|
| |
Posted: Wed Jul 15, 2009 11:43 am Post subject: |
 |
|
| Now those offsets make sense. Thanks for clarifying it. I use glOrtho with width and height of the window. I have some localization tasks on my todo list later is (japanese yay!), so I will take another look at that point. |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1549 Location: Kirkland WA
|
| |
Posted: Thu Jul 16, 2009 2:38 pm Post subject: |
 |
|
| Do you use width and height of the client portion of the window, rather than the window size you requested? |
|
| Back to top |
|
 |
|