Using custom fonts in iPhone applications

June 13, 2009 at 11:58 am (iPhone development, Software Engineering) (, , , , , )

As any iPhone developer knows, the fonts included on the iPhone can be a bit…limiting.  Sure, they are fine for business and utility applications, but for games and other design-heavy apps, the built-in fonts really don’t get the job done, with MarkerFelt being maybe the only usable, stylistic font.

I worked on typography for just about a decade at Adobe, on such applications as Photoshop, Illustrator, and Flash…so good typographic options are near and dear to my heart.  It pains me to see the limitations that iPhone developers operate with.

What is almost more painful, is the complete lack of a coherent solution from the community.  I spent some time looking around, and found a grand total of 2 solutions, neither of which is complete…but both are usable to some extent.

  1. EasyGlyph – this is a windows only .NET program to create a spritemap out of a font, plus objective-c code to support using the spritemap in your iPhone application.  This solution is good enough for some users, mainly game developers who don’t mind the inherent limitations, and just need some nicely styled text in small amounts.  You are basically just blitting images instead of text, so you are unable to do anything that is not pre-rendered into the images.  Personally, I don’t like this approach, but it would be rude of me not to include it here, as many of you may find that this is just what you need.  It works very well for very simple needs.
  2. A very nice and responsible blogger UIHacker posted this post, which is as far as I can tell, the only fully working solution that anyone had the confidence to post.  It is a very nice packaging up of what is really the best solution right now, which is to operate at the CG* level (CGFont, CGContext, etc).  If you are going to really dive in and use a custom font, this is the way to go.

What I have done, is taken the code that UIHacker posted, and expanded on it…to fit my needs.  Everyone’s needs will differ, but some things are very common.  I will post probably the #1 request I saw, which is how to center text.

  1. To begin, get the CustomFontBase.[hm] from the link above.
  2. in the drawRect() method, look for the line that draws the glyphs, it should look like
    CGContextShowGlyphsAtPoint( context, 0, 0 + fontSize * .25, 
                          glyphs, length );
  3. The second parameter is the x offset, which is what we are interested in.  Replace this call, with the following code:
    if ( isCentered )
    {
    CGContextSetTextDrawingMode( context, kCGTextInvisible );
    
    // draw the glyphs to get the width
    // hack the y-point to make sure it's not cut off below font baseline
    // - this creates a perfect vertical fit
    CGContextShowGlyphsAtPoint( context, 0, 0 + fontSize * .25,
                                                    glyphs, length ); 
    
    // get width of text for autosizing the frame later (perhaps)
    CGPoint textEnd = CGContextGetTextPosition( context );
    float adjustment = ( self.frame.size.width - textEnd.x ) / 2.0f;
    
    if ( isOutlined )
    {
    CGContextSetTextDrawingMode( context, kCGTextFillStroke );
    }
    else
    {
    CGContextSetTextDrawingMode(context, kCGTextFill);
    }
    
    // draw the glyphs for real
    // hack the y-point to make sure it's not cut off below font baseline
    // - this creates a perfect vertical fit
    CGContextShowGlyphsAtPoint( context, adjustment, 0 + fontSize * .25,
                                                    glyphs, length );
    }
    else
    {
    // draw the glyphs
    // hack the y-point to make sure it's not cut off below font baseline
    // - this creates a perfect vertical fit
    CGContextShowGlyphsAtPoint( context, 0, 0 + fontSize * .25,
                                                    glyphs, length );
    }
  4. You will also need to add a member “isCentered” to support both centered and non-centered drawing.  Also, the “isOutlined” section is optional, but I thought I’d include it since it was something else I added.  UIHacker included support for Glow, and I similarly added support for outlined text.  The color of the outline is controlled by the stroke color, which you can set like this:
    if ( isOutlined )
    {
    CGContextSetStrokeColorWithColor( context,
                                       outlineColor.CGColor );
    }

While this is still very limiting, only single-line text is currently supported…it is a very good start, and is very easily extendable to as much functionality as you are willing to code up.  Type engines are no easy task, but I think as long as the community continutes to share and build off each other’s success, we can make good progress.

I am considering putting together a more fully featured version of this and sharing it, if there is sufficient interest in the same features.  For now, I think this is a good enough starting point, that anyone can make good use of it in any iPhone app.

Permalink 3 Comments