1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-26 14:54:16 +03:00
Commit Graph

337 Commits

Author SHA1 Message Date
Wez Furlong
d3c748e18f fonts: enable matching against bitmap strike sizes
This is to handle situations such as some versions of the Terminus
bitmap font, where the individual bitmap strike sizes are broken
out across multiple individual files.

Font matching now passes down the nominal pixel height based on
the current DPI and font scale factor, and will use that to select
the font file that has the closest pixel size.

Previously, it would be potentially undefined which of the Terminus
font files would be selected.

refs: https://github.com/wez/wezterm/issues/1189
2021-10-02 09:33:55 -07:00
Wez Furlong
e287474973 fonts: fix a spacing issue for Goho OTB font
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
2021-09-25 08:57:26 -07:00
Wez Furlong
f648d8a6a5 deps: Upgrade to freetype 2.11 2021-09-25 00:43:23 -07:00
Wez Furlong
c1515404b7 fonts: improve(!) identifying italic fonts
refs: #1162
2021-09-22 11:00:06 -07:00
Wez Furlong
0ee1f7529b fonts: Fix shaping metrics
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
2021-09-22 08:34:40 -07:00
Wez Furlong
140d9fd345 fix font matching issue with .ttcs holding multiple families
refs: #1137
2021-09-12 13:31:21 -07:00
Wez Furlong
86f0bae1db fonts: tidy up fontconfig charset acceleration
and add a changelog entry!

refs: #250
2021-09-06 11:05:16 -07:00
HMH
466e5cab21 Speedup font loading with fontconfig and freetype.
- 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.
2021-09-06 10:53:01 -07:00
Wez Furlong
10b64abec8 fonts: constrain to a single thread for fallback resolution
@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.
2021-09-06 10:48:00 -07:00
Wez Furlong
3f212012f2 fix black pixel "halo"
Need to only set alpha to 1 if the pixel is not transparent

closes: #1110
2021-09-06 09:31:50 -07:00
Wez Furlong
545a8fc8a7 deps: ordered-float -> 2.8 2021-09-05 23:25:37 -07:00
Wez Furlong
18ddf38174 font: set alpha to 0xff in rasterizer
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
2021-09-04 18:54:32 -07:00
Wez Furlong
4fc8dfb374 fonts: retry fallback with no presentation if we hit last resort
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
2021-08-17 22:00:27 -07:00
Wez Furlong
6f78ee4f14 deps: update unicode-segmentation to 1.8 2021-08-11 23:06:17 -07:00
Wez Furlong
99074c6dc3 font: avoid running out of fallbacks!
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.
2021-08-11 22:50:35 -07:00
Wez Furlong
0866e5d213 fonts/shaping: respect the Presentation selection for a cluster
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
2021-08-11 09:11:59 -07:00
Wez Furlong
e3acbd594f fonts: coretext: don't specify monospace when locating fonts
The fonts in https://github.com/wez/wezterm/issues/984 aren't
considered to be monospace by coretext, so when we asked it
to resolve monospace fonts with the given name, it wouldn't
return it to us.

Remove the code that tries to restrict to monospace.

refs: https://github.com/wez/wezterm/issues/984
2021-08-04 16:25:08 -07:00
Wez Furlong
365a68dfb8 Wrap up synchronized output handling, parser changes
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
2021-07-24 17:01:21 -07:00
Wez Furlong
a2e882a7cb deps: cargo update, and a couple of dependabot suggestions 2021-07-18 19:10:46 -07:00
Wez Furlong
70ec166076 shaper: micro-optimize some of the harfbuzz stuff
Probably not super effective compared to all the Vec stuff
going on in here, but it can't hurt.
2021-07-09 19:56:31 -07:00
Wez Furlong
5b135a6e50 fix auto-complete-o 2021-07-04 09:43:34 -07:00
Wez Furlong
47fc6cac64 fixup build on linux 2021-07-04 09:30:16 -07:00
Wez Furlong
423b208780 font weight can now be specified as the underlying opentype weight
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
2021-07-04 08:55:08 -07:00
Wez Furlong
c514254138 wayland: use proportional font for title bar
allow specifying the font in the config file
2021-06-27 13:04:20 -07:00
Wez Furlong
e69869efa7 refactor deps so that window can depend on wezterm-font
I want to use this to render the font in the title bar
2021-06-26 22:58:42 -07:00
Wez Furlong
618f77f2c6 macos: improve core text font matching
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
2021-06-17 23:33:05 -07:00
Wez Furlong
7afe539b0c ls-fonts: implement for macos
this also improves the PartialOrd impl for ParsedFont so that we can
dedup results from core text correctly.

refs: https://github.com/wez/wezterm/issues/347
2021-06-17 17:58:00 -07:00
Wez Furlong
e0b62d07ca ls-fonts: add --list-system flag to list system fonts
heads up @bew!

This is implemented on windows and font-config systems;
needs to be fleshed out for macos.

refs: https://github.com/wez/wezterm/issues/347
2021-06-17 09:11:54 -07:00
Wez Furlong
c7ec47e2c0 add sextant glyphs to custom block glyphs
While I'm in here, teach the font fallback code that it doesn't
need to search for these glyphs when custom block glyphs are
enabled.

refs: https://github.com/dankamongmen/notcurses/issues/1715
refs: #584
refs: #588
2021-06-10 20:38:48 -07:00
Wez Furlong
b03e27adb1 deps: ordered-float 2.1 -> 2.5
closes: https://github.com/wez/wezterm/pull/831
2021-05-31 00:17:18 -07:00
Wez Furlong
717a2157f6 fonts: synthesize dim when a light weight font is unavailable 2021-05-30 20:52:10 -07:00
Wez Furlong
68619fcd92 fixup synthetic boldening
Improve the logic that enables it so that we don't make the wrong
things bolder than they should be.
2021-05-28 15:11:29 -07:00
Wez Furlong
030e517b43 deps: metrics 0.15 -> 0.16, cargo update 2021-05-24 07:57:03 -07:00
Wez Furlong
0519b5499a fonts: can now synthesize italics for bitmap fonts
refs: #815
2021-05-23 08:27:36 -07:00
Wez Furlong
c37ee01222 fonts: synthesize bold when missing
refs: #815
2021-05-22 16:20:35 -07:00
Wez Furlong
2bbe2bd154 fonts: synthesize italics for fonts that don't have it
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
2021-05-22 16:01:16 -07:00
Wez Furlong
a59e9b1706 update metrics 0.14 -> 0.15
closes: https://github.com/wez/wezterm/pull/778
2021-05-11 19:20:24 -07:00
Wez Furlong
0c4c129b91 fonts: use toast notification for missing glyph notification
Popping open the config error window is a bit of overkill
2021-05-01 16:45:57 -07:00
Wez Furlong
8880979586 Adjust font scaling math again
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
2021-05-01 16:45:57 -07:00
Wez Furlong
9ccdc157a7 fonts: search locator for fallbacks first
Also add an option to control whether we look in font_dirs for fallback.
Previously we would, but it could lead to some surprising fallback
choices.

