When P2=1, empty pixels are transparent.
This patch also changes the behavior of P2=0|2, from setting empty
pixels to the default background color, to instead use the *current*
background color.
To implement this, a couple of changes are needed:
* Sixel pixels always use alpha=1.0, except for *empty* cells when
P2=1 (i.e. transparent pixels).
* The renderer draws sixels with the OVER operator, instead of the SRC
operator.
* The renderer *must* now render the cells beneath the sixel. As an
optimization, this is only done for sixels where P2=1. I.e. for
fully opaque sixels, there’s no need to render the cells beneath.
The sixel renderer isn’t yet hooked into the multi-threaded
renderer. This means *rows* (not just the cells) beneath
maybe-transparent sixels are rendered single-threaded.
Closes#391.
This ensures we don’t trim off bottom rows in unhook().
This could happen either because the application used “Set Raster
Attributes” to configure an image size larger than the sixels later
emitted.
Or, the last sixel row contains empty pixel rows.
In either case, the size set with “Set Raster Attributes” defines
the *minimum* image size; the image may still end up being larger.
DECGRI, i.e. repeat sixel character, only need to do image resizing,
and updating the current ‘column’ value *once*.
By adding sixel_add_many(), and doing the size/resize checking there,
the performance of sixel_add() is made much simpler.
This boosts performance quite noticeably when the application is
emitting many and/or long repeat sequences.
This results in the same number of instructions inside the loop, with
a ‘lea’ instead of a ‘mov’, but simplifies the post-loop logic to
update the global state.
All-empty pixels rows in the last sixel row should not be included in
the final sixel image.
This allows applications to emit sixels whose height is not a multiple
of 6, and is how XTerm works.
This is done by tracking the largest row number that contains
non-empty pixels.
In unhook, when emitting the image, the image height is adjusted based
on this value.
This is to optimize sixel_add(). It already checks ‘pos’, to see if it
needs to resize the image, and if the resize fails (either due to
allocation failures, or because we’ve reached the maximum width), we
bail out.
We need to do the same thing for height. But, we don’t want to add
another check to sixel_add() since its’s performance critical.
By setting ‘col’ outside the image boundaries when ‘row’ reaches the
maximum image height, we can “re-use” the existing code in
sixel_add().
This reverts commit 5a9d70da837c20a9641d6cbadccc962a8e5a4283.
This broke jexer.
Comparing with what XTerm does, we can see that it updates its image
height for *each* pixel in *each* sixel. I.e. empty pixels at the
bottom of a sixel will not increase the image size.
Foot currently bumps the image height 6 pixels at a time, i.e. always
a whole pixel.
Given this, always rounding up the height to the nearest multiple of
6 (say, for example, when responding to a DECGRA command), is wrong.
Now, we use the image size specified in DECGRA as is, while still
allowing the image to grow beyond that if necessary.
What’s left to do, if we want to behave *exactly* like XTerm, is stop
growing the image with 6 pixels at a time when dynamically adjusting
the image size.
By storing the current row’s byte offset into the backing image in the
terminal struct.
This replaces the ‘imul’ with a load, which can potentially be
slow. But, this data should already be in the cache.
When we allocate the backing buffer, the number of allocated rows is a
multiple of 6.
When persisting the image, make sure its height does not exceed the
current maximum height.
But appears to have been allowed in older versions of meson.
Fixes an issue where foot’s version was always reported as the last
stable release, even though it was a git build.
Shift+Tab is an odd bird in XKB; it produces a shifted variant of tab,
ISO_Left_Tab, with Shift being a consumed modifier.
From a terminal perspective, Tab and ISO_Left_Tab are the same key,
with Shift+Tab generating ‘CSI Z’, and all other combos generating a
‘CSI 27;mods;9~’ escape.
Before, when we didn’t filter out consumed modifiers, we could simply
re-use the keymap for Tab when translating ISO_Left_Tab.
This is no longer possible, since shift has been filtered out. As a
result, Shift+Tab no longer generated ‘CSI Z’, but ‘\t’. I.e as if
shift wasn’t being pressed.
This patch adds a separate keymap table for ISO_Left_Tab. It’s MOD_ANY
entry corresponds to Shift+Tab, and emits ‘CSI Z’. All its other
entries *exclude* shift (since it has been consumed), *but*, the
encoded modifier (in the escape sequences) *include* shift.
This requirement is due to the recently added maybe_repair_key_combo()
function, which is making use of xkb_keymap_key_get_mods_for_level().
See also: commit a5b554761a.