Using custom fonts in application

Quick one: Is there a way to use custom TTF fonts included in the application in the application itself without installing them in the system?

I have found references for mac that really only seemed to work in Carbon and I haven’t found a definitive way to do it in Linux. For Windows I believe WFS has a way but I haven’t yet investigated it further.

Do you know of any method to use a font file included in the resources folder in the application itself that works in Mac, Windows and Linux (or, rather, what is the best way to do it in each)

I’m not at my computer, but we have done it with a Cocoa app.

I’ll dig out what you need when I get back.

hmmm… turns out that it requires more code than can be easily pasted into the forum. If you have the MBS plugin, it should have the functions so a little translation from my code to the MBS will be required.

[code] Dim fontManager as new NSFontManager
call fontManager.registerFontsInFolder( app.resourcesFolder.child( “fonts” ), NSFontManager.scope.process )

Public Enum scope
none
process
user
session

Function registerFontsInFolder(inFolder as folderitem, inScope as scope) As boolean
Dim n,l as integer
Dim fontArray as new CFarray
n = inFolder.count
for l=1 to n
select case inFolder.item( l ).nameExtensionMBS
case “ttf”, “otf”
fontArray.addValue CFURL.createWithFSRef( inFolder.item( l ).macFSRef )
end select
next

declare function CTFontManagerRegisterFontsForURLs lib library ( urls as Ptr, inScope as Uint32, errors as Ptr ) as boolean
return CTFontManagerRegisterFontsForURLs( fontArray.handle, Uint32( inScope ), nil )
End Function
[/code]

You could also translate the CFArray to NSArray and the CFUrl to NSURL.

Thanks, Sam. I’ll see about integrating this.

Something I haven’t seen in any forum post is doing it for Linux. I’ll have to assume it just isn’t possible.

Well, we have “FontActivateMBS(OnlyLocal as boolean) as integer” on folderitem class for this to load a font.
But for Linux, well, we’d first need to check as you’d be the first to ask for it.

Yeah - sorry I don’t know anything about Linux, except it’s a FREE version of UNIX…

[quote=13982:@Christian Schmitz]Well, we have “FontActivateMBS(OnlyLocal as boolean) as integer” on folderitem class for this to load a font.
But for Linux, well, we’d first need to check as you’d be the first to ask for it.[/quote]

Thanks, Christian. As usual, I’ll try to do it first by hand and if not possible I’ll go the plugin route :slight_smile:

Is this on OS X?

Yes.

I believe that the ATSApplicationFontsPath Info.plist key still works, even though ATS itself has been deprecated. I haven’t tested it to check.

If it doesn’t work, CoreText offers a bunch of font management APIs that can be accessed via declares. Sam posted some, but there might be a simper route.

[quote=14449:@Joe Ranieri]I believe that the ATSApplicationFontsPath Info.plist key still works, even though ATS itself has been deprecated. I haven’t tested it to check.

If it doesn’t work, CoreText offers a bunch of font management APIs that can be accessed via declares. Sam posted some, but there might be a simper route.[/quote]

I’m surprised I forgot about this, you’re right that this is still in place.

I’ll see if I can add the key using a post-build script.

For those using this thread to find out:

For Cocoa, you can add entry “ATSApplicationFontsPath” to your app’s info.plist file, specifying the relative path of the fonts in your Resources folder. For Example, if your fonts are in a folder called AppFonts inside Resources then that needs to be specified as the path.

For Windows WFS helps with a function dedicated to this:

UIExtrasWFS.TemporarilyInstallFont( theFontFolderItem )

It’s probably good form to uninstall them when not needed any more, even if the installation is temporary. A method exists for that as well.

For Linux I suspect the mess that is font installation there means this is not an easy answer and it may just not be worth pursuing.

Previous post was a duplicate error, but since we can’t edit posts I can’t put the right text in it. :expressionless:

[quote=13982:@Christian Schmitz]Well, we have “FontActivateMBS(OnlyLocal as boolean) as integer” on folderitem class for this to load a font.
But for Linux, well, we’d first need to check as you’d be the first to ask for it.[/quote]

I’m definitely interested in font handling for Linux…

Im just about to need this facility.

I have the MBS plugins : yay!

