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

Investigate/implement renderer setting to disable ligatures #759

Closed
Tracked by #1790
miniksa opened this issue May 13, 2019 · 29 comments · Fixed by #10525
Closed
Tracked by #1790

Investigate/implement renderer setting to disable ligatures #759

miniksa opened this issue May 13, 2019 · 29 comments · Fixed by #10525
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. Issue-Task It's a feature request, but it doesn't really need a major design. Priority-3 A description (P3) Product-Terminal The new Windows Terminal. Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Milestone

Comments

@miniksa
Copy link
Member

miniksa commented May 13, 2019

I think there is a setting somewhere in the DirectWrite stuff that will let you tell ligatures to go away and just use the individual symbols from a given font.

I think that by doing nothing, fonts like Fira Code are choosing the ligature.

This represents rooting around in DirectWrite land to see if:

  1. If there is a setting to stop ligatures from forming
  2. If we should pipe it through (or tell folks to stuff it because they could just choose a non-ligature font)
  3. Piping it through as a user preference, potentially.

Anyone could do the rooting around, so tagging as help-wanted. Please don't get too far without letting us know the investigation first.

Also, this is coming out of #514

@miniksa miniksa added Help Wanted We encourage anyone to jump in on these. Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. labels May 13, 2019
@mdtauk
Copy link

mdtauk commented May 13, 2019

The font picker that gets added to the app settings, could be sure to include options for discretionary ligatures, as well as possibly stylistic sets?

Opentype gives you a lot of options, as do Variable fonts, which could have a width slider for fonts which support that.

This should also lead to a discussion about the design and features of Cascadia Code or future versions of Consolas and which of these Opentype/Variables features should be implemented.

image
image
Stylistic Alternatives

image
Ligatures

image
Variable Weight

@ghost ghost added the Needs-Tag-Fix Doesn't match tag requirements label May 17, 2019
@miniksa miniksa added Product-Terminal The new Windows Terminal. and removed Mass-Chaos labels May 17, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label May 17, 2019
@dlong11
Copy link

dlong11 commented Jun 1, 2019

@miniksa shot in the dark here - I have done some DirectWrite work in the past and I think you can do what you want with "GetGlyphs". I am not sure the code I am referencing is even used in your scenario but I thought maybe with some luck the suggestion would be helpful. If not sorry for wasting your time. ☹️

// Can you pass in features and featuresLength to disable ligatures?
DWRITE_FONT_FEATURE fontFeature = { DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES, 0 };

r = _analyzer->GetGlyphs(..., fontFeature, length, ....)

@be5invis
Copy link

be5invis commented Jul 8, 2019

