Determining the Path to a Font file

Hi All,
I need to get the path to a font file selected by users so that it can be used in a do shell script command. In my applescript studio version, I used an open panel, but I thought maybe there was a more slick way to do it within ASOC. I’ve looked through the documentation for NSFont, NSFontManager and NSFontPanel, but nothing jumped out at me. It seems that for the most part, once you have an NSFont instance, you work with that and there is no need for the path to the corresponding font file.

Did you look at NSFontDescriptor? There might be a few methods that could help you, maybe…

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

I don’t think you can get the path to the font file from the font instance – what do you want to do with your do shell script command? Maybe you can do what you need within ASOC and not use do shell script.

Thanks for the responses. No luck with the NSFontDescriptor, at least from what I can tell with my noobie skill of deciphering the documentation. I’m running a UNIX app with the do shell script command and it requires the posix path of the file it’s working on so, unfortunately, there isn’t an ASOC alternative. I think I’ll forgo the slick and go with an open panel :).

Actually, as I’m working on fonts and I don’t really know much about font management, if I want to set an initial directory for the panel, can I assume that the users fonts will always be found at “/Library/Fonts/”? It is for all the macs I’ve checked.

Actually you need to pass “~/Library/Fonts/” to the nsopenpanel for it to open in the user’s font folder. The tilde means the current logged in user’s home folder path on every machines, no distinction whatsoever. The version you posted was the path to the local font folder on the sartup disk. :slight_smile:

It’s strange that we can’t get access to the font’s path. I’ll check this when time permits and post back any result.

Good luck with your project!

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

This is why I asked. On my system, the font folder in my home folder path is empty. All my fonts are in the Fonts folder in the Library folder of the start up disk. Like I said, I don’t know anything about font management. They just magically show up when I want to change them :). But it seems that the location can vary, perhaps depending on how they were installed? Regardless, it seems like it would be useful to have a way of finding the location of the Font folder. Interestingly, if I use “fonts folder” in applescript, it points to Fonts folder in Library in the system folder.

Yeah, well there is so many apps and tools that can play in the fonts folders that it is hard to make sense of it.

Yes in AS you can use fonts folder but if you use either “of system domain” or “of locale domain” or “of user domain” (I could be off on the exact spelling, memory…) then you can specify which one you want. Check in the AppleScript editor, within the library window, the standard additions I think, it will have more details.

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

Hi,

in Snow Leopard you can get the path of a NSFont with CTFontDescriptor (a part of CoreText > ApplicationServices.framework)


- (NSString)pathToFont:(NSFont *)font
{
	CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize ((CFStringRef)[font fontName], [font pointSize]);
	CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
	NSString *fontPath = [NSString stringWithString:[(NSURL *)url path]];
	CFRelease(fontRef);
	CFRelease(url);
	return fontPath;
}

The problem is you can’t use CoreFoundation code in ASOC.
But you could create a custom Cocoa class and call the method from there

I think this needs to be (NSString *)pathToFont:(NSFont *)font

With that change, StefanK’s method worked for me with this call to it:

set myPath to objC’s pathToFont_(current application’s NSFont’s fontWithName_size_(“Times-Roman”, 12))

objC is a property connected to the blue cube that is of the class GetPath (the name of the .h and .m files where I put Stefan’s objective-C code).

Ric

Of course :slight_smile:

FWIW, I think stuff like this is a good reason to consider having a base Objective-C class in your projects that your app delegate inherits from. You can then quickly add methods like this and call them directly, without having to add/instantiate/add property.

Stefan: Is there some special reason you put “NSString stringWithString:” in there?

Yeah, I agree – I sometimes forget about that option. Another fix that makes the method simpler, is to pass the font name and size instead of the font object – since you have to call current application’s NSFont’s fontWithName_size_ and pass it that information anyway and then the objective-C method just gets those values back from the font object (of course, if you already have the font object, then Stefan’s way would be easier). So, this is the code I have now:

script FontPathAppDelegate
	property parent : class "GetPath"
	
	on applicationWillFinishLaunching_(aNotification)
		set myPath to pathToFontNamed_size_("Times-Roman", 12)
		log myPath
	end applicationWillFinishLaunching_
	
end script

And the GetPath.m is:

@implementation GetPath

    - (NSString *)pathToFontNamed:(NSFont *)fontName size:(CGFloat)fontSize
    {
        CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize ((CFStringRef)fontName, fontSize);
        CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
        NSString *fontPath = [(NSURL *)url path];
        CFRelease(fontRef);
        CFRelease(url);
        return fontPath;
    }
@end

Ric

I think you meant NSString rather than NSFont…

Oops! Yeah, that’s what I meant to do (but I forgot to change it from stefan’s method, and it worked anyway).

Ric

I want to make sure to get a retained string before releasing the URL object

I’m lost. Are you writing this with GC in mind?

I could understand if you were returning url itself, but not its path…

No, I’m an old-fashioned memory management guy :wink:

Probably it’s overcautious and not needed,
but my intention is, if the derived path depends on the url object,
it’s safer to create a new string object before releasing the url object.

Well as I read things, we still need to manage memory at the CF level, albeit a bit differently.

Thanks. So if instead I did something like:

NSString *fontPath = NSMakeCollectable(CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle))

I assume I’d be fine.

Actually you should write


NSString *fontPath = [NSMakeCollectable(CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle)) autorelease];

because of the leak of CFURLCopyFileSystemPath.

I just tested this


NSString *fontPath = [(NSURL *)url path];

and it worked perfectly

Uhh … you guys lost me about 10 posts back when you started talking about custom classes :). Would the “Adding Objective-C Code” section in Shane’s book be a good place to start the deciphering process? I’ve glanced at it but I haven’t really gone over it very thoroughly since for some reason when I see the “.h’s” and “.m’s”, my brain seems to go into a shut down mode :).