Skip to content

Add OpenType font feature support via 'guifont' ":f" modifiers#1689

Open
humblehacker wants to merge 5 commits into
macvim-dev:masterfrom
humblehacker:add-macfontfeatures-option
Open

Add OpenType font feature support via 'guifont' ":f" modifiers#1689
humblehacker wants to merge 5 commits into
macvim-dev:masterfrom
humblehacker:add-macfontfeatures-option

Conversation

@humblehacker

@humblehacker humblehacker commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

This adds OpenType font feature support — character variants, stylistic sets, etc. — to MacVim's Core Text renderer, using the same :f 'guifont' modifier syntax that patch 9.2.0321 introduced for the Win32 DirectWrite backend:

:set guifont=Maple\ Mono:h14:fss19=1:fcalt=0   " tag=value, one feature per :f entry
:set guifont=Maple\ Mono:h14:fcv01             " bare tag is equivalent to tag=1
:set guifont=Maple\ Mono:h14                   " no :f entries restore font defaults

tag=0 disables a feature the font enables by default (e.g. fcalt=0); default features are otherwise preserved, matching the Win32 behavior.

Implementation

  • MacVim's 'guifont' parser (gui_macvim_font_with_name) accepts h<size> and f<feature> modifiers. Each feature is validated during font parsing (four-character printable-ASCII tag, optional =<number>); an invalid entry rejects the font with E596, like other malformed guifont values.
  • Features are carried in the normalized font string (so getfontname() round-trips them) and sent to the GUI via a new SetFontFeaturesMsgID (appended before LoopBackMsgID so existing message IDs keep their values across version skew).
  • MMCoreTextView parses the list into a kCTFontFeatureSettingsAttribute array and applies it in fontVariantForTextFlags: after bold/italic trait conversion, so the base, wide, bold, and italic fonts all pick up the features and they survive NSFontManager trait conversion. Font caches are invalidated on change.
  • The OpenType feature tag API requires macOS 10.10; on the legacy 10.9 build the setting is ignored via the usual @available guard. The legacy (non-Core Text) renderer ignores the option, matching 'macligatures'.
  • Standard ligatures remain governed by 'macligatures', which takes precedence over a liga entry (documented).

Note on history: the first revision of this PR implemented this as a new 'macfontfeatures' option; per review feedback it now uses the cross-platform 'guifont' syntax instead, and the option has been removed. The renderer-side machinery is unchanged.

Testing

  • test_macvim.vim: guifont :f round-trip and E596 validation tests (GUI-only, skipped in terminal runs); test_codestyle.vim passes.
  • Manually verified with Maple Mono: fcv01=1 changes the rendered character variants, features apply to bold/italic/wide variants, fcalt=0:fliga=0 decomposes the font's default ligatures, an unsupported tag renders unchanged, and removing the :f entries restores defaults.
  • Docs added to the MacVim section of gui.txt, mirroring the Win32 fXX flag documentation.

AI disclosure

This contribution was developed with AI assistance (Claude Code); the design, implementation, and documentation were AI-generated under my direction, and I reviewed and tested the result.

🤖 Generated with Claude Code

Add a SetFontFeaturesMsgID message that carries a comma-separated list
of OpenType feature settings ("tag" or "tag=N" entries).  The Core
Text renderer parses the list into a kCTFontFeatureSettingsAttribute
array and applies it when deriving the fonts used for drawing, so the
base, wide, bold and italic fonts all pick up the features.  Requires
macOS 10.13 for the OpenType feature tag API; older systems ignore the
setting.  The legacy renderer does not support font features.

Signed-off-by: David Whetstone <david@humblehacker.com>
The macfontfeatures option is a comma-separated list of OpenType font
features to enable, e.g.:

    :set macfontfeatures=cv01,cv09,ss03=2

Each entry is a four-character feature tag optionally followed by "="
and a number; a bare tag is equivalent to "tag=1".  This allows
selecting character variants and stylistic sets in fonts that provide
them, similar to font feature settings in other editors.  Setting the
option to an empty string restores the font's default features.

Invalid values are rejected with E474.  Includes tests for option
existence, validation and round-tripping.

Signed-off-by: David Whetstone <david@humblehacker.com>
Signed-off-by: David Whetstone <david@humblehacker.com>
@humblehacker

Copy link
Copy Markdown
Contributor Author

The test failure doesn't look like it's related to my changes. Can we retry the build?

@eirnym

eirnym commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Looks good for me in the first glance.

  • is macOS 10.13 check is the only check required?
  • do you plan to add routing of an existing flag via yours as they essentially would duplicate each other.
  • is it possible to disable a feature or it is not required?

The kCTFontOpenTypeFeatureTag and kCTFontOpenTypeFeatureValue keys are
available since macOS 10.10 per the CoreText SDK headers, which also
document that OpenType setting dictionaries are accepted by
kCTFontFeatureSettingsAttribute starting with OS X 10.10.  The 10.13
guard was stricter than necessary.

Signed-off-by: David Whetstone <david@humblehacker.com>
Adopt the OpenType font feature syntax that patch 9.2.0321 introduced for
the Win32 DirectWrite backend, e.g.:

    :set guifont=Maple\ Mono:h14:fss19=1:fcalt=0

The ":f" entries in 'guifont' are validated during font parsing (an
invalid entry rejects the font with E596) and routed through the same
SetFontFeaturesMsgID mechanism to the Core Text renderer.  A bare tag is
equivalent to "tag=1"; "tag=0" disables a default-on feature.

This removes the MacVim-specific 'macfontfeatures' option in favor of the
cross-platform 'guifont' syntax.

Signed-off-by: David Whetstone <david@humblehacker.com>
@humblehacker

humblehacker commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for you review!

  • is macOS 10.13 check is the only check required?

I believe it is, but it was overly strict. I've dropped it to macOS 10.10, since that's the minimum supported by kCTFontOpenTypeFeatureTag/kCTFontOpenTypeFeatureValue, and code comments on kCTFontFeatureSettingsAttribute indicate OpenType setting dictionaries are accepted starting 10.10.

  • do you plan to add routing of an existing flag via yours as they essentially would duplicate each other.

Good call. I completely missed that guifont on Win32 already supports font features. It makes way more sense to build on that than to add this new macfontfeatures flag, so I've gone ahead and made that change.

  • is it possible to disable a feature or it is not required?

Yes — tag=0 disables a feature the font enables by default, e.g. :set macfontfeatures=calt=0,liga=0. This is documented and I verified it against a real font: with calt=0,liga=0, Maple Mono's default != and -> ligature glyphs decompose back into their individual component glyphs.

@humblehacker humblehacker changed the title Add 'macfontfeatures' option for OpenType font features Add OpenType font feature support via 'guifont' ":f" modifiers Jul 5, 2026
@eirnym

eirnym commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Thank you for your responses and additional work.

I've added information about minimal supported version in the changelog somewhere. This will be useful for MacPorts port for old macOS versions, not for a general public version.

One more seemingly unrelated question: how could I list all features for a given font and read more information about them?

@humblehacker

Copy link
Copy Markdown
Contributor Author

There are a few third-party command-line tools that could give you that info, but they're not available by default and I don't know them off the top of my head. FontBook unfortunately doesn't show this detail, and the built-in typography settings in macOS's font selection panel show some, but not a complete set. We could add a really simple CoreText function that could dump this info, but I'm not sure if that kind of thing belongs in MacVim. Generally, I find this info where I find the specific font. For example, Maple Mono has a really helpful "Playground" for experimenting with the various features.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants