Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add style_name support to SystemFont to allow using specific members of font families #11712

Open
lostminds opened this issue Feb 6, 2025 · 6 comments
Assignees

Comments

@lostminds
Copy link

lostminds commented Feb 6, 2025

Describe the project you are working on

A non-game application where the user can select fonts from the system to use in the application

Describe the problem or limitation you are having in your project

With the addition of godotengine/godot#62973 we now have support for accessing fonts installed on the system via the SystemFont class. And we can get a list of the names of the installed fonts via OS.get_system_fonts().

However, a limitation to this is that the list only provides the font family names of the installed fonts (such as "Roboto" or "Arial") but there is no way to get the names of the members of the font family, for example Thin, Italic, Semi-Bold, Bold-Italic etc. Below is an example of the font family Roboto as seen in the macOS font manager.

Image

When loading a font from file, this name is accessible via get_style_name() so to keep with this convention I'll call this name style_name from now on.

However, there is no way to specify this style_name in SystemFont to access a specific font version. Instead, what you can do is specify font_weight or font_italic to try and find bold or italic style versions.

There is also no way to get what style_name members a font family has (could be just one or twelve, with various names), which makes it impossible to present a selector interface to select available system fonts where you can also show and pick the different variations of each font.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

First complement the existing OS.get_system_fonts() with a new OS.get_system_font_style_names(font_family_name) which would return an array containing the style names of all members of the installed font identified with the font family name (if any).

Second, extend the SystemFont class with a font_style_names property. This would work together with the font_names property to pick which font family member is selected and used by SystemFont. If font_style_names is set this should be used first and the font_weight, font_italic etc properties are disregarded if a match is found in the font_style_names array. However, in the spirit of the current implementation they could still be used as fallbacks. So for example if you specify a style_names "Thin" and font_weight 100 this could fall back to some other light style with low weight if no style named "Thin" is found.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

To get and populate a font selector list you could do something like:

var font_family_names:PackedStringArray = OS.get_system_fonts()
var font_style_names:PackedStringArray

for font_family_name:String in font_family_names:
   font_style_names = OS.get_system_font_style_names(font_family_name)
   # add selector items / sub-items based on font_family_name and font_style_names

EDIT: On macOS getting the members of a font family can be done via NSFontManager availableMembersOfFontFamily and on Windows There seems to be a corresponding FontFamily.GetTypeFaces that could be used to get this information.

To use a specific font style, for example Roboto Thin Italic you would then use:

var robotoFont:SystemFont = SystemFont.new()
robotoFont.font_names = ["Roboto"]
robotoFont.font_style_names = ["Thin Italic"]

or some user-selected font version using

var userFont:SystemFont = SystemFont.new()
userFont.font_names = [selected_font_family_name]
userFont.font_style_names = [selected_font_style_name]

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, it's currently not possible to get a list of installed font family members, at least not via the Godot font system. Possibly you could try getting paths to the system font files and try to list the files in these directories and try guess based on the filenames. But this seems inefficient and prone to errors.

It is also not possible to select a specific known font style member of an installed system font. In simple cases (like if there's a "Bold" style) it could be selected by setting the font family name as SystemFont font_names and setting font_weight to a guessed value of what the "Bold" style would have. But this will be increasingly difficult with style names like "Semi-Bold", "Book", "Roman", "Caption", "Display" etc that may not just refer to weight (and you don't know if they exist for this font).

Is there a reason why this should be core and not an add-on in the asset library?

Both SystemFont and the OS.get_system_fonts() function are core components, and the proposed support for getting and specifying font_style_names I think would allow them to be used as I think the original intention with the features was.

@bruvzg
Copy link
Member

bruvzg commented Feb 6, 2025

System font already has weight, stretch, italic properties that are used to select specific font style, these properties have pretty standard mapping to the style names. So it is possible to use specific styles from the system fonts, but not enum them.

@bruvzg bruvzg self-assigned this Feb 6, 2025
@lostminds
Copy link
Author

So it is possible to use specific styles from the system fonts, but not enum them.

Yes, you can pick different font styles by setting a desired weight etc. But without being able to know what styles are available per font family you don't know if there is for example a Bold, Semi-Bold, Black or whatever weight version of the specific font. And as I understand it specifying such unavailable weights will just result in falling back the closest available one. This can be desirable in some situations for rendering intents, but not in a situation where the user is selecting a font version and would expect the options shown to reflect what is available and be able to select and use these specific font family members.

Equally, just adding a OS.get_system_font_style_names(font_family_name) to get the font family members wouldn't be very useful if these enumerated style names couldn't also be used to specify the font in SystemFont. Even if based on these names you could (usually) kind of guess the italic and weight values of the available style names, using the names directly seems safer. This is why I propose these additions together.

@Calinou
Copy link
Member

Calinou commented Feb 6, 2025

Does the OS have a native font picker we can defer to? For complex font picking use cases, this would seem like the way to go to me.

@lostminds
Copy link
Author

Does the OS have a native font picker we can defer to? For complex font picking use cases, this would seem like the way to go to me.

macOS has a shared NSFontPanel you can use and on Windows there seems to be some sort of such dialogue even if the documentation there makes me a little unsure and I'm not sure it's used much.

For my use-case this would be acceptable, and perhaps a font picker dialog with a "use native" option similar to how the file dialogs work could be a reusable pattern. However, I'm pretty sure adding all the integrations with these diverse native font pickers would be a bigger project than implementing the proposal above.

@bruvzg
Copy link
Member

bruvzg commented Feb 6, 2025

Does the OS have a native font picker we can defer to? For complex font picking use cases, this would seem like the way to go to me.

Yes, but we do not use system font system, so it won't help much. Godot only uses the font file name from the system, so if it's a font collection (like most system fonts are), we still need to manually select the style when loading the font.

@lostminds
Copy link
Author

Yes, but we do not use system font system, so it won't help much.

Even if the OS-specific font objects we could get back from a native font picker would not be used directly they could still be used just as carriers of the font family and style names needed to then select the correct font file and style when loading it in the Godot font system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants