Font font("Helvetica");
font.print("Hello World", 0, 0, 0);
The font is loaded directly from the iPhone's font set. You don't have to bundle a font with your App and you get international support. You can use ASCII or UTF8.
// Hello World in Chinese (UTF8 format)
const char str[] = { 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 0xe6, 0x82, 0xa8, 0xe5, 0xa5, 0xbd, 0 };
font.print(str, 0, 0, 0);
The used glyphs are saved into OpenGL textures "on demand", providing full international support without bogging down the iPhone.
To use it, unzip the file and drag the 'Font' folder to the left Xcode panel.
Any file including font.h will have to use the extension ".mm" This allows the C++ and Objective-C code to be written interchangeably.
Below are the docs for the Font class. You can also get the same info inside 'font.h'.
Font(string family = "Helvetica", int size = 36)
Font(int size, string family = "Helvetica")
- Construct a font by name 'family' of 'size' points.
void print(string text, float x, float y, float z,
int align = -1, float scale = 1.0f)
- Prints 'text' at location 'x', 'y', 'z'.
The text can be left, center, or right
aligned by setting 'align' to -1, 0, or
1 respectively. The text can be
crudely scaled by setting 'scale' to a
multiplier.
+ Example:
Font font;
font.print("Hello World!", 0, 0, 0);
PrintStream print(float x, float y, float z,
int align = -1, float scale = 1.0f)
- Starts a PrintStream at location 'x', 'y', 'z'.
The text can be left, center, or right aligned
by setting 'align' to -1, 0, or 1 respectively.
The text can be crudely scaled by setting
'scale' to a multiplier. The PrintStream can
be written to using operator << in a similar
manner to cout. The PrintStream can be
written to multiple times
(ie. print(0, 0, 0) << "FPS: " << 30).
+ Example:
Font font;
font.print(0, 0, 0) << "Hello World!";
struct Size { int width, height; };
Size getSize(string text, float scale = 1.0f)
- Returns the dimensions of 'text' as it will be
drawn. The text size can be crudely scaled
by setting 'scale' to a multiplier. The Size
type has two attributes: 'width' and 'height'.



15 comments:
Yay I've been wanting to learn how to do this.
But I'm confused... I didn't know you could use C++ on the iPhone. That would be soooo cool.
Hey are you from a.cc?
Oh, well considering that you've linked this article from your signature I'd say that you are...
I think that for font rendering in OpenGL, most people go straight to the Apple-supplied example Texture2D class. It's a texture upload each time a string changes, but unlike your solution the pair kerning is correct and the number of communications with the GL driver is much fewer, which makes a major difference on the iPhone.
This looks good. However, when I compiled font.h, I got "No such file or directory" for #import (angle brackets left out ) map, string and sstream. Am I missing a framework or something else?
I love the design of this library, but it is drawing only a solid color rectangle in one corner of the screen when I use
Font font("Helvetica");
font.print("What",0,0,0);
@thedingohasmybaby: This class uses Texture2D under the hood. Texture2D has a fatal flaw in that it allocates a large amount of data for each change in text. Applications that require changing text will overuse their memory and crash very quickly -- This library resolves that issue and is easier to use.
@Bob: You will have to change the extension of all files including font.h from .m to .mm. This allows you to use C++ and Objective-C interchangably.
@Thomson: There is a difficulty creating OpenGL libraries that will work with any OpenGL setup. This code is meant for an OpenGL context that is setup as such:
glOrthof(0.0f, 320, 480, 0.0f, -1.0f, 1.0f);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
You ofcourse don't have to have exactly this setup. If you havent fully learned about all the features and gotchyas of OpenGL you could try just copy pasting the above.
Dude, that's awesome... you just saved me a ton of work. I'm not an OpenGL master, but just a quick comment for those that are having trouble getting the setup to work - before calling glOrthof, you might want to load the modelview matrix with the identity, i.e.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrthof(0.0f, 320, 480, 0.0f, -1.0f, 1.0f);
Just a hint on what made it work for me... it's probably obvious to someone that uses OGL a lot...
Thanks for the excellent font object!
Uh, sorry, meant GL_PROJECTION....
Hi, Im working on the ipad and this seems to work pretty good on it EXCEPT that when the text is displayed, there is a black box around each letter. Im not sure if I have messed up OpenGL settings or if its something on the iPad.
If anybody knows about this please reply.
you have a bug in the code involving different length of utf8 bytes table, simple
for(int i = 0; i < 6; i++)
if(c[i] < u.c[i])
return true;
does not work with std::map and different amount of utf8 bytes characters (mixing chineese & latin f.e.), different comparison function have to be used
@funckymonk: You probably have blending turned off. See if placing this code at the end of your OpenGL initialization code helps:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
@slajerek: All the characters are padded with 0s up to 6 characters, so there isn't a risk of comparing garbage data.
Are you sure? I used your code directly and debugged. For such string: "abcABC ąèćęł 官湘語北方話" (mixture of 1, 2 and 3 bytes codes), a texture for chinese chars was created every time (it was rendered correctly though). It seems the comparison operator < was not working with std::map in the way we wanted (== operator should be ok). I also changed your code a little bit, so I hope the error not came from my own changes (I doubt...), anyway - just be aware ;)
It's awesome!! thank you.
But, how can I change color of text?
@slajerek I'll look into it next time I get a chance.
@아이정말 You can change the color of the text by calling glColor4f.
glColor4f(1, 0, 0, 1);
font.print("Hello World", 0, 0, 0);
That example will print in red. The first 3 arguments specify how much red, green and blue you want to mix into a color. The forth parameter is a value specifying how transparent you'd like the text to be. A value of 0 makes it invisible while a value of 1 makes it opaque.
You can read more about the glColor functions here: http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
Keep in mind everything you draw afterwards will also turn red! Put it back to normal again by calling this after your printing code.
glColor4f(1, 1, 1, 1);
Post a Comment