I did a bunch of testing of various ansi escape codes (including
italics) with all three char atlas implementations (none, static,
dynamic), with and without `drawBoldTextInBrightColors`, and with and
without `enableBold` to test all of the edge cases that I could.
Drawing dim colors sets the globalAlpha to 0.5, so we need to
save/restore the ctx state. Otherwise, every time we draw some dim
content, our display will get progressively dimmer.
I tested this by running `echo '\u001b[2mfoo'` a few times in zsh.
Fixes#1424
Adjacent cells on the same row sharing the same background color will be
drawn using the same `fillCells` call. This should make drawing an
application with a solid or mostly solid background color (e.g. vim)
faster.
I set vim to draw the background color for a file, and started scrolling
through it. Before, _drawBackground was taking around 6ms per frame.
After this commit, it was taking around 0.5ms per frame.
Based on prior experience, I'd expect these results to be more drastic
for larger terminal windows. The demo's window is pretty small.
I'm primarily interested in doing this because it'll allow me to
optimize the background rendering in later diffs, but this may also make
it possible to fix some minor rendering issues.
Right now, if we draw a single-width character that overflows its cell's
bounds, and the character to the right of it has a background, that
background may cover up the first character's foreground. By drawing the
background in a separate pass, we can avoid those cases.
There's still some issues with how dirty regions are computed that makes
rendering stuff like that flaky, but this at least gets us closer to
"correct" rendering.
Other terminal emulators (e.g. alacritty) render the foreground and
background in separate passes:
https://github.com/jwilm/alacritty/blob/1b7ffea/src/renderer/mod.rs#L766
It turns out that `glyph.char.charCodeAt(0)` isn't equivalent to the
character's actual code because of utf-16 garbage, so this adds
`glyph.code` to the `glyph` object so that we can use the `code` value,
and don't need to regenerate it.
- We need to make a clone of this array, because ColorManager mutates
it.
- We only want to compare the first 16 colors instead of all 256, since
only the first 16 will ever change. In DynamicCharAtlas, we can pull
the additional colors from DEFAULT_ANSI_COLORS.
I tested this out by loading the demo and changing the theme a few
times.
This limits the amount of damage a pathological program can cause in
thrashing the LRU cache.
I ran the script described here:
https://github.com/xtermjs/xterm.js/pull/1327#issuecomment-374003960
Without this patch, the entire output would get drawn in one frame that
took about 140 ms to draw. With this patch, it takes about 60 ms. It's
still nowhere as good as the static or none atlas implementations, but
it's not terrible, like it was.
This should have minimal impact on real-world applications: it'll just
take a little longer for the atlas to warm up.
The implementation is a little hacky, since it involves throwing some
code into TextRenderLayer that violates the separation of concerns, but
we can clean this up later.
Pros:
- The code is simpler.
- AA rendering is consistent between cached and uncached characters.
- No long requires parsing color values to determine the alpha, which
means that we no longer depend on #rrggbbaa color value support.
Cons:
- We're drawing without SPAA in some cases where we could be.
Addresses this comment:
https://github.com/xtermjs/xterm.js/pull/1327#discussion_r176109332