But then I find

Another reason not to upgrade? Worrying.
Is there a workaround that also works in Xojo 2017?

If I am not mistaken, the issue will be solved in 2017R2. I have seen that in the bug report. Christian probably tested.

After much testing, it appears that ActivateFontMBS doesnt activate the font well enough for the font to be used embedded in a DynaPDF document.

Works if I install it into Fonts, but not if I ActivateFontMBS(true)
Although on-screen controls are happy enough after the MBS call.

Now things are getting scary.
DynaPDFMBS wont use the font unless it is installed.
So I have been looking into ‘how can you install a font in OSX’
Launching it SHOULD open in Font Book , but on my machine I found TTF associated with Glyphs , so thats a non starter… the same could be true anywhere else.

‘To install a font copy it to the Fonts folder’ says the internet.

OK:

F= parentfolder.child(“MYfont.ttf”)
f.copyfileto specialfolder.fonts

Doesnt work.
No does specialfolder.userlibrary.child(“Fonts”)

Now, after a lot of mucking about, the TTF file is not in any of the various fonts folders in my Mac, yet Xojo lists it in the .Font() array.
Try to use it and get an error.
Fontbook doesnt list it, yet Xojo does.

Im in a mess… how can this happen?

Jeff you can fix the file assignment for TTF using the file inspector in Finder. I haven’t got a copy of Glyphs, but I would assume third party font managers would let you install fonts.

Next, SpecialFolder.Fonts is the System level font directory, you would need administrator permissions to copy files into it. Copying fonts into the user’s font directory is rude without asking the user.

Yourapp can see the font because you activated it with MBS for just your app. If you didn’t deactivate it before quit, there’s a possibility that your app still has the font activated. I have seen this more on Windows than Mac, but it did lock the font file from being allowed to get deleted, and then proceeded to become quite the nightmare as it persisted through a system reboot. Be sure to deactivate any font you activate during CancelClose. I recommend CancelClose because you can get error codes back from the deactivation, and perhaps you want to handle them somehow.

Lastly, remember that on Mac, after installing a font you have to re-start an application for the app to be able to see and use the new font. I’m not entirely sure what your use case is, but if you’re going to require that fonts are installed you may be one of those rare instances where a .pkg installer is a better option.

>>Jeff you can fix the file assignment for TTF using the file inspector in Finder.<<
Oh indeed. Already done it. But users… Just making a note against potential support calls. It will happen, and I’d like to avoid it completely
[i]

Next, SpecialFolder.Fonts is the System level font directory, you would need administrator permissions to copy files into it. <<[/i]
So thats a no

>>Copying fonts into the user’s font directory is rude without asking the user.<<
Yes even if I ask, the CopyFileTo process doesnt succeed.

it persisted through a system reboot. <<
Ive restarted and the phantom menace has now cleaned itself up.

I’m not entirely sure what your use case is, but if you’re going to require that fonts are installed you may be one of those rare instances where a .pkg installer is a better option.<<

Starting to look that way.
Over the years Ive used zip, dmg, and pkg
I went off pkg after I found it would update an app that was already in the Trash instead of installing a new copy into Applications. Too clever for its own good!
But I cant find a way to add an Alias for Fonts into a DMG, in the way that I have an alias for ‘Applications’
That would be the ideal, I think: customer drags font to Fonts , and app to Applications…

Well, I have a solution but it’s not great.

There are several ways to have a font available to your app only.
The MBS plugin will activate it temporarily.
Adding two lines to your apps info.plist will also do the trick

The temporary font will appear in the font enumerations and can be used in your Xojo app to draw on graphics and in controls.

But a temporary font like this cannot be used with DynaPDFMBS with a line like this:

call pdf.SetFontAnsi appfontname, pdf.kfsNormal, 25 , true, pdf.kcp1252

Which should force the use and embedding of the font.
The only way I can find to make that work is to install the font ‘properly’ , which I really didnt want to have to do.

Copying to SpecialFolder.fonts should do it, but the call fails silently.
since I cant seem to create a DMG with an alias to Fonts in the way that I can to Applications,
my final working solution is this:

f = somefolder.child("MyFont.ttf") f.CopyFileTo specialfolder.UserLibrary.child("Fonts")