Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

BNicholson

macrumors newbie
Apr 7, 2008
14
0
There's actually a thread on the Cocoa-dev mailing list going around about this. The same plist key would probably work on the OSX side, although the bundling is a bit different for iPhone.

http://www.cocoabuilder.com/archive/message/cocoa/2008/4/6/203410

http://developer.apple.com/document...PListKeys.html/apple_ref/doc/uid/20001431-SW8

See where that'll get ya.

I greatly appreciate the help! Unfortunately the solutions provided through the threads require linking to a framework that isn't supported by the Iphone SDK. Hopefully they will release a little more support for getting custom fonts working in a later version. = )
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Just in case anyone wanted the solution to this problem, all you need to do to display the correct characters is make the CGGlyph = (the decimal value of your character - 29)

Example: Say if you want to print a capital A.
You would want to set your CGGlyph = 65(Decimal value of A) - 29;
Then call CGContextShowGlyphsAtPoint or CGContextShowGlyphs as appropriate.

I have no idea as to why 29 is the magic number but there is your solution as to how to load and display(correctly) a custom font in a .ttf format = )

Interesting work, I hope this is helpful to others working on iPhone development. i was curious about the 29, it seemed nonsensical. After some research I wanted to warn that that may be specific to the font you are working with:
http://developer.apple.com/document.../reference.html#//apple_ref/doc/c_ref/CGGlyph

Per that page a GCGlyph is:
An index into the internal glyph table of a font.

I don't know that every font will have things at the some position in their internal glyph table. I'm not a truetype guru, so maybe they will be, but it doesn't seem like that's a guarantee.

-Lee
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
I suddenly got very interested in this and started digging more. There is a cmap, or "Character to Glyph Map" in the font (perhaps a few, for different platforms). This states which glyph should be used for a character in an outside encoding such as unicode. From:
http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter08#ba57949e

The ‘cmap’ table is used to convert from an outside encoding (such as Unicode) to internal glyph ids.

I am not sure if the cmap(s) can be accessed using the CGFontRef, but I am going to keep digging. If there is, it should be easy to write a routine that takes an NSString or utf8 string and turns it into an array of Glyphs.

-Lee
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
I'm not there yet, but this seems to be the way you might be able to get glyphs for a generic font:

Code:
NSTextStorage
  setFont
    You have to pass an NSFont to this. This might complicate things because you have a CGFontRef, but hopefully it's easy to get the NSFont pretty similarly.
  setCharacters
    Pass an NSArray of characters. I would just pass in 0-127 or 0-256

NSLayoutManager
  glyphIndexForCharacterAtIndex
    You should be able to pass in a character index (which would just be the ascii values or unicode code points) and get the glyph back. it will be a NSUInteger, but you should be able to cast that to a CGGlyph. The CGGlyph is an unsigned short, not an integer, but I think the cast should do it.

I'm afraid other than parsing the font yourself, this is the only way to go. I have C code that parses a ttf, but I didn't write it and it belongs to my employer, so I probably can't share it. It's painful anyway.

You may not need to do this, but it's probably the best way to go unless you want to make the glyph list for each font you will use.

That is also a valid method. For each font you will use, just figure out a map of the characters (at least the ones you want to use) to the glyphs and keep it around to use when you use that font.

Good luck.

-Lee
 

yayaba

macrumors 6502
Original poster
Apr 24, 2007
297
0
San Francisco Bay Area
Wow, great work guys. I've been a bit busy lately so I haven't had time to code (haven't even tried Beta 3 yet!) but I'll start digging around what you guys suggested.

Thanks!
 

Andy55

macrumors newbie
Apr 4, 2003
2
0
Hey guys, I was in need of a unicode-to-glyph converter, so here's what I came up with using the lead provided by lee1210 (thanks!).

Note the comments/warnings in the body and that since this proc has high overhead, you'll want to cache the results, etc. The class 'UtilStr' is our in-house string C++ wrapper and should be self-explainitory.

Finally, can someone confirm that I'm not leaking anything? I'm not a Cocoa guy, so that stuff doesn't jump out at me. Thanks in advance!

Code:
void GetGlyphsForUniChars( const UtilStr& inTypefaceName, const UniChar inChars[], int inNumChars, CGGlyph outGlyphs[] ) {

	// A negative length denotes that inChars[] is NUL terminated.
	if ( inNumChars < 0 ) {
		inNumChars = 0;
		while ( inChars && inChars[ inNumChars ] )
			inNumChars++;
	}

	if ( inNumChars <= 0 )
		return;

	NSString* srcChars = [ NSString stringWithCharacters: inChars length: inNumChars ];
	NSString* fontName = [ NSString stringWithUTF8String: inTypefaceName.CStr() ];
	NSFont* font = [ NSFont fontWithName:fontName size:0 ];

	NSTextStorage* textStorage = [[ NSTextStorage alloc ] initWithString: srcChars ];
	
	if ( font ) {
		[ textStorage setFont: font ];
	} else {
		ss_break();
	}

	NSLayoutManager* layoutMgr = [[ NSLayoutManager alloc ] init ];
	[ textStorage addLayoutManager: layoutMgr ];


	// Unicode strings can be arbitraily complex and all kinds of reordering and glyph combination can occur (including consolidation to fewer glyphs).
	// We assume below that one unicode char maps to one glyph and that they occur in order.  Since this assuption doesn't hold for asian languages, 
	//    we must be careful.  Fortunately, for typical western fonts and the text we intend to convert, this is good enough.
	SInt32 numGlyphs = [ layoutMgr numberOfGlyphs ];
	ss_assert( (int) numGlyphs == inNumChars );

	NSGlyph* nsglyphs = (NSGlyph*) ss_malloc( sizeof( NSGlyph ) * numGlyphs );

	NSRange range = { 0, numGlyphs };
	[ layoutMgr getGlyphsInRange : range glyphs: nsglyphs characterIndexes:NULL glyphInscriptions:NULL elasticBits:NULL ];

 	{
		int i;

		for ( i = 0; i < numGlyphs; i++ ) {
			if ( nsglyphs[ i ] < 0xFFFF ) {
				outGlyphs[ i ] = (CGGlyph) nsglyphs[ i ];
			} else {
				outGlyphs[ i ] = 0;
			}
		}

		for ( ; i < inNumChars; i++ ) {
			outGlyphs[ i ] = 0;
		}
	}

	ss_free( nsglyphs );
	nsglyphs = NULL;

	[ layoutMgr release ];
	[ textStorage release ];
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.