The default now is to search locator then built-in.

refs: https://github.com/wez/wezterm/issues/685
refs: https://github.com/wez/wezterm/issues/727
2021-05-01 16:45:57 -07:00
Wez Furlong
f91ca30008 micro-optimize clustering
This improves it by ~4x for long lines, taking it from 120us to ~30us.
2021-04-28 08:25:07 -07:00
Wez Furlong
a2b068d59f fonts: remove some dead code 2021-04-27 22:24:43 -07:00
Wez Furlong
d6c8eb1e3b benchmarking shaping
`cargo test --release -p wezterm-gui -- --nocapture bench_shaping`:

```
running 1 test
100: 139.82µs
1000: 385.333µs
10000: 3.144203ms
test shapecache::test::bench_shaping ... ok
```
2021-04-27 21:48:15 -07:00
Wez Furlong
2520b6bd1d fontconfig: allow for undefined spacing case
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
2021-04-24 11:32:11 -07:00
Wez Furlong
91cd2e22e4 prefer local/specific config for a couple more cases
Avoid using `configuration()` when there may be a more specific
config with overrides that we can resolve.
2021-04-16 09:04:51 -07:00
Wez Furlong
67d8848676 ls-fonts: refine output a bit
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",

})
```
2021-04-14 09:06:02 -07:00
Wez Furlong
1f6bfd453b fontconfig: remove over-eager unloading
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.
2021-04-14 07:38:01 -07:00
Wez Furlong
ac6ac53655 fonts: under-specify fontconfig pattern, match ourselves
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
2021-04-14 07:34:42 -07:00
Wez Furlong
5d386818e1 fontconfig: skip postscript name lookup if already resolved font
I put this condition at the wrong nesting level :-/
2021-04-14 07:34:42 -07:00
Wez Furlong
c54b9dc873 fonts: include the width in the fontconfig debug output 2021-04-14 07:34:42 -07:00
Wez Furlong
3fae59b01b fonts: use cap-height metric to scale fallback fonts
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
2021-04-13 23:02:27 -07:00
Wez Furlong
776aedf97e fonts: allow specifying weight/stretch/italic for each fallback font 2021-04-12 22:30:55 -07:00
Wez Furlong
2e34f1a8dd Add wezterm ls-fonts subcommand
At this time it just shows you the fonts that your config matches
and where they came from:

```
; wezterm -n ls-fonts
Primary font:
  wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false)
    (<built-in>, BuiltIn)

When Italic=true:
  wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=true)
    (/home/wez/.fonts/JetBrainsMono-Italic.ttf, FontConfig)

  wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false)
    (<built-in>, BuiltIn)

When Intensity=Bold:
  wezterm.font("JetBrains Mono", weight="Bold", stretch="Normal", italic=false)
    (/home/wez/.fonts/JetBrainsMono-Bold.ttf, FontConfig)

  wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false)
    (<built-in>, BuiltIn)

