This font is a bit funky; the bitmap strikes are only 4px wide:
```
; ftdump gohufont.otb
There is 1 face in this file.
----- Face number: 0 -----
font name entries
family: Gohu GohuFont
style: Regular
postscript: UNAVAILABLE
created: 1904-01-01
modified: 1904-01-01
revision: 1.00
glyph count: 1694
font type entries
FreeType driver: truetype
sfnt wrapped: yes
type: fixed size
direction: horizontal
fixed width: no
glyph names: no
fixed size
0: height 11, width 3
size 11.000, x_ppem 11.000, y_ppem 11.000
1: height 14, width 4
size 14.000, x_ppem 14.000, y_ppem 14.000
charmaps (1)
0: format 4, platform 3, encoding 1 language 0 (active)
```
but using that the cell size isn't right.
We draw from the metrics we compute via cell_metrics to get more
information; we don't get a valid height from that (just 0!), but
we do get the much more plausible width of 8 pixels.
So we take the max of the two techniques for figuring the metrics.
That appears to work out, and also doesn't appear to break emoji
fonts.
refs: #1165
This was a bit of a PITA to run down; the essence of the problem
was that the shaper was returning an x_advance of 0 for U+3000,
which caused wezterm's shaping layer to elide that glyph.
I eventually tracked down the x_advance to be the result of
scaling by an x_scale of 0, which in turn is the result of
harfbuzz not knowing the font size.
The critical portion of this diff is the line that advises
harfbuzz that the font has changed after we've applied the
font size.
The rest is just stuff to make it easier to debug and verify.
This:
```
printf "x\u3000x."
```
Now correctly renders on screen as "x x".
fixes: #1161
- If possible use fontconfig to obtain character coverage instead of
going through all glyphs using freetype.
- `FT_Get_First_Char` typically returns ranges of continuous glyphs itself
and it is far cheaper (I measured a speedup of about 7 times while
catting a large file with lots of funny unicode) to add a range to the
glyph coverage instead of adding each glyph individually.
- Permit adding a range to a RangeSet without performing checks to speed
up things even further.
@H-M-H noticed and suggested this; rather than spawning a thread
for potentially every cluster of graphemes that are being displayed
before we've located a font, constrain things to a single thread
so that we don't burn CPU trying to process the same results
in an excessive number of threads.
Since fonts now use dual source blending, the pixel colors are
interpreted as individual alpha channels. The A component should
be set to 1.0, so that's what we do here.
refs: #1025
The introduction of the Emoji vs Text VS processing means that we might
in some cases not find a glyph with the requested presentation.
In that case, we'd rather show the emoji presentation glyph than none at
all, so we'll retry fallback processing with unspecified presentation.
refs: #997
The recent presentation logic needs to be tweaked to ensure that
we ignore presentation when we reach the fallback font, otherwise
we'll end up in a bad error stack and crash the program.
This commit annotates fonts with a boolean that indicates whether
we think it contains glyphs with emoji presentation, and then
passes the cluster.presentation field down to the shaper.
If the presentation doesn't match the current font in the fallback,
then it will be skipped until we exhaust its options.
`wezterm ls-fonts` also shows whether we think a font has emoji
presentation.
refs: #997
This commit hooks up DECRQM so that we can report that we implement
synchronized updates, and then refines the code that manages sending
data to the terminal model; the first cut at synchronized updates
was a bit simplistic, and now we make a point of "flushing" pending
actions when we start a sync point, and again as soon as we release
the sync point.
This smooths out the jaggies around the orca that I mentioned in
dcbbda7702
and while testing this, I realized that recent parser changes had
mangled processing bundled dec private mode sequences where multiple
modes were specified in the same overall escape sequence. I've
added the missing unit test case for this and made that work again.
refs: https://github.com/wez/wezterm/issues/955
refs: https://github.com/wez/wezterm/issues/882
opentype allows a font to have a weight in the range 0-1000.
MacOS has its own concept of symbolic weight names and opentype
values that is a slightly different scale of boldness to Windows
and Linux.
That means that Medium could be a different range of opentype
weight values depending on the system.
To further complicate things, the font designer can name their
variant with any name they like and assign it an arbitrary
opentype weight value.
For the Operator Mono font, it has Book variant with opentype
weight 325 and a Light variant with an opentype weight of 300.
wezterm was considering these both to have `FontWeight::Light` because
that's how those values were bucketed, which results in amibiguity in
resolve the font and frustration in not being able to access one of the
variants.
This commit changes the `FontWeight` type to now hold the unambiguous
opentype weight value, and to define some symbolic aliases for
some specified weights.
When serializing, if the weight matches a symbolic alias, then that
name will be used in the canonical name (eg: as listed via ls-fonts).
Otherwise, the numeric value will be used.
When parsing the font configuration, wezterm will allow both symbolic
and numeric values.
This allows all of the Operator Mono variants to be referenced
unambiguously, although some variants have to be specified via the
numeric weight:
```
wezterm.font("Operator Mono", {weight=275, stretch="Normal", italic=false}) -- /Users/wez/.fonts/OperatorMono-XLight.otf, FontDirs
wezterm.font("Operator Mono", {weight="Light", stretch="Normal", italic=false}) -- /Users/wez/.fonts/OperatorMono-Light.otf, FontDirs
wezterm.font("Operator Mono", {weight=325, stretch="Normal", italic=false}) -- /Users/wez/.fonts/OperatorMono-Book.otf, FontDirs
wezterm.font("Operator Mono", {weight="DemiLight", stretch="Normal", italic=false}) -- /Users/wez/.fonts/OperatorMono-Medium.otf, FontDirs
wezterm.font("Operator Mono", {weight="Regular", stretch="Normal", italic=false}) -- /Users/wez/.fonts/OperatorMono-Bold.otf, FontDirs
```
https://github.com/wez/wezterm/issues/849#issuecomment-873454483
Change the loader so that it has better matching weight and stretch
characteristics, and ask core text to return all possible candidates
so that we can then apply our CSS-style font matching rules.
Previously, the font descriptor we created would only match the
family name and return the normal/regular variant only.
refs: https://github.com/wez/wezterm/issues/873
This commit adds a slant to *scalable* (not bitmap!) fonts whose
originating font attributes requested italics but for for which
the resolved face is not italic.
refs: #815
This commit introduces the knowledge about whether a font is
scalable or was using bitmap strikes (eg: color emoji bitmaps).
Then that information is used to help figure out whether and
how to scale a glyph.
refs: https://github.com/wez/wezterm/issues/685
I *think* the heart of the issue is that the problematic fonts
don't define a `spacing` property, and we were being stric
about matching it.
This commit changes the behavior to strictly match the spacing
value when it is defined, but to allow an undefined spacing
value to match.
refs: https://github.com/wez/wezterm/issues/726
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