I would like to have an app include a custom font for rendering text, load it, and then use it with standard UIKit elements like UILabel. Is this possible?
I found these links:
-
http://discussions.apple.com/thread.jspa?messageID=8304744
-
http://forums.macrumors.com/showthread.php?t=569311
but these would require me to render each glyph myself, which is a bit too much like hard work, especially for multi-line text.
I've also found posts that say straight out that it's not possible, but without justification, so I'm looking for a definitive answer.
EDIT - failed -[UIFont fontWithName:size:]
experiment
I downloaded Harrowprint.tff (downloaded from here ) and added it to my Resources directory and to the project. I then tried this code:
UIFont* font = [UIFont fontWithName:@"Harrowprint" size:20];
which resulted in an exception being thrown. Looking at the TTF file in Finder confirmed that the font name was Harrowprint.
EDIT - there have been a number of replies so far which tell me to read the documentation on X or Y. I've experimented extensively with all of these, and got nowhere. In one case, X turned out to be relevant only on OS X, not on iPhone. Consequently I am setting a bounty for this question, and I will award the bounty to the first person who provides an answer (using only documented APIs) who responds with sufficient information to get this working on the device. Working on the simulator too would be a bonus.
EDIT - it appears that the bounty auto-awards to the answer with the highest nunber of votes. Interesting. No one actually provided an answer that solved the question as asked - the solution that involves coding your own UILabel subclass doesn't support word-wrap, which is an essential feature for me - though I guess I could extend it to do so.
Source: Tips4all
Edit: As of iOS 3.2, this functionality is built in. If you need to support pre-3.2, you can still use this solution.
ReplyDeleteI created a simple module that extends UILabel and handles loading .ttf files. I released it opensource under the Apache license and put it on github here: git://github.com/zynga/FontLabel.git
The important files are FontLabel.h and FontLabel.m.
It uses some of the code from Genericrich's answer above.
Browse the source here: http://github.com/zynga/FontLabel/tree/master
iOS 3.2 and later support this. Straight from the What's New in iPhone OS 3.2 doc:
ReplyDeleteCustom Font Support
Applications that want to use custom fonts can now include those fonts in their application bundle and register those fonts with the system by including the UIAppFonts key in their Info.plist file. The value of this key is an array of strings identifying the font files in the application’s bundle. When the system sees the key, it loads the specified fonts and makes them available to the application.
Once the fonts have been set in the Info.plist, you can use your custom fonts as any other font in IB or programatically. There is an ongoing thread on Apple Developer Forums:
https://devforums.apple.com/thread/37824 (login required)
And here's an excellent and simple 3 steps tutorial on how to achieve this.
Here are the steps transcribed:
Add your custom font files into your project using XCode as a resource
Add a key to your info.plist file called UIAppFonts.
Make this key an array
For each font you have, enter the full name of your font file (including the extension) as items to the UIAppFonts array
Save info.plist
Now in your application you can simply call [UIFont fontWithName:@"CustomFontName" size:12] to get the custom font to use with your UILabels and UITextViews, etc…
Also: Make sure the fonts are in your Copy Bundle Resources.
There is a simple way to use custom fonts in iOS 4.
ReplyDeleteAdd your font file (for example, Chalkduster.ttf) to Resources folder of the project in XCode.
Open info.plist and add a new key called UIAppFonts. The type of this key should be array.
Add your custom font name to this array including extension ("Chalkduster.ttf").
Now you can use [UIFont fontWithName:@"Chalkduster" size:16] in your application.
Unfortunately, IB doesn't allow to initialize labels with custom fonts. See this question to solve this problem. My favorite solution is to use custom UILabel subclass:
@implementation CustomFontLabel
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder: decoder])
{
[self setFont: [UIFont fontWithName: @"Chalkduster" size: self.font.pointSize]];
}
return self;
}
@end
edit: This answer is defunct as of iOS3.2; use UIAppFonts
ReplyDeleteThe only way I've been able to successfully load custom UIFonts is via the private GraphicsServices framework.
The following will load all the .ttf fonts in the application's main bundle:
BOOL GSFontAddFromFile(const char * path);
NSUInteger loadFonts()
{
NSUInteger newFontCount = 0;
for (NSString *fontFile in [[NSBundle mainBundle] pathsForResourcesOfType:@"ttf" inDirectory:nil])
newFontCount += GSFontAddFromFile([fontFile UTF8String]);
return newFontCount;
}
Once fonts are loaded, they can be used just like the Apple-provided fonts:
NSLog(@"Available Font Families: %@", [UIFont familyNames]);
[label setFont:[UIFont fontWithName:@"Consolas" size:20.0f]];
GraphicsServices can even be loaded at runtime in case the API disappears in the future:
#import <dlfcn.h>
NSUInteger loadFonts()
{
NSUInteger newFontCount = 0;
NSBundle *frameworkBundle = [NSBundle bundleWithIdentifier:@"com.apple.GraphicsServices"];
const char *frameworkPath = [[frameworkBundle executablePath] UTF8String];
if (frameworkPath) {
void *graphicsServices = dlopen(frameworkPath, RTLD_NOLOAD | RTLD_LAZY);
if (graphicsServices) {
BOOL (*GSFontAddFromFile)(const char *) = dlsym(graphicsServices, "GSFontAddFromFile");
if (GSFontAddFromFile)
for (NSString *fontFile in [[NSBundle mainBundle] pathsForResourcesOfType:@"ttf" inDirectory:nil])
newFontCount += GSFontAddFromFile([fontFile UTF8String]);
}
}
return newFontCount;
}
I have done this like this:
ReplyDeleteLoad the font:
- (void)loadFont{
// Get the path to our custom font and create a data provider.
NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"mycustomfont" ofType:@"ttf"];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]);
// Create the font with the data provider, then release the data provider.
customFont = CGFontCreateWithDataProvider(fontDataProvider);
CGDataProviderRelease(fontDataProvider);
}
Now, in your drawRect:, do something like this:
-(void)drawRect:(CGRect)rect{
[super drawRect:rect];
// Get the context.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
// Set the customFont to be the font used to draw.
CGContextSetFont(context, customFont);
// Set how the context draws the font, what color, how big.
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGContextSetFillColorWithColor(context, self.fontColor.CGColor);
UIColor * strokeColor = [UIColor blackColor];
CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
CGContextSetFontSize(context, 48.0f);
// Create an array of Glyph's the size of text that will be drawn.
CGGlyph textToPrint[[self.theText length]];
// Loop through the entire length of the text.
for (int i = 0; i < [self.theText length]; ++i) {
// Store each letter in a Glyph and subtract the MagicNumber to get appropriate value.
textToPrint[i] = [[self.theText uppercaseString] characterAtIndex:i] + 3 - 32;
}
CGAffineTransform textTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, textTransform);
CGContextShowGlyphsAtPoint(context, 20, 50, textToPrint, [self.theText length]);
}
Basically you have to do some brute force looping through the text and futzing about with the magic number to find your offset (here, see me using 29) in the font, but it works.
Also, you have to make sure the font is legally embeddable. Most aren't and there are lawyers who specialize in this sort of thing, so be warned.
Yes, you can include custom fonts. Refer to the documentation on UIFont, specifically, the fontWithName:size: method.
ReplyDelete1) Make sure you include the font in your resources folder.
2) The "name" of the font is not necessarily the filename.
3) Make sure you have the legal right to use that font. By including it in your app, you're also distributing it, and you need to have the right to do that.
Here's the step by step instructions how to do it. No need extra library or any special coding.
ReplyDeletehttp://shang-liang.com/blog/custom-fonts-in-ios4/
Most of the time the issue is with the font not the method. The best way to do it is to use a font that for sure will work, like verdana or geogia. Then change to the intended font. If it does not work, maybe the font name is not right, or the font is not a well formated font.
If you are using xcode 4.3, you have to add the font to the Build Phase under Copy Bundle Resources, according to http://stackoverflow.com/users/1292829/arne in the thread, Custom Fonts Xcode 4.3. This worked for me, here are the steps I took for custom fonts to work in my app:
ReplyDeleteAdd the font to your project. I dragged and dropped the OTF (or TTF) files to a new group I created and accepted xcode's choice of copying the files over to the project folder.
Create the UIAppFonts array with your fonts listed as items within the array. Just the names, not the extension (e.g. "GothamBold", "GothamBold-Italic").
Click on the project name way at the top of the Project Navigator on the left side of the screen.
Click on the Build Phases tab that appears in the main area of xcode.
Expand the "Copy Bundle Resources" section and click on "+" to add the font.
Select the font file from the file navigator that pops open when you click on the "+".
Do this for every font you have to add to the project.
I have been trying out the various suggestions on this page on Iphone OS 3.1.2 and these are my conclusions:
ReplyDeleteSimply using [UIFont fontWithName:size:] with the fonts in the Resources directory will not work, even if the FOND name is set using FontForge.
[UIFont fontWithName:size:] will work if the fonts are loaded first using GSFontAddFromFile. But GSFontAddFromFile is not part of Iphone OS 3.1.2 so it has to be dynamically loaded as described by rpetrich.
Find the TTF in finder and "Get Info". Under the heading "Full name:" it gave me a name which I then used with fontWithName (I just copied and pasted the exact name, in this case no '.ttf' extension was necessary).
ReplyDeleteBetter solution is to add a new property "Fonts provided by application" to your info.plist file.
ReplyDeleteThen, you can use your custom font like normal UIFont.
For iOS 3.2 and above:
ReplyDeleteUse the methods provided by several above, which are:
Add your font file (for example, Chalkduster.ttf) to Resources folder of the project in XCode.
Open info.plist and add a new key called UIAppFonts. The type of this key should be array.
Add your custom font name to this array including extension ("Chalkduster.ttf").
Use [UIFont fontWithName:@"Real Font Name" size:16] in your application.
BUT
The "Real Font Name" is not always the one you see in Fontbook. The best way is to ask your device which fonts it sees and what the exact names are.
I use the uifont-name-grabber posted at:
http://forgecode.net/2010/08/uifont-name-grabber/
Just drop the fonts you want into the xcode project, add the file name to its plist, and run it on the device you are building for, it will email you a complete font list using the names that UIFont fontWithName: expects.
It's not out yet, but the next version of cocos2d (2d game framework) will support variable length bitmap fonts as character maps.
ReplyDeletehttp://code.google.com/p/cocos2d-iphone/issues/detail?id=317
The author doesn't have a nailed down release date for this version, but I did see a posting that indicated it would be in the next month or two.
One important notice: You should use the "PostScript name" associated with the font, not its Full name or Family name. This name can often be different from the normal name of the font.
ReplyDeleteLook up ATSApplicationFontsPath
ReplyDeleteA simple plist entry that allows you to include the font file(s) in your app resources folder and they "just work" in your app.
Maybe the author forgot to give the font a Mac FOND name?
ReplyDeleteOpen the font in FontForge then go to Element>Font Info
There is a "Mac" Option where you can set the FOND name.
Under File>Export Font you can create a new ttf
You could also give the "Apple" option in the export dialog a try.
DISCLAIMER: I'm not a IPhone developer!
It is very easy to add a new font on your existing iOS App.
ReplyDeleteYou just need to add the font e.g font.ttf into your Resource Folder.
Open your application info.plist.Add a new row as "Fonts provided by application" and type the font name as font.ttf.
and when setting the font do as setFont:"corresponding Font Name"
you can check whether your font is added or not by NSArray* check = [UIFont familyNames];.
It return all the font your application support.
Here is another variable-length font system for iPhone: http://ambiguiti.es/2009/05/easyglyph-an-iphone-font-system/
ReplyDelete