@miniksa
IDWriteTextAnalyzer's methods (GetGlyphs, etc.) accept a list of feature tags (like liga for liagatures), and you can easily configure that.
For variation support, you need to use IDWriteFactory6 and related methods to deal with that. (MSDN don't have documents about it! WHY?)

Please note that there are some features that are mandatory for supporting complex scripts, so they cannot be turned off. IDK whether rvrn belongs to it, and it is used to support variable fonts' non-continuous variations. (check out this crazy example!)

Here are some sample code: https://github.com/fdwr/TextLayoutSampler/blob/master/DWritEx.ixx

cc. @fdwr

@DHowett-MSFT DHowett-MSFT added Issue-Task It's a feature request, but it doesn't really need a major design. and removed Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. labels Jul 8, 2019
@DHowett-MSFT DHowett-MSFT added this to the Terminal v1.0 milestone Jul 8, 2019
@jasonxoc
Copy link

jasonxoc commented Sep 4, 2019

Is it appropriate to have a font rendering option that forces mono spaced glyphs? Or is this specifically an issue with the font? I may have this wrong but I think there are half/double spaced glyphs, however in other terminal emulators powerline / nerdfont arrow glyphs are single spaced glyphs but in this terminal it's making the arrows double spaced glyphs. By the way, what MS is doing for developers is incredible.

@jasonxoc
Copy link

jasonxoc commented Sep 4, 2019

Ah sorry guys, I see that this was talked about here:

The powerline glyphs are in a region of the character table specified as "ambiguous width." Whenever we get one of those, we ask the font how wide the grapheme cluster is. This is required to eventually support things like Devanagari and other N:M glyph->cell mapping scripts. Anyway, the standard NerdFont patcher installs the powerline glyphs as double-width glyphs.
So, Windows Terminal asks how wide the powerline characters are and gets "two cells".
There's a conhost instance backing every tab. That one also (for a long list of legacy compatibility reasons that are better explained in #1739) needs to count cells and widths and characters and stuff. That one is not using the same font, so it gets a different answer: "one cell".
They trivially and immediately disagree on where the cursor is, and where all characters after the mis-identified grapheme cluster are.

@obskyr
Copy link

obskyr commented Sep 20, 2019

Chiming in here to say that there is (anecdotally) a significant number of people who aren't big fans of fancy coding ligatures, and that being able to turn them off would be a godsend. Personally, I'd like to try using the shiny new Cascadia Code you guys have so lovingly put together, but not being able to disable its ligatures is stopping me from sticking with it.

@thundernixon
Copy link

Currently, Fira Code & Cascadia Code rely on the opentype feature calt to display code ligatures. This feature should be active by default, but is possible to turn off. From what I can tell, this is how VS Code offers an option to toggle code ligatures (their option toggles both liga and calt).

I am currently making a font with code ligatures (https://github.com/arrowtype/recursive), and looking into using discretionary ligatures dlig for code ligatures, for exactly the reason that some people like them, but some people don't, and I don't believe they should be on by default.

So, in my mind, the ideal controls for this would be:

  1. One setting to disable default ligatures (liga, clig, and calt)
  2. Another setting to enable optional ligatures (dlig)

@fdwr
Copy link

fdwr commented Oct 2, 2019

@thundernixon Would you ever want to display dlig without clig? That is, are there 4 distinct states of interest here, or just 3? (a) No ligatures at all (b) Default ligatures (c) All ligatures.

@thundernixon
Copy link

@fwdr good question! It's hard to be totally confident in a universal statement about typography, especially because I am only familiar with Latin script. However, I think you are mostly correct in seeing this as a three-state option, rather than a four-state option. Both are abstractions, but the simpler one probably covers almost all reasonable (Latin) uses of these four features, and would have the benefit of being possible through a single setting with a radio-button option.

I see it as:

  1. no ligatures at all, even if they improve readability
  2. subtle ligatures that are "default" to the typeface, there to improve readability without being especially noticeable (liga, clig, and calt)
  3. noticeable, "decorative" ligatures that are there to add style and delight (dlig)

It's natural to add ligatures for readability without adding ligatures for flair. However, I doubt many type designers or users would want to add ligatures for flair, without also adding ligatures for readability.

@be5invis
Copy link

be5invis commented Oct 3, 2019

@thundernixon
Why can't we just allow users to specify features and variation coordinates? Like {variation:{wght: 350}, features:['calt', 'liga', 'COOL']}.
Note: we may need allowing them to specify variations for bold (axis wght), italic (axis ital, slnt) and bold-italic.

@obskyr
Copy link

obskyr commented Oct 3, 2019

@be5invis It's just not very user-friendly, is it? A user shouldn't have to know the specifics of the OpenType format to turn ligatures on or off.

@thundernixon
Copy link

@obskyr well, it could basically follow the CSS approach to font control, which should presumably be friendly enough for most folks wanting to customize a developer app. It would likely be less about them knowing the opentype format, and more about font developers documenting what settings are available. It would open up so much more flexibility to allow users to specify variation axes and opentype features, and avoid asserting an abstraction onto all languages, users, and screens. After all, almost 100% of the user’s interface in a terminal is typography, so it might make sense to allow some control.

Potentially, might there be a way to have a simple ligature (choices Off, Default, All) control, but allow this to be overridden by a @be5invis’s CSS-like advanced setting?

@be5invis
Copy link

be5invis commented Oct 4, 2019

@thundernixon
OpenType: "Off", "Default", "All", "Custom" ← write "CSS" if this option is chosen.

@arrowtype
Copy link

@be5invis I like it! Though, I think the label OpenType wouldn't really be quite clear ... what is OpenType: All? Maybe something like...

OpenType: ⚪️Off   🔘Default ligatures   ⚪️All ligatures   ⚪️Custom...

@arrowtype
Copy link

arrowtype commented Oct 4, 2019

Though, I think it would have to be constrained what CSS could be written. Probably, it should be specifically font-feature-settings, and allow whatever values that allows, like "dlig", "ss08", "swsh" 2, "onum"; etc.

https://helpx.adobe.com/fonts/using/open-type-syntax.html

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/OpenType_fonts_guide

Specifically, I think font-variation-settings would make more sense if placed nearby general font choice – maybe under a Custom... or Advanced... button of some sort.

@arrowtype
Copy link

Looping back on this with something related:

VS Code now supports control over opentype features, including dlig, stylistic sets, and more!

microsoft/vscode#80577

Basically, they have just allowed users to directly enter OpenType tages into the settings.json file, under fontLigatures:

"editor.fontLigatures": "'ss01','ss02','dlig','onum'"

This isn't perfect, because the name of the setting isn't quite logical – ligatures are only one type of OpenType feature. A more apt name might be something like editor.openTypeFeatures or fontFeatures (similar to font-feature-settings in CSS). Still, it's a very good start, and the general scheme of entering OT feature tags into JSON settings seems like it might be pretty ideal for the Windows Terminal's profile.json settings!

@cinnamon-msft cinnamon-msft removed this from the Terminal v1.0 milestone Jan 23, 2020
@PetterS
Copy link

PetterS commented Apr 23, 2020

This isssue is now more important, because after the latest update, Cascadia Code includes ligatures which cause visual problems in Terminal, e.g. when printing "." after one another like a progress bar.

ghost pushed a commit that referenced this issue Apr 23, 2020
It was brought to our attention that shipping a font with ligatures as our default
font could be an accessibility issue for the visually-impaired. Unfortunately, we
don't have a renderer setting to disable ligatures (#759). Fortunately however, we
DO already have a version of Cascadia that doesn't have ligatures.

If we ship that and set it as our default font, we'll at least let people _opt_ to
have ligatures enabled by switching from `Cascadia Mono` to `Cascadia Code`.

## PR Checklist
* [x] Closes internal discussion
* [x] CLA signed
* [ ] Tests added/passed
* [x] Requires documentation to be updated
* [x] I've discussed this with core contributors already.
@miniksa
Copy link
Member Author

miniksa commented Apr 24, 2020

My best guess here, which hasn't been validated yet, is passing a DWRITE_FONT_FEATURE_TAG with DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES (https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_font_feature_tag) in a DWRITE_FONT_FEATURE (https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) with the parameter set to 0 or something inside the IDWriteTextAnalyzer calls to GetGlyphs (https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritetextanalyzer-getglyphs) and/or GetGlyphPlacements (https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritetextanalyzer-getglyphplacements) inside our CustomTextLayout class.

I would have to play around with it and/or ask the DWrite folks.

DHowett-MSFT pushed a commit that referenced this issue Apr 27, 2020
It was brought to our attention that shipping a font with ligatures as our default
font could be an accessibility issue for the visually-impaired. Unfortunately, we
don't have a renderer setting to disable ligatures (#759). Fortunately however, we
DO already have a version of Cascadia that doesn't have ligatures.

If we ship that and set it as our default font, we'll at least let people _opt_ to
have ligatures enabled by switching from `Cascadia Mono` to `Cascadia Code`.

## PR Checklist
* [x] Closes internal discussion
* [x] CLA signed
* [ ] Tests added/passed
* [x] Requires documentation to be updated
* [x] I've discussed this with core contributors already.
@KalleOlaviNiemitalo
Copy link

Would this setting also disable the abnormal rendering of x between digits (microsoft/cascadia-code#285)?

@DHowett
Copy link
Member

DHowett commented Jun 12, 2020

Yes.

@ghost ghost added the In-PR This issue has a related PR label Jul 13, 2021
@ghost ghost closed this as completed in #10525 Jul 22, 2021
@ghost ghost added Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Jul 22, 2021
ghost pushed a commit that referenced this issue Jul 22, 2021
Adds support for users to be able to set font features and axes (see the spec for more details!)

## Detailed Description

**CustomTextLayout**
- Asks the `DxFontRenderData` for the font features when getting glyphs
- _If any features have been set/updated, we always skip the "isTextSimple" shortcut_
- Asks the `_formatInUse` for any font axes when mapping characters in `_AnalyzeFontFallback`

**DxFontRenderData**
- Stores a map of font features (initialized to the [standard feature list])
- Stores a map of font axes
- Has methods to add font features/axes to the map or update existing ones
- Has methods to retrieve the font features/axes
- Sets the font axes in the `IDWriteTextFormat` when creating it

## Validation Steps Performed
It works!

[standard feature list]: https://github.com/fdwr/TextLayoutSampler/blob/ac5aef67d1cc0cb67c5e3be29b30bda5a90c3e2b/DrawableObject.ixx#L802

Specified in #10457
Related to #1790 
Closes #759
Closes #5828
@ghost
Copy link

ghost commented Aug 31, 2021

🎉This issue was addressed in #10525, which has now been successfully released as Windows Terminal Preview v1.11.2421.0.:tada:

Handy links:

@pedrolamas
Copy link

Unless I'm missing something, this doesn't seem to be working correctly...

image

I've tried a few fonts that I know that have ligatures support, and I couldn't get them disabled in Windows Terminal 1.11.2421.0

@pedrolamas
Copy link

Found my problem: it's "features", not "feature"... after making that change I could see it working perfectly with CaskaydiaCove NF font!

@trallnag
Copy link

@pedrolamas, weird, your settings did not work for me. I had to set the following:

"features": {
    "calt": 0,
    "clig": 0,
    "dlig": 0
}

@pedrolamas
Copy link

@trallnag I probably have changed it and never actually noticed, but my main issue was the node name! In any case, these are the current flags I use:

"features": {
    "calt": 0,
    "clig": 0,
    "dlig": 0,
    "hlig": 0,
    "liga": 0,
    "rlig": 0,
    "salt": 1
}

@trallnag
Copy link

trallnag commented Oct 2, 2021

@pedrolamas, do you know a place where these flags are documented?

@pedrolamas
Copy link

@trallnag documentation links here: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/#font-features-and-axes

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. Issue-Task It's a feature request, but it doesn't really need a major design. Priority-3 A description (P3) Product-Terminal The new Windows Terminal. Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.