View Full Version : obtaining the glyphs for characters that aren't letters

May 19, 2009, 09:45 PM
so i found out a nice way to get the width of strings, and taht is to obtain a glyph which can then be used to obtain a rectangle which can then be used to obtain the width

seems pretty silly to have to go through all that, but then there is no getTheWidthOfThisStringInPixels:WithThisFont: method

so i found out that glyphs can't recognize non letter characters... like 'space', numbers, quotes, and other punctuation

if i have an entire string how can i loop through all the letters and identify when i've come across a non-letter so i can then get the glyph for it.

what i have is

if([word length] > 0) {
for(unsigned int i = 0; i < [word length]; i++){
NSGlyph gly = [aFont glyphWithName: [NSString stringWithFormat: @"%C", [word characterAtIndex: i]]];
if(gly) {
// do stuff

i saw "+" is coded as "plus" to get the glyph... so what's everything else and how do determine when i have something that isn't a letter?

i am also working under the assumption that glyphs will help me in this same manner if the language uses a non roman alphabet

May 19, 2009, 11:37 PM
It seems like that wouldn't take into account kerning, etc... have you tried making an NSAttributedString with your font and such and getting the width of that?

May 20, 2009, 02:25 PM
Long time C/C++ programmer so excuse my attempt at Objective-C but the following should get the idea across.

-(void)drawString:(NSString*)message withFontname:(NSString*)fontname atSize:(CGFloat)pointSize
NSFont* font = nil;
NSMutableString* str = nil;
NSMutableAttributedString* astr = nil;
NSTextView* view = nil;
NSBezierPath* bezier = nil;
NSRect bounds;

font = [NSFont fontWithName:fontname size:pointSize];
if ( !font ) return;

str = [NSMutableString stringWithCapacity:0];
[str appendString:message];

astr = [[[NSMutableAttributedString alloc] initWithString:str] autorelease];
[astr addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, [astr length])];

view = [[[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
if ( view )
[[view textStorage] appendAttributedString:astr];

bezier = [NSBezierPath bezierPath];
if ( bezier )
[bezier moveToPoint:NSMakePoint( 0, 0 )];

for ( unsigned int i = 0; hasGlyph; i++ )
NSGlyph glyph = [[view layoutManager] glyphAtIndex:i isValidIndex:&hasGlyph];
if ( hasGlyph == YES )
[bezier appendBezierPathWithGlyph:glyph inFont:font];

bounds = [bezier bounds];

/* Your draw code here ...

May 20, 2009, 04:52 PM
catfishMan: yeah, i'm not sure how to go about that with attributed string but lloyddean's post looks helpful

lloyddean, i will try your solution, thanks for all that help :cool:

edit: thanks lloyddean! the code worked wonders! and i get what you're doing too, which is great!

May 21, 2009, 02:24 PM
My suggestion would look something like this:

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:fontName size:fontSize], NSFontAttributeName, nil];
NSAttributedString *attString = [[NSAttributedString alloc] initWithString:message attributes:attributes];
NSSize drawnFontSize = [attString size];

Rather a lot simpler, and I suspect much faster as well since it uses CoreText for text measurement under the hood instead of doing it manually. NSAttributedString also has simple methods to draw the string in a rect, or at a point.

May 21, 2009, 04:37 PM
ah thanks catfish, that's a heck of a lot more accurate than the other solution (sorry lloyddean)
it looks so simple to

May 21, 2009, 06:00 PM
ah thanks catfish, that's a heck of a lot more accurate than the other solution (sorry lloyddean)
it looks so simple to

No problem - don't be sorry.

I was doing research into grabbing glyphs as beziers from fonts
for use in some games I'm working on. The code you presented
looked like you were interested in something along the same line
and I presented it in that light.

I've found a unicode symbol font with some useful glyphs for doing
board style games (the font has a very liberal license allowing
for such use) but couldn't use the whole font and had written
something to pull the glyphs I was interested in to individual
files for inclusion in my projects.

The resulting bezier can be manipulated in may interesting ways
before rendering.

Keep that in mind and you may yet find the snippet useful!

Good luck!