1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-28 01:06:37 +03:00
Commit Graph

35 Commits

Author SHA1 Message Date
Wez Furlong
32bf0d281e fonts: improve font name decoding
freetype can't handle a wide range of encodings for
font names and can return strings like `?????` when
the family name is only present in the font as a non-unicode encoding,
such as Chinese.

This commit improves our handling of the font name table
and prefers to use results from processing that over the
results returned for eg: font family directly from the
freetype API.

refs: https://github.com/wez/wezterm/issues/1761
2022-03-25 23:27:27 -07:00
Wez Furlong
240026de48 refactor: move color parsing into wezerm-color-types crate
Resolves a little bit of the awkward duplication of color types
between some of the crates by factoring them a little bit better.

This is prep for allowing specifying alpha for some colors
in the config.
2022-02-05 13:59:54 -07:00
Wez Furlong
0324ff66f0 wezterm: add experimental_bidi config option and very basic bidi
This commit is larger than it appears to due fanout from threading
through bidi parameters.  The main changes are:

* When clustering cells, add an additional phase to resolve embedding
  levels and further sub-divide a cluster based on the resolved bidi
  runs; this is where we get the direction for a run and this needs
  to be passed through to the shaper.
* When doing bidi, the forced cluster boundary hack that we use to
  de-ligature when cursoring through text needs to be disabled,
  otherwise the cursor appears to push/rotate the text in that
  cluster when moving through it! We'll need to find a different
  way to handle shading the cursor that eliminates the original
  cursor/ligature/black issue.
* In the shaper, the logic for coalescing unresolved runs for font
  fallback assumed LTR and needed to be adjusted to cluster RTL.
  That meant also computing a little index of codepoint lengths.
* Added `experimental_bidi` boolean option that defaults to false.
  When enabled, it activates the bidi processing phase in clustering
  with a strong hint that the paragraph is LTR.

This implementation is incomplete and/or wrong for a number of cases:

* The config option should probably allow specifying the paragraph
  direction hint to use by default.
* https://terminal-wg.pages.freedesktop.org/bidi/recommendation/paragraphs.html
  recommends that bidi be applied to logical lines, not physical
  lines (or really: ranges within physical lines) that we're doing
  at the moment
* The paragraph direction hint should be overridden by cell attributes
  and other escapes; see 85a6b178cf

and probably others.

However, as of this commit, if you `experimental_bidi=true` then

```
echo This is RTL -> عربي فارسی bidi
```

(that text was sourced from:
https://github.com/microsoft/terminal/issues/538#issuecomment-677017322)

then wezterm will display the text in the same order as the text
renders in Chrome for that github comment.

```
; ./target/debug/wezterm --config experimental_bidi=false ls-fonts --text "عربي فارسی ->"
LeftToRight
 0 ع    \u{639}      x_adv=8  glyph=300  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 2 ر    \u{631}      x_adv=3.78125 glyph=273  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 4 ب    \u{628}      x_adv=4  glyph=244  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 6 ي    \u{64a}      x_adv=4  glyph=363  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 8      \u{20}       x_adv=8  glyph=2    wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
 9 ف    \u{641}      x_adv=11 glyph=328  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
11 ا    \u{627}      x_adv=4  glyph=240  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
13 ر    \u{631}      x_adv=3.78125 glyph=273  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
15 س    \u{633}      x_adv=10 glyph=278  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
17 ی    \u{6cc}      x_adv=4  glyph=664  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
19      \u{20}       x_adv=8  glyph=2    wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
20 -    \u{2d}       x_adv=8  glyph=276  wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
21 >    \u{3e}       x_adv=8  glyph=338  wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
```

```
; ./target/debug/wezterm --config experimental_bidi=true ls-fonts --text "عربي فارسی ->"
RightToLeft
17 ی    \u{6cc}      x_adv=9  glyph=906  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
15 س    \u{633}      x_adv=10 glyph=277  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
13 ر    \u{631}      x_adv=4.78125 glyph=272  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
11 ا    \u{627}      x_adv=4  glyph=241  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 9 ف    \u{641}      x_adv=5  glyph=329  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 8      \u{20}       x_adv=8  glyph=2    wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
 6 ي    \u{64a}      x_adv=9  glyph=904  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 4 ب    \u{628}      x_adv=4  glyph=243  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 2 ر    \u{631}      x_adv=5  glyph=273  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
 0 ع    \u{639}      x_adv=6  glyph=301  wezterm.font(".Geeza Pro Interface", {weight="Regular", stretch="Normal", italic=false})
                                      /System/Library/Fonts/GeezaPro.ttc index=2 variation=0, CoreText
LeftToRight
 0      \u{20}       x_adv=8  glyph=2    wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
 1 -    \u{2d}       x_adv=8  glyph=480  wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
 2 >    \u{3e}       x_adv=8  glyph=470  wezterm.font("Operator Mono SSm Lig", {weight="DemiLight", stretch="Normal", italic=false})
                                      /Users/wez/.fonts/OperatorMonoSSmLig-Medium.otf, FontDirs
;
```

refs: https://github.com/wez/wezterm/issues/784
2022-01-25 09:00:53 -07:00
Wez Furlong
79f7f63064 deps: ordered-float -> 2.10
closes: https://github.com/wez/wezterm/pull/1524
2022-01-09 19:25:48 -07:00
Wez Furlong
bf9a95ea1b remove our incomplete allsorts shaper implementation
We rely on using freetype in order to support more fonts in more
situations, and we have a deeper existing integration with harfbuzz.

I'm unlikely to come back to allsorts to complete our integration,
and in the meantime, it just adds overhead to build/test and those
builds are taking longer and longer.

I loved the idea of using pure rust for all the font stuff, but
its time is not now.

closes: #587
closes: #66
2021-11-23 05:43:13 -07:00
Wez Furlong
545a8fc8a7 deps: ordered-float -> 2.8 2021-09-05 23:25:37 -07:00
Wez Furlong
6f78ee4f14 deps: update unicode-segmentation to 1.8 2021-08-11 23:06:17 -07:00
Wez Furlong
a2e882a7cb deps: cargo update, and a couple of dependabot suggestions 2021-07-18 19:10:46 -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
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
030e517b43 deps: metrics 0.15 -> 0.16, cargo update 2021-05-24 07:57:03 -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
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
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
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
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
1ee4d52a1c deps: update ttf_parser 0.9 -> 0.12 2021-03-18 22:08:07 -07: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
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
7cbbb49ab4 deps: ordered-float -> 2.0 2020-12-28 08:25:43 -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
c1fa08319e deps: upgrade euclid -> 0.22 2020-12-10 10:03:30 -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
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
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
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
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
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