It now outputs something that you could conceivably put into
your config file, although the intent is to show the canonical
way to reference the individual fonts that were found, rather
than to specify a fully baked list to paste into a config.
eg:
```
; ./target/debug/wezterm ls-fonts
Primary font:
wezterm.font_with_fallback({
-- /home/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
{family="Operator Mono SSm Lig", weight="DemiLight"},
-- /home/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontConfig
{family="Operator Mono SSm Lig", weight="DemiLight"},
-- /home/wez/.fonts/MaterialDesignIconsDesktop.ttf, FontDirs
"Material Design Icons Desktop",
-- /home/wez/.fonts/terminus-bold.otb, FontDirs
{family="Terminus", weight="Bold"},
-- /home/wez/.fonts/JetBrainsMono-Regular.ttf, FontDirs
"JetBrains Mono",
-- /home/wez/.fonts/NotoColorEmoji.ttf, FontDirs
"Noto Color Emoji",
-- /home/wez/.fonts/MaterialDesignIconsDesktop.ttf, FontConfig
"Material Design Icons Desktop",
-- /usr/share/fonts/terminus-fonts/ter-u32n.otb, FontConfig
"Terminus",
-- /home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig
"JetBrains Mono",
-- /home/wez/.fonts/NotoColorEmoji.ttf, FontConfig
"Noto Color Emoji",
-- <built-in>, BuiltIn
"Last Resort High-Efficiency",
})
```
In earlier times, in an effort to avoid bleeding resources into
child processes, the fontconfig wrapper grew some logic to keep
track of how many fontconfig objects we'd loaded so that we could
aggressively unload it when there were none.
Since that time we've evolved differently pessimistic logic that forces
random fds closed when we spawn children so the critical need for unloading
fontconfig is no longer present.
Importantly, with the over-eager unloading, each font query we make
effectively needs to initialize fontconfig from scratch, which is a
fixed minimum cost of ~5-6ms on my system, and I've seen some traces
with a number as high as 100ms (those systems need `fc-cache` to be
run).
Removing the unloading keeps fontconfig initialized so we only pay
the 5ms cost once, then subsequent queries are in the order of 100us.
It seems difficult/impossible to phrase precisely the constraints
that we want when making a font config query, so this changes our
queries to use relative broad family and postscriptname list operations
and then we parse and filter using our own CSS-inspired font matching
criteria.
refs: #689
we now compute the ratio of the cap height (the height of a capital
letter) vs. the em-square (which relates to our chosen point size) to
understand what proportion of the font point-size that a given font
occupies when rendered.
When rendering glyphs from secondary fonts we can use the cap height
ratios of both to scale the secondary font such that its effective
cap height matches that of the primary font.
In plainer-english: if you mix say bold, italic and regular text
style in the same line, and you have different font families for
those fonts, then they will now appear to be the same height where
previously they may have varied more noticeably.
For emoji and symbol fonts there may not be a cap-height metric
encoded in the font. We can however, improve our scaling: prior
to this commit we'd use the ratio of the cell metrics of the two
fonts to scale the icon/emoji glyph, but this could cause the glyph
to be slightly oversized as seen in https://github.com/wez/wezterm/issues/624
If we know the cap-height of the primary font then we can additionaly
apply that factor to scale the emoji to better fit the cell.
While looking at this, I noticed that the aspect ratio calculation
for when to apply to the allow_square_glyphs_to_overflow_width option
had width and height flipped :-(
See also: https://tonsky.me/blog/font-size/
refs: https://github.com/wez/wezterm/issues/624
We weren't fixing up the active tab position correctly after removing
a tab. I think this bug crept in around the ActivateLastTab changes.
We now try harder to set active idx back to the tab that was active
prior to the remove, and ensure that we set the active index to
something within range if it was the active tab that was removed.
Refs: https://github.com/wez/wezterm/issues/690
Sort the available fonts list by family name (rather than full name),
then the styling attributes.
Display the font name in the preferred form for inclusion in the
wezterm config.
* Log which codepoints we're about to perform fallback resolution for
* Rank the fallback fonts by decreasing amount of coverage
* If a fallback covers the desired codepoints, remove those codepoints
from the set and reduce, so that we only add the minimal set of
fallback fonts for the set of codepoints
You can see what triggered fallback processing using:
```
; WEZTERM_LOG=wezterm_font=trace wezterm -n 2> /tmp/font.txt
; grep 'fallback font' /tmp/font.txt
2021-04-11T21:41:09.653Z TRACE wezterm_font > Looking for \u{d604}\u{c7ac}\u{be0c}\u{b79c}\u{ce58} in fallback fonts
2021-04-11T21:41:12.132Z TRACE wezterm_font > Looking for \u{f4e9} in fallback fonts
```
refs: https://github.com/wez/wezterm/issues/559#issuecomment-817260512
Now that all platforms know whether the system fallbacks
covered the requested glyph range, it is reasonable to
restore the configuration error window to advise the user
if they are missing fonts for the text they want to display.
refs: https://github.com/wez/wezterm/issues/671
Previously, we would add a list of ~100 or so fallback fonts to
the shaper's fallback list.
In pathological cases where a wide range of glyphs that have no
corresponding font are repeatedly emitted to the output, we'd
keep loading and unloading that large list of fallbacks in the
hope of finding a match.
Since that code was written, we're now able to compute the
codepoint coverage for ourselves, so teach the core text locator
how to reduce the the list of fallback fonts to just those that
contain the missing glyphs.
Furthermore, we restrict that list to just the normal/regular
weight/stretch/style fonts.
refs: https://github.com/wez/wezterm/issues/671
NSCursor hide/unhide must be perfectly balanced otherwise
the cursor can vanish unexpectedly when the mouse leaves
the window, and not come back.
So, let's use NSCursor:setHiddenUntilMouseMoves instead; it's
not 100% fulfilling the promise of the API, but it's close enough
and should avoid the permanent invisibility issue.
refs: https://github.com/wez/wezterm/issues/618
The intent is to reveal more context on what's happening in
https://github.com/wez/wezterm/issues/671
As a nice side benefit, this avoids the potential inability
to open paths that are not utf8 or representable as c-strings
on Windows.
And on top of that: this enables memory mapped file IO as well,
which wasn't enabled previously. This should help to reduce
extraneous copies of the font in memory, have fewer open files
and minimize the chances of racing with O_CLOEXEC.
This addresses the render artifacts aspect of https://github.com/wez/wezterm/issues/671
For whatever reason, some font(s) cannot be loaded on that system
and that results in the paint routine erroring out.
This commit avoids the error by substituting a blank glyph
instead of the glyph that failed to load.
refs: https://github.com/wez/wezterm/issues/671
When we process the system fallback list, we can produce a long list
of fonts to be speculatively processed by the shaper.
Until this commit, the shaper would always keep the associated
freetype face open forever, which increases the number of open
files and the amount of allocated memory.
This commit allows the shaper to release a font if it has never
produced any valid shaper results, which keeps the list down
to just the fonts that are in use.
Migrate information into the relevant config option pages, and
instead summarize with a demonstration of configuring the font.
For wezterm.font, there's now an expanded discussion on naming
and matching fonts.
closes: https://github.com/wez/wezterm/issues/560
We were handling the case where the chunk intersected a multibyte
boundary after the first chunk, but not for the first chunk itself.
Refactor the code so that we use the same chunk splitting logic
for both of those cases.
refs: https://github.com/wez/wezterm/issues/668
This commit allows the x11 window implementation to detect changes
in the DPI that occur after a window is created.
These can occur when changing desktop resolution or when changing
the accessibility option for "Large Text" in gnome.
In order to avoid continually polling for the value on every resize,
we look for the `_GTK_EDGE_CONSTRAINTS` atom in our property change
notifications. This seems to be sent at least as often as the
dpi/scaling changes.
It's also worth noting that some dpi changes don't generate resize
events, so we can't just read the dpi value on every resize, because
we'd miss some of those changes.
Part of this commit changes the font scaling logic: previously
we'd keep a notion of "dpi scale" to apply. That dates from an
earlier time in wezterm where we didn't think that we knew an
actual dpi value.
The way that worked was that we'd compare our current guestimate
of the DPI against what we though the baseline OS dpi should be to
produce a scaling factor.
On X11 that dpi value is global and we'd effectively always produce
a revised scaling factor of 1 after we'd set up the initial window.
This commit changes that logic to just pass down the actual DPI value
to the font code. That DPI value already accounts for HiDPI scaling
so this is hopefully a NOP change for the other systems.
refs: https://github.com/wez/wezterm/issues/667
I noticed edenscm log -p (using streampager) cannot render 256 colors
if TERM is not "*-256color", despite forcing enabling true colors in
streampager (https://github.com/markbt/streampager/pull/28).
I tracked it down here. The problem is that we ask terminfo for colors
it does not claim to support. Fix it by using fallback CSI rendering
for colors exceeding the terminfo max color.
The latest Rust handles more types of const expressions. So we can
use const fns or match directly without using workarounds like OptionPack
and macros.
Going to change how TRANSITIONS is generated. Add a test to ensure the
value is unlikely changed by the change. Note the string is 14K long
so we only hash its values to keep the code short.