When Intensity=Bold Italic=true:
  wezterm.font("JetBrains Mono", weight="Bold", stretch="Normal", italic=true)
    (/home/wez/.fonts/JetBrainsMono-Bold-Italic.ttf, FontConfig)

  wezterm.font("JetBrains Mono", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/JetBrainsMono-Regular.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Noto Color Emoji", weight="Regular", stretch="Normal", italic=false)
    (/home/wez/.fonts/NotoColorEmoji.ttf, FontConfig)

  wezterm.font("Last Resort High-Efficiency", weight="Regular", stretch="Normal", italic=false)
    (<built-in>, BuiltIn)

```

refs: #347
2021-04-12 09:44:27 -07:00
Wez Furlong
5ced58c37b Allow disabling re-sorting fallback fonts
The system locator may have a reasonable default ordering
in its list of fallbacks.

refs: #685
2021-04-12 08:03:17 -07:00
Wez Furlong
e6602dde7d fonts: refine font sorting and listing
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.
2021-04-11 16:53:12 -07:00
Wez Furlong
903c7a47b6 fonts: refine fallback some more
* 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
2021-04-11 14:43:29 -07:00
Wez Furlong
88e9ce8fa5 fonts: remove trace log when Face is dropped
It's overly verbose!
2021-04-10 21:37:00 -07:00
Wez Furlong
406d1044fa fonts: restore messaging about missing glyphs
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
2021-04-10 21:35:58 -07:00
Wez Furlong
22c4407ae9 fonts: macos: improve fallback glyph resolution performance
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
2021-04-10 21:10:22 -07:00
Wez Furlong
9b7ae8fb23 fonts: move coverage calc into ParsedFont 2021-04-10 20:39:58 -07:00
Wez Furlong
39856e4d8a fixup stream code for win32 portability 2021-04-10 11:09:20 -07:00
Wez Furlong
6c86e20b30 fonts: add custom freetype stream impl
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.
2021-04-10 10:36:22 -07:00
Wez Furlong
2e8f215d09 really fix build on win32 :-p 2021-04-10 07:46:39 -07:00
Wez Furlong
8237dfc8c6 fonts: fix compilation on win32 2021-04-10 07:32:56 -07:00
Wez Furlong
02e58d904d fonts: allow unloading unused fonts from the shaper
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.
2021-04-10 00:20:47 -07:00
Wez Furlong
3ce44823a0 fonts: FontDataSource::Memory -> BuiltIn
This makes it harder to accidentally copy the associated data.
2021-04-09 23:43:44 -07:00
Wez Furlong
f9bdd2502a fonts: adjust error diagnostics 2021-04-09 22:25:47 -07:00
Wez Furlong
18061bb47c really fixup win32 build 2021-04-09 14:16:23 -07:00
Wez Furlong
ac04076827 maybe fixup win32 build 2021-04-09 14:07:20 -07:00
Wez Furlong
b006ab923b fonts: adopt CSS Fonts Level 3 compatible font matching 2021-04-09 14:05:41 -07:00
Wez Furlong
99fc3ee3cd fonts: rename width/FontWidth to stretch/FontStretch
This terminology is consistent with that used in CSS to describe
this same property of the font.
2021-04-09 12:00:18 -07:00
Wez Furlong
0694e905e8 font-config: fall back to searching by postscript name
Our first pass is to match based on the overall constraints
supplied by the user, but if that fails, we fall back to
looking up by postscript name.
2021-04-09 10:26:46 -07:00
Wez Furlong
16e7457049 x11: notice dynamic changes to Xft.dpi
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
2021-04-09 09:23:25 -07:00
Wez Furlong
6e6d6a7f06 fonts: refine matching on macos
Potentially allow matching more ttc and variable fonts on this
platform.
2021-04-08 17:37:40 -07:00
Wez Furlong
4c1de197bd fonts: use ParsedFont rather than FontDataHandle
This can avoid extraneous parses in a few cases.
2021-04-08 17:11:23 -07:00
Wez Furlong
c4d6831cf7 fixup build on macos 2021-04-08 16:23:32 -07:00
Wez Furlong
22440a3cb2 fixup font tests 2021-04-08 16:04:59 -07:00
Wez Furlong
43ea2f192a Allow matching font weight and font width in wezterm.font
refs: https://github.com/wez/wezterm/issues/655
2021-04-08 15:42:53 -07:00
Wez Furlong
5b5751d2b9 fonts: improve font matching of variations on windows
Try harder to find a better variation match when we get
a data blob from gdi.
2021-04-08 12:42:48 -07:00
Wez Furlong
392fe098c9 fonts: place FontDataHandle in ParsedFont 2021-04-08 12:08:21 -07:00
Wez Furlong
364ab2a35b fonts: refactor: split out FontDataSource 2021-04-08 11:34:58 -07:00
Wez Furlong
63222e4a94 fonts: fixup build on unix systems 2021-04-08 10:53:00 -07:00
Wez Furlong
064b591a1b fonts: remove ttf_parser, compute coverage from freetype
Replaces the last usage of ttf-parser with calling into freetype.

This removes a source of inconsistency, as ttf-parser doesn't support
all of the things that freetype does.

Notably, this prevents a weird error from blowing up codepoint coverage
calculations on a system where I have helvetica.bdf in my font dir for
long-forgotten reasons.
2021-04-08 09:12:59 -07:00
Wez Furlong
e59e17d773 fonts: remove last use of ttf_parser::fonts_in_collection
improve some diagnostics around fonts on windows
2021-04-08 08:46:10 -07:00
Wez Furlong
024f66ba87 fonts: improve diagnostics 2021-04-08 01:12:37 -07:00
Wez Furlong
14b2537c15 fonts: restore listing of fonts in trace mode
```
WEZTERM_LOG=wezterm_font=trace,info wezterm
```

will list fonts found in font_dirs and the builtin fonts.
It can't show all fonts found via the system locator, because
that only has an interface for finding fonts by matching name,
not listing all of them.
2021-04-08 01:00:13 -07:00
Wez Furlong
88837a0f1d fonts: allow matching against the postscript name 2021-04-08 00:52:06 -07:00
Wez Furlong
99368ad567 fonts: (almost) migrate away from ttf_parser::fonts_in_collection
Use the equivalent functionality from freetype instead.

Just one call site to update on windows; will do that from a
windows machine.
2021-04-08 00:47:11 -07:00
Wez Furlong
e3fc0a583b win32: cut over to new font matcher
and remove the old one

refs: https://github.com/wez/wezterm/issues/655
2021-04-07 22:36:34 -07:00
Wez Furlong
a8281e4984 font-config: cut over to new matcher
refs: https://github.com/wez/wezterm/issues/655
2021-04-07 22:29:10 -07:00
Wez Furlong
7fb485d4ff parse font width, improve font matching
refs: https://github.com/wez/wezterm/issues/655
2021-04-07 22:07:15 -07:00
Wez Furlong
80aa86fa0c fonts: parse weight and italic into ParsedFont 2021-04-07 20:00:41 -07:00
Wez Furlong
f35d58a031 fixup win32 build
refs: https://github.com/wez/wezterm/issues/655
2021-04-07 18:17:29 -07:00
Wez Furlong
04cf0de1af fixup build on linux
refs: https://github.com/wez/wezterm/issues/655
2021-04-07 18:14:19 -07:00
Wez Furlong
e200605b8f fonts: add support for "variable" fonts
With this configuration:

```lua
local wezterm = require 'wezterm'

return {
  font_dirs = {"/Users/wez/Downloads/Inconsolata"},
  font = wezterm.font("Inconsolata"),
  font_locator = "ConfigDirsOnly"
}
```

wezterm is now able to see the 74 variations that are available
in the single inconsolata ttf.

Running `WEZTERM_LOG=wezterm_font=trace wezterm` will log the
variations.

refs: https://github.com/wez/wezterm/issues/655
2021-04-07 17:45:38 -07:00
Wez Furlong
38d6c45194 fonts: switch parsing over to freetype
This is leading up to multi-master font support
2021-04-07 16:14:58 -07:00
Wez Furlong
cf9f9c849b fixup; wasn't actually returning distinct load/render settings
refs: https://github.com/wez/wezterm/issues/639
2021-04-07 12:38:20 -07:00
Wez Furlong
b03300404a Allow specifying distinct load and render targets
refs: https://github.com/wez/wezterm/issues/639
2021-04-07 12:15:03 -07:00
Wez Furlong
d2419fb99e fonts: subpixel had blue/red flipped
refs: #639
2021-04-06 09:04:34 -07:00
Wez Furlong
a5bb5be80a fonts: fix other platforms and tests
Ungh, shouldn't push before I'm awake :-/

refs: #648
2021-04-05 09:27:01 -07:00
Wez Furlong
2c7e5196ac fonts: improve debugging for windows font loading
We didn't have as much info here as I thought; improve it!

refs: https://github.com/wez/wezterm/issues/624
2021-04-03 17:42:44 -07:00
Wez Furlong
4e25a399b2 fonts: improve trace diagnostics
refs: #607
2021-04-02 09:09:09 -07:00
Wez Furlong
cfe6894e83 fix warning on win32 2021-03-26 09:10:32 -07:00
Aaron Abramov
786888ce0a update k9 to 0.11.0 to make it work with rustc@1.51.0
1.51.0 no longer takes non string literals in `panic()`. k9@0.11.0 fixes that
2021-03-25 10:39:00 -07:00
Wez Furlong
3bec6fb5c0 lint: remove redundant semicolons
Newer versions of Rust emit warnings for these
2021-03-25 09:44:27 -07:00
Wez Furlong
be8c3be910 clear no_glyphs cache when font scale changes
refs: https://github.com/wez/wezterm/issues/508
2021-03-22 22:49:31 -07:00
Wez Furlong
8f856d0b81 font: make system fallback async wrt. rendering
If shaping can't resolve some glyphs, queue the font locator
fallback resolution to another thread; meanwhile, a last resort
glyph is used.

That thread can trigger an invalidation once the fallback resolve
is complete, the window is invalidated and the last resort glyph
is replaced by the resolve glyph.

refs: https://github.com/wez/wezterm/issues/559
refs: https://github.com/wez/wezterm/issues/508
2021-03-22 20:42:03 -07:00
Wez Furlong
e69485d3ca avoid hang if several glyphs fail to resolve in quick succession
The channel to the connui was bounded to 16 and could easily be
saturated from the main thread.  The saturated queue would block
the main thread.
2021-03-22 15:53:56 -07:00
Wez Furlong
6b92cf7539 fonts: show config error window when glyphs cannot be resolved
Keep track of the glyphs we've already advised about (until the
config is reloaded) so that we don't keep spamming the user.

refs: https://github.com/wez/wezterm/issues/559
2021-03-22 15:29:03 -07:00
Wez Furlong
f7b0ea2eb7 fonts: tune up fallback font resolution
* Check built-in fonts before asking the system for codepoint coverage
* If one of the earlier stages resolved some fonts, skip the remaining
  stages and speculatively shape what we have.  This avoids triggering
  the system font lookup for fonts that are present in the font_dirs
  or that are built-in, such as powerline symbols.

refs: https://github.com/wez/wezterm/issues/559
2021-03-22 15:03:50 -07:00
Wez Furlong
961e4ef9f7 fonts: improve FontDataHandle ordering/comparison
Don't include in-memory data in these operations
2021-03-22 14:49:00 -07:00
Wez Furlong
1b7c980646 fonts: avoid querying macos fallback list multiple times 2021-03-22 12:46:58 -07:00
Wez Furlong
af84d1ee7f fonts: prefer dwrote over gdi so that we can get OnDisk handles
The dwrote crate offers functions that can extract the underlying
font file name(s) from the system, so let's use those to get
OnDisk font handles and save some memory.

refs: https://github.com/wez/wezterm/issues/559
2021-03-21 01:44:41 -07:00
Wez Furlong
2c37d2eeb5 fonts: fixup win32 build
refs: https://github.com/wez/wezterm/issues/559
2021-03-20 23:32:19 -07:00
Wez Furlong
70c4cd1a53 fonts: use Cow instead of making a Vec copy for Memory handles
This doesn't change much, just makes things slightly tidier.

refs: https://github.com/wez/wezterm/issues/559
2021-03-20 23:15:33 -07:00
Wez Furlong
eafe01e946 fonts: avoid making an in-memory copy of OnDisk font handles
In an earlier incarnation of both wezterm and freetype, FT_New_Face
would lead file descriptors into child processes because it didn't
set O_CLOEXEC.  That led to the slightly pessimistic approach of
loading the font into memory for the lifetime of the wezterm process.

With the improved fallback handling on macos, this can result in
hundreds of MB of font data being loaded, in some cases multiple
times.

Since those days, freetype now sets O_CLOEXEC and wezterm has some
logic to close other random fds, so the descriptor leaking problem
is gone and we can now let freetype manage a file handle instead
of a memory-baked font.

This reduces the memory utilization by at least 1GB in the case
that a glyphs need to be resolved from the system fallback fonts.

refs: https://github.com/wez/wezterm/issues/559
2021-03-20 23:00:53 -07:00
Wez Furlong
72f2ff850f fonts: avoid making copies of Memory font handles
refs: https://github.com/wez/wezterm/issues/559
2021-03-20 22:49:27 -07:00
Wez Furlong
5eb6a15312 macos: reduce memory utilization in font fallback case
refs: https://github.com/wez/wezterm/issues/559
2021-03-20 22:27:08 -07:00
Wez Furlong
f4a8b14a2c tidy up the error message when no fallback is found
on macos there's no guarantee that the fallback set has glyphs
for the requested range.
2021-03-20 22:09:23 -07:00
Wez Furlong
1cf335cb45 fonts: handle bitmap-only fonts better
terminus-bold.otb reports 0 height!

Detect and force that case to go through the bitmap strike loading
code path.

Improve the size selection heuristic for bitmap strikes: previously,
we would just pick the largest bitmap and allow it to be scaled down,
which was OK for emoji fonts that just had 128px square glyphs, but
is not ok for pre-rendered pixel strikes like terminus.

Note that IncreaseFontSize works in terms of percentages only,
so using a font like this may have "gaps" when ctrl-+ or - to change
the font size.

refs: https://github.com/wez/wezterm/issues/560
2021-03-20 12:52:20 -07:00
Wez Furlong
1ee4d52a1c deps: update ttf_parser 0.9 -> 0.12 2021-03-18 22:08:07 -07:00
Wez Furlong
1441462624 fonts: add explicit fallback to Apple Symbols font
This is a bit unfortunate, but necessary, because the system fallback
list contains a handful of special fonts that apple doesn't ship on
disk in ttf/otf files.

One of those is `.AppleSymbolsFB` which would normally satisfy
the symbol lookup.

This commit hard codes the "Apple Symbols" font to use instead,
which is a disk based font.  I don't know what the difference
is between it and `.AppleSymbolsFB`, but this is sufficient
to satisfy the glyph in question from the referenced issue.

refs: https://github.com/wez/wezterm/issues/506
2021-03-17 21:56:14 -07:00
Wez Furlong
09081d2189 improve texture upload performance, part 2
Continuing along the same lines as the prior commit, the goal
of this commit is to remove the buffer transformation that was
part of uploading the texture to the GPU provided surface.

In order to do so:

* The sense of our local textures needs to change from bgra32 to rgba32.
  bgra32 was a hangover from earlier versions of our window crate that
  allowed direct-to-fb writes in software mode.  We had to pick bgra32
  for that for the broadest OS compatibility.  I believe that that
  constraint has been totally removed, although there is a chance that
  this will flip the colors on macos.
* There was an additional linear-to-srgb conversion inlined in that
  buffer transformation.  I have no idea where that is needed because
  the source data is carefully constructed as SRGB.  I don't yet know
  how to signal that, but for now I've moved that gamma correction
  into the shader when we sample the texture.

With this change, timg playback now has vtparse as the hottest
region of code.

refs: #537
2021-03-14 09:14:30 -07:00
Wez Furlong
18cb179227 x11: query Xft.dpi from the root window
We should now be using the root window specified default dpi
if the dpi is left unspecified in the wezterm configuration.

refs: #515
2021-03-08 22:19:44 -08:00
Wez Furlong
4b7f774bc5 Bundle PowerlineExtraSymbols as a fallback font 2021-03-06 19:12:35 -08:00
Wez Furlong
d56c5178da shaping: add test for FiraCode
Adds a test and seemingly a fix for https://github.com/wez/wezterm/issues/478#issuecomment-787520977

Fira Code is OFL-1.1 licensed like the other fonts we include,
however, I'm not distributing Fira Code with wezterm.
2021-02-28 13:35:00 -08:00
Wez Furlong
db08b8c1dc add window:set_config_overrides lua method
This commit expands on the prior commits to introduce the concept
of per-window configuration overrides.

Each TermWindow maintains json compatible object value holding
a map of config key -> config value overrides.

When the window notices that the config has changed, the config
file is loaded, the CLI overrides (if any) are applied, and then
finally the per-window overrides, before attempting to coerce
the resultant lua value into a Config object.

This mechanism has some important constraints:

* Only data can be assigned to the overrides.  Closures or special
  lua userdata object handles are not permitted.  This is because
  the lifetime of those objects is tied to the lua context in which
  they were parsed, which doesn't really exist in the context of
  the window.
* Only simple keys are supported for the per-window overrides.
  That means that trying to override a very specific field of
  a deeply structured value (eg: something like `font_rules[1].italic = false`
  isn't able to be expressed in this scheme.  Instead, you would
  need to assign the entire `font_rules` key.  I don't anticipate
  this being a common desire at this time; if more advance manipulations
  are required, then I have some thoughts on an event where arbitrary
  lua modifications can be applied.

The implementation details are fairly straight-forward, but in testing
the two examplary use cases I noticed that some hangovers from
supporting overrides for a couple of font related options meant that the
window-specific config wasn't being honored.  I've removed the code that
handled those overrides in favor of the newer more general CLI option
override support, and threaded the config through to the font code.

closes: #469
closes: #329
2021-02-27 14:53:19 -08:00
Wez Furlong
4e27607615 macos: fonts: fix a potential unterminated loop
for fonts located by core text, if they are singular TTF files rather
than TTC files, and the font doesn't exactly match the search critiera,
we could loop forever re-parsing the same file over and over again.

This commit restructures the logic to definitively check the number
of contained font entries and constrain the loop to that number.

In addition, it adjusts the name matching, as macos can return
names like "Cascadia Code Roman" when the underlying font is named
"Cascadia Code".

refs: https://github.com/wez/wezterm/issues/475
2021-02-25 20:47:02 -08:00
Wez Furlong
01f587d1d0 fixup tests for macos
refs: #478
2021-02-22 20:38:24 -08:00
Wez Furlong
3e44abcca8 Adopt new shaper logic in gui
Connect the gui to the new shaping logic; this means that we
can now correctly render fg/bg color when the cursor moves
through the cells that comprise a ligature.

refs: https://github.com/wez/wezterm/issues/478
2021-02-22 19:17:24 -08:00
Wez Furlong
ee17e4e174 Add shaper post-processing function
This function is intended to deal with certain kinds of ligatures
and certain combining sequences that don't have corresponding glyphs.

It isn't hooked up to the gui yet, but does have unit tests that
are probably mostly correct.

refs: https://github.com/wez/wezterm/issues/478
2021-02-22 19:17:24 -08:00
Wez Furlong
82fc53d736 rasterize: refine blending math
Refine the colorization logic to make it more of a blending operation.
Previously, we were relying on opengl to carry out blending between
layers on our behalf, but that wasn't perfect.

This commit is inspired by this post:
https://www.puredevsoftware.com/blog/2019/01/22/sub-pixel-gamma-correct-font-rendering/
and factors in the background color when computing the colorized
glyph.

This appears to reduce the dark fringes/edges that we were seeing
before, without noticeably changing the brightness of the result.

refs: #491
2021-02-20 18:00:23 -08:00
Wez Furlong
4e2b2eddba split shaders, adjust srgb opengl render settings
https://learnopengl.com/Advanced-Lighting/Gamma-Correction suggests
some good practices:

* Only enable SRGB output on the final draw call, so that all prior
  stages can operate on linear values and avoid converting to/from
  linear multiple times.
* The SRGBA textures automatically linearize when sampled, but:
  * The RGB data must be SRGB (non-linear)
  * The A channel is assumed to be linear!

This commit nudges us closer to that by:

* Converting the freetype coverage map from its linear value to
  non-linear when rasterizing.
* Splitting the shader files into one per stage (background, lines,
  glyphs) and only setting outputs_srgb for the glyph stage

refs: #491
2021-02-20 17:12:36 -08:00
Wez Furlong
dd70a8a53b introduce freetype_load_flags and freetype_load_target config
In the earlier times wezterm supported different font rasterizers,
and the configuration was a bit vague and generic to accomodate
differences in how the rasterizers worked.

Since then, we've standardized on freetype.

One of the things that's been bothering me for a while is that
we have some fiddly logic to transform from the config to the freetype
flags.

This commit does away with the transformation and simply exposes
the two sets of freetype options.

The main thing that I expect people to play with is
`freetype_load_target` which can have one of the following values:

```
pub enum FreeTypeLoadTarget {
    /// This corresponds to the default hinting algorithm, optimized
    for standard gray-level rendering.
    Normal,
    /// A lighter hinting algorithm for non-monochrome modes. Many
    generated glyphs are more fuzzy but better resemble its original
    shape. A bit like rendering on Mac OS X.  This target implies
    FT_LOAD_FORCE_AUTOHINT.
    Light,
    /// Strong hinting algorithm that should only be used for
    monochrome output. The result is probably unpleasant if the glyph
    is rendered in non-monochrome modes.
    Mono,
    /// A variant of Normal optimized for horizontally decimated LCD displays.
    HorizontalLcd,
    /// A variant of Normal optimized for vertically decimated LCD displays.
    VerticalLcd,
}
```

I expect most people will want to set this to one of `Normal`, `Light`
or `HorizontalLcd`.  `HorizontalLcd` is what `font_antialias=Subpixel`
used to select.

refs: #491
2021-02-20 14:00:38 -08:00
Wez Furlong
475260d3e3 Update bundled JetBrainsMono font to 2.225
refs: #452
2021-02-11 23:56:07 -08:00
Wez Furlong
005b492a8b deps: update to ordered-float 2.1 2021-02-07 22:54:02 -08:00
Wez Furlong
d9275e110c deps: update metrics from 0.12 -> 0.14 2021-02-03 23:50:29 -08:00
Wez Furlong
b49c7a7a72 font: fontconfig: also allow dual spacing fonts in fallback
refs: #446
2021-01-30 08:44:12 -08:00
Leiser Fernández Gallo
f6fc1c6524
Add dual font support (#446) 2021-01-30 08:43:41 -08:00
Wez Furlong
4bbe67aac3 gui: refuse to scale to sizes where cell height would be < 2 pixels
refs: https://github.com/wez/wezterm/issues/428
2021-01-16 08:45:38 -08:00
Wez Furlong
db964a91a0 gui: handle a failure to compute font metrics at very small scales
https://github.com/wez/wezterm/issues/428
2021-01-16 08:27:32 -08:00
Wez Furlong
4d8cc1bb26 font: consider "random" glyphs when computing metrics for symbol fonts
If a font doesn't have any latin glyphs then we'd compute 0 as the
average width.  Later, during rendering, we'd compute an `inf` scaling
factor and then subsequently fail to allocate texture space.

This commit takes the average width from a "random" selection of glyphs
(whatever the first few glyphs in the font may be) to avoid that
situation.

refs: https://github.com/wez/wezterm/issues/404
2020-12-28 09:02:30 -08:00
Wez Furlong
7cbbb49ab4 deps: ordered-float -> 2.0 2020-12-28 08:25:43 -08:00
Wez Furlong
979368c4eb font: add freetype_interpreter_version configuration option
This defaults to None, taking the default from the freetype library.
You can select an integer value to tell the library to use an
alternative version.

Versions that are available in the build used by wezterm are 35, 38 and
40.

See https://freetype.org/freetype2/docs/subpixel-hinting.html for
more information.
2020-12-21 09:15:13 -08:00
Wez Furlong
80214319ae adjust log levels
Revise logging so that we use info level for things that we want
to always log, and adjust the logger config to always log info
level messages.

That means shifting some warning level logs down lower to debug level so
that they aren't noisy.

closes: https://github.com/wez/wezterm/issues/388
2020-12-20 22:01:06 -08:00
Wez Furlong
c948fff0d2 font: make fewer overall passes to compute Names struct 2020-12-20 12:24:04 -08:00
Wez Furlong
eff3a13847 font: switch parser to ttf_parser
My original goal was to update to allsorts 0.5 but the API
changes are significant and not clearly described.

To make that transition easier, the prior commit moved the shaping
logic into our allsorts shaper module, leaving the name parsing
here in parser.rs.

This commit now replaces that logic with ttf_parser, which is
potentially faster (there's more emphasis on optimal code in that
crate than in allsorts) but definitely simpler.

It's not a slam-dunk transition: ttf_parser doesn't know how to
decode MacRoman encoded text, so there's a bit of logic borrowed
from allsorts here to handle that.
2020-12-19 21:55:24 -08:00
Wez Furlong
6bc1e50350 font: move some of the allsorts code into the shaper module 2020-12-19 18:21:52 -08:00
Wez Furlong
ad7362d3f7 add error handling to getting best match
refs: #383
2020-12-19 09:23:05 -08:00
Wez Furlong
dc83c6de2a fix locating Hasklig
The root cause of this was that I'd added a fontformat=TrueType
constraint to the fontconfig pattern and since fontconfig has
fontformat=CFF for Hasklig, it wasn't the primary font candidate.

When I cut out redundant fontconfig checks in
ee1d84829a it meant that we'd never
"see" the hasklig result that turns up ~20 or so fonts into the
fallback list.

This commit removes the TrueType constraint so that the results
are ranked correctly again.

I've also switched the main font lookup path to using an alternative
font config API that returns only the best match as that more closely
aligns our intent in this function; originally, fallback was intended
to be handled in this code path, but these days it has its own separate
method.

closes: https://github.com/wez/wezterm/issues/383
refs: https://github.com/wez/wezterm/issues/379
2020-12-19 09:12:41 -08:00
Wez Furlong
ee1d84829a fonts: font-config: stop after first match
font-config can return very long lists of fallback fonts like:

```
 2020-12-16T16:23:13.306Z TRACE wezterm_font::locator::font_config > query font-config for Pattern(Operator Mono SSm Lig Medium,DejaVu Sans,PT Sans,PT Sans Caption,Bitstream Vera Sans,DejaVu Sans,Verdana,Arial,Albany AMT,Luxi Sans,Nimbus Sans L,Nimbus Sans,Nimbus Sans,Helvetica,Nimbus Sans,Lucida Sans Unicode,BPG Glaho International,Tahoma,Comfortaa,Montserrat,URW Gothic,Nimbus Sans,Nimbus Sans Narrow,Carlito,Droid Sans,Nachlieli,Lucida Sans Unicode,Yudit Unicode,Kerkis,ArmNet Helvetica,Artsounk,BPG UTF8 M,Waree,Loma,Garuda,Umpush,Saysettha Unicode,JG Lao Old Arial,GF Zemen Unicode,Pigiarniq,B Davat,B Compset,Kacst\-Qr,Urdu Nastaliq Unicode,Raghindi,Mukti Narrow,malayalam,Sampige,padmaa,Hapax Berbère,MS Gothic,UmePlus P Gothic,Microsoft YaHei,Microsoft JhengHei,WenQuanYi Zen Hei,WenQuanYi Bitmap Song,AR PL ShanHeiSun Uni,AR PL New Sung,MgOpen Modata,VL Gothic,IPAMonaGothic,IPAGothic,Sazanami Gothic,Kochi Gothic,AR PL KaitiM GB,AR PL KaitiM Big5,AR PL ShanHeiSun Uni,AR PL SungtiL GB,AR PL Mingti2L Big5,MS ゴシック,ZYSong18030,TSCu_Paranar,NanumGothic,UnDotum,Baekmuk Dotum,Baekmuk Gulim,KacstQura,Lohit Bengali,Lohit Gujarati,Lohit Hindi,Lohit Marathi,Lohit Maithili,Lohit Kashmiri,Lohit Konkani,Lohit Nepali,Lohit Sindhi,Lohit Punjabi,Lohit Tamil,Meera,Lohit Malayalam,Lohit Kannada,Lohit Telugu,Lohit Oriya,LKLUG,Mingzat,Padauk,Nuosu SIL,FreeSans,FreeSans,Arial Unicode MS,Arial Unicode,Code2000,Code2001,sans\-serif,Roya,Koodak,Terafik,sans\-serif,sans\-serif,sans\-serif,ITC Avant Garde Gothic,URW Gothic,sans\-serif,sans\-serif,Helvetica,Helvetica Narrow,Nimbus Sans Narrow,sans\-serif,sans\-serif,sans\-serif:slant=0:weight=80:spacing=100:fontformat=TrueType) took 1.344155ms
 ```

In the context of that particular call, we only care about whether the
first result matches what we're looking up.  The fallbacks are processed
separately in a different method.

Therefore, we can skip additional processing and save a non-trivial
number of milliseconds overall parsing/re-parsing them to verify
whether they are the one we wanted to match.

refs: https://github.com/wez/wezterm/issues/379
2020-12-16 08:26:24 -08:00
Wez Furlong
7e49377313 font: avoid parsing fallback results from font-config
font-config can return a long list of fallback results for a given
font family, and we parse those to see if they match; once we've
found a match there's zero chance that that errort is helpful,
so break out of the loop.

Add some more trace logging to see if that helps.

refs: https://github.com/wez/wezterm/issues/379
2020-12-14 23:41:45 -08:00
Wez Furlong
c1fa08319e deps: upgrade euclid -> 0.22 2020-12-10 10:03:30 -08:00
Wez Furlong
22b4e99c82 tidy up default_dpi vs DEFAULT_DPI
This commit breaks the dependency from config -> window,
which in turn breaks the dependency from mux-server -> x11 libs
on linux.
2020-12-09 13:48:23 -08:00
Wez Furlong
2888428dda wezterm-font: add system font fallback on macOS
Teach the core text locator how to obtain the system fallback list
and add that to the fallback.

Fixup handling of ttc files on macOS; we'd always assume index 0
when extracting font info from the font descriptor.  We now make
the effort to enumerate the contents of the TTC and find a match.
2020-12-06 22:23:39 -08:00
Wez Furlong
ba9bc30b79 harfbuzz: skip some unused bits
don't bother building the coretext or uniscribe bits of harfbuzz
2020-12-05 14:19:47 -08:00
evs-ch
1a42b17727
Fixes building on aarch64 (#356)
827d94a seems to have broken building on aarch64. The fix is pretty
much adapted from bf962c8.
I know little about rust, so I might've missed some obvious issues with
this PR - it seems to work so far, though.
2020-11-26 20:41:04 -08:00
Wez Furlong
214390ba5a wezterm-font: remove some dead code 2020-11-25 22:12:40 -08:00
Wez Furlong
6ccef46989 wezterm-font: compute codepoint coverage for font-dirs
This commit adds support for computing the codepoint coverage for fonts
loaded from font-dirs and the built-in, in-memory fonts.

What this means is that if you have eg: a font with chinese glyphs in
your font-dirs but not explicitly listed in your wezterm config, if
chinese text is rendered and no match from your config is found, wezterm
will be able to find the font from your font-dirs and use that
implicitly.

Computing the codepoint coverage is relatively expensive so we defer it
until we need to perform it, and cache it.
2020-11-25 20:41:09 -08:00
Wez Furlong
d934a0ae88 wezterm-font: move FontDatabase into FontConfiguration
Previously, we'd enumerate the font dirs on every font resolve for
every bit of styled text.

This moves the new FontDatabase instances to be single instanced
in the FontConfiguration.  The font-dirs will be scanned once
on a config reload, but the built-in in-memory fonts will only
every be enumerated once per FontConfiguration instance.
2020-11-25 19:21:51 -08:00
Wez Furlong
b0bee3b036 wezterm-font: introduce FontDatabase
This tidies up the font-dir and built-in font management a little
bit and paves the way for codepoint -> font resolution for fonts
discovered in font-dirs.
2020-11-25 19:15:08 -08:00
Wez Furlong
80488ea14d improve freetype error context
Tag some font related errors with more context.
This makes it a bit easier to understand where a problem
is coming from.
2020-11-25 16:19:56 -08:00
Wez Furlong
4fd574cc7f freetype: enable FT_Error_String
By default, freetype doesn't include error strings and FT_Error_String
will always return NULL.  Turn on the compile time option that makes
this function useful!
2020-11-25 16:19:56 -08:00
Wez Furlong
ba44548d46 wezterm-font: teach gdi locator how to search for fallback fonts
This commit uses a bit of DirectWrite to discover which font(s)
can be used to render a set of codepoints.

While hooking this up, I found that the method we were using
to extract the font data didn't handle TTC data so this commit
improves some parser diagnostics and handling for that.

refs: https://github.com/wez/wezterm/issues/299
2020-11-25 16:19:56 -08:00
Wez Furlong
58eb8e3614 wezterm-font: move caching of freetype font size into Face
Profiling showed that set_font_size was a hotspot.  While there was
caching of the size info at the shaper layer, it was also needed in
the raster layer, so move it into the raster layer from the shaper
layer.

refs: #353
2020-11-25 09:20:14 -08:00
Wez Furlong
5fbb6a4400 wezterm-font: cache metrics lookup in harfbuzz shaper
98f289f511 causes more metrics retrieval
than in earlier versions; each unchached glyph render would trigger
a metrics recompute for the relevant font.

Add a simple cache for this.

refs: #353
2020-11-24 18:19:49 -08:00
Wez Furlong
827d94a9a8 wezterm-font: add find-fall-back-for-codepoints concept
This commit makes some adjustments to FontConfiguration and LoadedFont
such that it the shaper is unable to resolve a (non-last-resort) font
for a set of codepoints, the locator can be used to try to find a
font that has coverage for those codepoints.

At the moment this is a bit limited:

* Only the font-config locator implements this function
* The directory based locator isn't actually an implementor of the
  locator trait and doesn't have a way to be invoked for this.
2020-11-24 18:03:32 -08:00
Wez Furlong
3652a8360f wezterm-font: fix typo in error message 2020-11-24 12:37:11 -08:00
Wez Furlong
6e8f8298af wezterm: explain where the font came from in fallback errors
Make an effort to explain what failed to load and where it came from,
and funnel users to the documentation on font configuration.

The message presented is slightly different depending on whether
we think that the font was their primary font, an explicitly
specified font_rule or an implicitly synthesized font_rule.

refs: #340
2020-11-24 08:49:26 -08:00
Wez Furlong
98f289f511 wezterm-font: improve fallback font scaling
Use the scaling factor between the font metrics for the base font
and those of the fallback font selected for a given glyph.

The scenario is this: the base font is typically the first one selected
from the font configuration.  There may be multiple fallback fonts that
are different sizes; for instance, the Font Awesome font has glyphs that
are square in aspect and are thus about twice the width of a typical
textual monospace font.  Similarly, Noto Color Emoji is another square
font but that has a single set of bitmap strikes at a fixed 128 px
square.

The shaper returns advance metrics in the scale of the containing font,
and the rasterizer will target the supplied size and dpi.

We need to scale these to match the base metrics.

Previously we used a crude heuristic to decide whether to scale,
and that happened to work for Noto Color Emoji but not for Font Awesome,
whose metrics were just inside the bounds of the heuristic.

This commit allows retrieving the metrics for a given font_idx so
that we can compute the correct scale factor without any heuristics,
and applies that to the rasterized glyph.

refs: https://github.com/wez/wezterm/issues/342
2020-11-23 16:59:30 -08:00
Wez Furlong
65ac2269dd wezterm-font: fix exact match of full font name
Don't short circuit on just the family portion of the name;
if the criteria don't match there, we should fall back to
test against the full font name.

closes: https://github.com/wez/wezterm/issues/341
2020-11-23 15:01:19 -08:00
Wez Furlong
a063d20cf0 wezterm: improve shaping of emoji
This is one of those massive time sinks that I almost regret...
As part of recent changes to dust-off the allsorts shaper, I noticed
that the harfbuzz shaper wasn't shaping as well as the allsorts one.

This commit:

* Adds emoji-test.txt, a text file you can `cat` to see how well
  the emoji are shaped and rendered.

* Fixes (or at least, improves) the column width calculation for
  combining sequences such as "deaf man" which was previously calculated
  at 3 cells in width when it should have just been 2 cells wide, which
  resulted in a weird "prismatic" effect during rendering where the
  glyph would be rendered with an extra RHS portion of the glyph across
  3 cells.

* Improved/simplified the clustering logic used to compute fallbacks.
  Previously we could end up with some wonky/disjoint sequence of
  undefined glyphs which wouldn't be successfully resolved from a
  fallback font.  We now make a better effort to consolidate runs of
  undefined glyphs for fallback.

* For sequences such as "woman with veil: dark skin tone" that occupy a
  single cell, the shaper may return 3 clusters with 3 glyphs in the
  case that the font doesn't fully support this grapheme.  At render
  time we'd just take the last glyph from that sequence and render it,
  resulting in eg: a female symbol in this particular case.  It is
  generally a bit more useful to show the first glyph in the sequence
  (eg: person with veil) rather than the gender or skin tone, so the
  renderer now checks for this kind of overlapping sequence and renders
  only the first glyph from the sequence.
2020-11-23 13:45:38 -08:00
Wez Furlong
69d56fc868 wezterm-font: remove some dead code 2020-11-23 08:43:53 -08:00
Wez Furlong
3bd8d8c845 wezterm-font: bundle a last resort font
Bundle the *Last Resort High-Efficiency* font from
https://github.com/unicode-org/last-resort-font/
version 13.001 (Oct 22 2020).

This provides a more useful fallback glyph than we'd otherwise
produce if there is no matching glyph in any of the fonts.

Its license is OFL-1.1 which is compatible with the other
bundled fonts.
2020-11-22 16:12:20 -08:00
Wez Furlong
4500510d5c wezterm-font: improve perf of windows font locator
This avoids enumerating and parsing all fonts on startup, and improves
matching in general.
2020-11-22 12:39:29 -08:00
Wez Furlong
534cdfeaf2 wezterm-font: cargo fmt and fix comment
refs: #337
2020-11-22 11:23:58 -08:00
Wez Furlong
30cc10d4cf wezterm-font: remove font-loader dependency
This commit replaces it with the underlying core text calls
on macos.

refs: #337
2020-11-22 11:19:44 -08:00
Wez Furlong
9ca428c4e1 wezterm-font: remove font-loader dep on windows
There are a number of cases where font-loader might panic on windows,
and the optional font-loader dep causes problems with `cargo vendor`
in #337, so this is a step to removing that dep.

This commit makes direct GDI calls to enumerate monospace truetype
fonts from the system and then applies our normal matching on the
result.
2020-11-22 10:27:48 -08:00
Wez Furlong
ddc4c1b624 wezterm: fixup some allsorts shaping cases
* Fixes `keycap 0` by plucking out the prior character for an
  EnclosingMark
* Fixes lookahead for VariationSelector

refs: #66
2020-11-20 18:44:28 -08:00
Wez Furlong
a2a64e80a7 wezterm: update allsorts shaper
The current master of allsorts supports color fonts in both bitmap and
svg varieties.  I'm interested to see if I can teach wezterm to render
the svg based variety in a subsequent diff.

First though, it's times to dust off our allsorts shaper logic.

This commit updates to point to the current master of allsorts at the
time of writing; there's a little bit of API fanout that makes it a bit
easier to manage font fallback.

The fallback logic has been improved so that we can now successfully
fall back to the emoji font.

The shaping logic has been improved so that we turn on the options that
enable ZWJ for combining sequences of emoji, such as "man health
worker".

Running with the allsorts shaper enabled produces generally superior
emoji/ligature substitution results compared to harfbuzz with Noto Color
Emoji; the "man health worker" and the flags (eg: `flag: England`) from
the subdivsion-flag section don't get substituted at all with harfbuzz,
but do produce appropriate glyphs with allsorts.

refs: https://github.com/wez/wezterm/issues/66
2020-11-20 16:56:07 -08:00
Wez Furlong
720a6fd9b6 wezterm: fixup dark edges on text
9892b16d40 adjusted how the text
colors are produced; it resulted in some ugly dark edges, especially
on lighter backgrounds.

This commit routes that tint via an alpha compositing helper which
produces smoother edges.

refs: #320
2020-11-15 15:17:23 -08:00
Wez Furlong
9892b16d40 wezterm-font: tidy up some font hinting/aa options
This commit more cleanly separates the load from the render flags,
and fixes up the render call; at some point this got messed up such
that we'd never end up with freetype returning subpixel format data
(LCD) and instead we'd only ever get grayscale data.

With that fixed, it's apparent that the colorization of the glyph
data was wonky in the shader so this commit also cleans this up.

refs: #320
refs: #121
2020-11-14 17:27:31 -08:00
Wez Furlong
72492c1517 font: tidy up imports/exports a bit 2020-11-11 20:31:26 -08:00
Jeremy Fitzhardinge
bf962c8b1a Use right char type for ffi binding
On aarch64, `char` is unsigned (unlike x86-64 where it's signed), so use
`c_char` for the pointer so that it always matches the architecture.
2020-11-11 20:31:18 -08:00
Wez Furlong
ea0d8d6f11 wezterm-font: remove font-kit dep
This wasn't used by anything and the version was getting pretty stale.
Upgrading is awkward because newer versions pull in an incompatible
freetype library version.
2020-10-24 22:01:00 -07:00
Wez Furlong
7d843c6b24 wezterm: fixup win32 build for wezterm-gui changes
refs: #301
2020-10-24 17:00:07 -07:00
Wez Furlong
7e8c5a06bb split gui into wezterm-gui executable
This commit moves a bunch of stuff around such that `wezterm` is now a
lighter-weight executable that knows how to spawn the gui, talk to
the mux or emit some escape sequences for imgcat.

The gui portion has been moved into `wezterm-gui`, a separate executable
that doesn't know about the CLI or imgcat functionality.

Importantly, `wezterm.exe` is no longer a window subsystem executable
on windows, which makes interactions such as `wezterm -h` feel more
natural when spawned from `cmd`, and should allow
`type foo.png | wezterm imgcat` to work as expected.

That said, I've only tested this on linux so far, and there's a good
chance that something mac or windows specific is broken by this
change and will need fixing up.

refs: #301
2020-10-24 16:40:15 -07:00