Detecting the actual system font on OSX

Until OSX 10.9, the system font was usually “Lucida Grande”, but in 10.10 it has changed to “Helvetica Neue”.

Now, I like to display a font menu, with font names that I can assign to Xojo controls (e.g. to a Label’s TextFont property), and I also like to identify the default (system) font on that system, without hard-coding the name.

Is that possible?

I’ve tried getting the system font name by asking the Cocoa API, i.e. +[NSFont systemFontOfSize:0], but that’s not working well, because it gives me “System Font Regular” on 10.10 with Xojo 2015r2, which is a name I cannot match to the Font list I get from Xojo with the Font() function.

And Xojo doesn’t seem to offer any way to “translate” between OSX’s NSFont names and the names Xojo uses, or does it?

Any suggestions?

Another oddity:

When I set a Label’s TextFont to “Helvetica Neue”, its text appear significantly smaller than when I use “System” as its font name. Why is that? Is the system font actually not “Helvetica Neue” but something else such as “Helvetica Neue Phat”?

[code]Declare Function NSClassFromString Lib “Foundation” (className As CFStringRef) As Ptr
Declare Function systemFontOfSize Lib “AppKit” Selector “systemFontOfSize:” (NSFontClass As Ptr, size As Single) As Ptr
Declare Function fontName Lib “AppKit” Selector “fontName” (NSFont As Ptr) As CFStringRef

Dim fontClassPtr As Ptr = NSClassFromString(“NSFont”)
Dim systemFont As Ptr = systemFontOfSize(fontClassPtr, 13)
Dim fontName As String = fontName(systemFont)[/code]

Eli, that code seems to be pretty much the same I described above having already tried - and it gives me a font name I cannot match to any font name that Xojo’s Font() function returns, so I cannot figure out which font I actually have of Xojo’s list of fonts.

I get
.HelveticaNeueDeskInterface-Regular

I just found this bit of information:

[quote]OS X Yosemite doesn’t actually use the standard Helvetica Neue, they’ve tweaked it for use in the UI. It’s defined in the OS as:

sysFont: NSFont = { font = HelveticaNeueDeskInterface-Regular, pointSize = 13.00 }[/quote]

Thanks, you all confirm what I have found. Now, how do I figure which font is this system font when I get the Fonts with this code:

for i as Integer = 0 to FontCount-1 dim fontName as String = Font(i) if fontName = sysFont then ' got it! end next

I need this detection so that I can pre-select the system font when I show font menu.

Or, alternatively, if I use NSFont to get a complete list of fonts so that I can determine the system font this way, how do I translate their font names so that I can assign them to a Control’s TextFont?

(How odd, all those Europeans working this late … get a life! :smiley: )

We all watched Bayern vs Porto :wink:

You’re not going to get an exact match, the OS is returning the Postscript name of the font, you’ll need to do a conversion to get the familyName, which is what Xojo uses.

Seems strange, but maybe there is no real solution to the problem for Thomas.

The only solution I found was to hardcoding it in case of Yosemite. Hence I have to lie, telling that something displayed with System font is “Helvetica Neue”. Which is not… :frowning:

But that name comes from some OSX API, doesn’t it? I wonder if I can use the two different APIs to match the fonts, then? But I don’t even know where to start.

I decided to take a look around and what I can determine is that the system font is a custom hidden font, it doesn’t appear in any of the font lists, not even in Apple’s Font Book.

If you want to display that in a font menu, I would suggest using the declares to get the familyName, then if that name doesn’t match what Xojo returns, manually add it to your font list.

Jean-Paul, I don’t see what your code adds to the previous code. All it gives me additionally is the index into the CTFontManager’s array. How shall I use that information?

However, I found out by experimentation that I can assign those font names from [NSFont fontName] to a TextFont property, and it appears to work, even if these names do not match any of the font names returned by the Font() function.

Sadly, this is not documented clearly, so it’s not reliable, as Xojo engineers like to point out in these cases.

Plus, as pointed out before, when I assign the so-found system font name to a Label’s TextFont, the displayed text is not the same as the default “System” font - it’s smaller!

Thus the challenge remains: With neither Xojo’s own Font() function nor with the other OSX Font functions I can put a font name to the font that Xojo uses for “System”.

Which makes the “System” font not a real font but a pseudo font, it seems, meaning I’ll have to add this pseudo font to my font menu, and call it “System” so that the user can choose that. Oh well,maybe that’s for the best.

The idea behind the “system font” is that it should only be used with selectors like “systemFontOfSize:”. It gives Apple the possibility to change the font without breaking any code.

So the system font is kind of an opaque thing. I would go with showing “System” to the user in a PopupMenu or so.

Another problem is, that the font name is localized. I’m using MBS to get the font name:

[code]Function getAppearanceFont(doSmall as Boolean) As String

'get the standard font, either for standard size or small size

dim FontSize as Double
if doSmall then
FontSize = NSFontMBS.smallSystemFontSize
else
FontSize = NSFontMBS.systemFontSize
end if
dim theFont as NSFontMBS = NSFontMBS.systemFontOfSize(FontSize)
dim FontName as String = theFont.familyName
Return FontName

End Function[/code]

Then I check this with

dim theFont as String = OSUtils.getAppearanceFont(false) if theFont = ".Helvetica Neue DeskInterface" or theFont = kSystemFontRegular then theFont = "Helvetica Neue"

where the constant is: kSystemFontRegular = “System Font Regular” or “Systemschrift Normal” for German.

The problem is getting worse in OS X 10.11:

There, the actual system font named “San Francisco” doesn’t even appear in the Fonts list any more. So, when I build a list of fonts so the user can choose which font to use in Xojo text controls, I cannot even offer the system font a a choice any more because it’s simply not seen by Xojo’s Font functions. Damn.

The System font is hidden by the OS (the name of the file starts with a dot).
You have access to it by using:

aControl.TextFont = "System"

In my application I have a popup menu which looks like this:

[code]System
System (small)

Abadi MT
American TypeWriter
…[/code]
It wouldn’t make sense to show the actual name of the system font as the user doesn’t know the name of it.

The system font varies by versions of OS X. This is the kind of thing where trying to reinvent the wheel by hacking the actual font behind system is counterproductive IMHO.

If one wants more control about which fonts are used in a UI, why not, stick to Lucida Grande. It is present in all versions of the system. It is also possible to use custom fonts.

That said, I tend to stick to “System”, because Apple goes to great lengths tweaking and polishing its system font for the best legibility and display. Importantly, as machines screen size and resolution change, what has worked for the previous generation may not look as good in, say, a Retina display today.

Not using system means on 10.7 10.8 and 10.9 you look one way, 10.10 another, and in 10.11 another
If they change the system font every release you’d only ever look right on one
Thats the whole point of “System”