How do I embed a font in an app?

  • In my application's user interface I want to use some TrueType fonts
    which are not built into the OS. (Yes, they're free and their licenses
    allow this sort of use.) I thought I remembered a way to embed fonts
    in an application bundle, or to programmatically load a font from a
    file; but I'm drawing a blank now when I try to look it up.

    Surely I don't have to copy the fonts into the system (~/Library/
    Fonts) like in the bad old days? :-P

    —Jens
  • I had some success with this -

    -(void) loadFonts {
    // Get the main bundle object
    NSBundle * appBundle = [NSBundle mainBundle];
    NSString *fontsPath = [[appBundle resourcePath]
    stringByAppendingPathComponent:@"Fonts"];
    if (fontsPath) {
      NSURL *fontsURL = [NSURL fileURLWithPath:fontsPath];
      if (fontsURL) {
      // Using the Carbon APIs:  get a file reference and spec for the path

      FSRef fsRef;
      FSSpec fsSpec;
      (void)CFURLGetFSRef((CFURLRef)fontsURL, &fsRef);
      OSStatus status = FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL,
    NULL, &fsSpec, NULL);
      if (status==noErr) {
        //activate the font file using the file spec
        status = ATSFontActivateFromFileSpecification (  &fsSpec,
                                    kATSFontContextLocal,
            kATSFontFormatUnspecified,
            NULL,
            kATSOptionFlagsDefault,
                                    NULL
            );
        if (status != noErr) {
        NSLog(@"Error %d loading fonts from %@",status,fontsURL);
        }
      } else {
        NSLog(@"Error loading catalog info");
      }
      } else {
      NSLog(@"Error creating fonts URL");
      }
    } else {
      NSLog(@"Error creating fonts path");
    }
    }

    On Apr 4, 2008, at 3:37 PM, Jens Alfke wrote:
    > In my application's user interface I want to use some TrueType fonts
    > which are not built into the OS. (Yes, they're free and their
    > licenses allow this sort of use.) I thought I remembered a way to
    > embed fonts in an application bundle, or to programmatically load a
    > font from a file; but I'm drawing a blank now when I try to look it
    > up.
    >
    > Surely I don't have to copy the fonts into the system (~/Library/
    > Fonts) like in the bad old days? :-P
    >
    > —Jens
  • On 5 Apr 2008, at 00:37, Jens Alfke wrote:
    > In my application's user interface I want to use some TrueType fonts
    > which are not built into the OS. (Yes, they're free and their
    > licenses allow this sort of use.) I thought I remembered a way to
    > embed fonts in an application bundle, or to programmatically load a
    > font from a file; but I'm drawing a blank now when I try to look it
    > up.

    It surely can be done. Apple's own iDVD application bundles a number
    of fonts under Resources/Fonts in the application bundle.
  • On 4 Apr '08, at 4:06 PM, Buddy Kurz wrote:

    > I had some success with this -

    Works like a charm, thanks!

    ATSFontActivateFromFileSpecification is deprecated in Leopard, but the
    new replacement function, ATSFontActivateFromFileReference, is
    identical except for taking an FSRef instead of an FSSpec. So it makes
    the code even simpler.
  • On 4 Apr '08, at 3:37 PM, Jens Alfke wrote:

    > In my application's user interface I want to use some TrueType fonts
    > which are not built into the OS. (Yes, they're free and their
    > licenses allow this sort of use.) I thought I remembered a way to
    > embed fonts in an application bundle, or to programmatically load a
    > font from a file; but I'm drawing a blank now when I try to look it
    > up.

    FYI, Ben Stiglitz emailed me an even simpler solution that requires no
    code at all:

    Begin forwarded message:
    >
    > From: Benjamin Stiglitz <ben...>
    > Date: 4 April, 2008 11:02:06 PM PDT
    > To: Jens Alfke <jens...>
    > Subject: Re: How do I embed a font in an app?
    >
    >> ATSFontActivateFromFileSpecification is deprecated in Leopard, but
    >> the new replacement function, ATSFontActivateFromFileReference, is
    >> identical except for taking an FSRef instead of an FSSpec. So it
    >> makes the code even simpler.
    >
    > Even better is an Info.plist key for all the fonts you could want:
    > ATSApplicationFontsPath.
    > http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/
    Articles/PListKeys.html#/

    > /apple_ref/doc/uid/20001431-SW8
    >
    > -Ben
  • On Sun, Apr 6, 2008 at 12:43 PM, Jens Alfke <jens...> wrote:
    > FYI, Ben Stiglitz emailed me an even simpler solution that requires no code
    > at all:

    Unfortunately the docs don't seem to mention if this is a Leopard-only
    key.  Can someone confirm either way?

    --Kyle Sluder
  • Hi,

    Just embed it as a resource, and then use the code
    below to load it for use. You can just reference it by
    name from then on (well, as long as your app is
    running) as you would any other font. (Where
    "kDefaultFontFile" is the name of your TTF file. Ex:
    @"MyFont.TTF")

    HTH!

    B

      NSString *fontPath = [[[[NSBundle mainBundle]
    resourcePath] stringByAppendingPathComponent:@"Fonts"]
    stringByAppendingPathComponent: kDefaultFontFile];
      NSData *fontData = [NSData dataWithContentsOfFile:
    fontPath];

      ATSFontContainerRef container;
      OSStatus err = ATSFontActivateFromMemory([fontData
    bytes], [fontData length],
                             kATSFontContextLocal,
                             kATSFontFormatUnspecified,
                             NULL,
                             kATSOptionFlagsDefault,
                             &container );

         if( err != noErr )
             NSLog(@"failed to load font into memory");

         ATSFontRef fontRefs[100];
         ItemCount  fontCount;
         err = ATSFontFindFromContainer(
                             container,
                             kATSOptionFlagsDefault,
                             100,
                             fontRefs,
                             &fontCount );

      if( err != noErr || fontCount < 1 ){
             NSLog(@"font could not be loaded.");
      }
      else{

      NSString *fontName;
      err = ATSFontGetPostScriptName(
                                 fontRefs[0],
                                 kATSOptionFlagsDefault,
                                 (CFStringRef*)( &fontName ) );

      NSLog(@"font %@ loaded", fontName);
      }

          ____________________________________________________________________________________
    You rock. That's why Blockbuster's offering you one month of Blockbuster Total Access, No Cost.
    http://tc.deals.yahoo.com/tc/blockbuster/text5.com
  • On 7 Apr '08, at 5:52 PM, Brad Peterson wrote:

    > Just embed it as a resource, and then use the code below to load it
    > for use.

    This seems less efficient (and more complicated) than either of the
    two earlier solutions. Loading the font into memory first means it
    takes up heap space, which is private and has to be allocated out of
    swap, rather than allowing the file to be memory-mapped. Better just
    to point ATS at the file. And you can't get much simpler than just
    pointing your Info.plist at a directory full of fonts.

    —Jens
previous month april 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
Go to today