mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
wezterm: add excess padding for image protocols
When allocating space in the texture atlas, we typically use a small padding to avoid accidentally interpolating textures into glyphs. When it comes to rendering images via iterm2 or sixel image protocols, the image emitted by the user may not exactly fill the cell dimensions, and due to the how the shader works to apply those textures we could end up revealing nearby images in the texture when displaying an unrelated image. This commit adjusts the texture atlas allocation when making space for image protocol textures; excess padding based on an overestimate of the cell dimensions is added to the right and bottom of the image, guaranteeing that that border will be filled with transparent pixels. This is a bit wasteful of texture space, but isn't egregiously bad and is easy to reason about and makes things look less janky. refs: #292
This commit is contained in:
parent
e2bf111426
commit
52908712c6
@ -253,7 +253,11 @@ impl<T: Texture2d> GlyphCache<T> {
|
||||
Ok(Rc::new(glyph))
|
||||
}
|
||||
|
||||
pub fn cached_image(&mut self, image_data: &Arc<ImageData>) -> anyhow::Result<Sprite<T>> {
|
||||
pub fn cached_image(
|
||||
&mut self,
|
||||
image_data: &Arc<ImageData>,
|
||||
padding: Option<usize>,
|
||||
) -> anyhow::Result<Sprite<T>> {
|
||||
if let Some(sprite) = self.image_cache.get(&image_data.id()) {
|
||||
return Ok(sprite.clone());
|
||||
}
|
||||
@ -266,7 +270,7 @@ impl<T: Texture2d> GlyphCache<T> {
|
||||
decoded_image.to_vec(),
|
||||
);
|
||||
|
||||
let sprite = self.atlas.allocate(&image)?;
|
||||
let sprite = self.atlas.allocate_with_padding(&image, padding)?;
|
||||
|
||||
self.image_cache.insert(image_data.id(), sprite.clone());
|
||||
|
||||
|
@ -2501,7 +2501,7 @@ impl TermWindow {
|
||||
|
||||
quad.set_texture(white_space);
|
||||
if let Some(im) = self.window_background.as_ref() {
|
||||
let sprite = gl_state.glyph_cache.borrow_mut().cached_image(im)?;
|
||||
let sprite = gl_state.glyph_cache.borrow_mut().cached_image(im, None)?;
|
||||
quad.set_texture(sprite.texture_coords());
|
||||
quad.set_is_background_image();
|
||||
}
|
||||
@ -2832,10 +2832,22 @@ impl TermWindow {
|
||||
if let Some(image) = attrs.image() {
|
||||
// Render iTerm2 style image attributes
|
||||
|
||||
let padding = self
|
||||
.render_metrics
|
||||
.cell_size
|
||||
.height
|
||||
.max(self.render_metrics.cell_size.width)
|
||||
as usize;
|
||||
let padding = if padding.is_power_of_two() {
|
||||
padding
|
||||
} else {
|
||||
padding.next_power_of_two()
|
||||
};
|
||||
|
||||
let sprite = gl_state
|
||||
.glyph_cache
|
||||
.borrow_mut()
|
||||
.cached_image(image.image_data())?;
|
||||
.cached_image(image.image_data(), Some(padding))?;
|
||||
let width = sprite.coords.size.width;
|
||||
let height = sprite.coords.size.height;
|
||||
|
||||
|
@ -39,6 +39,12 @@ where
|
||||
"texture must be square!"
|
||||
);
|
||||
let side = texture.width();
|
||||
let iside = side as isize;
|
||||
|
||||
let image = crate::Image::new(side, side);
|
||||
let rect = Rect::new(Point::new(0, 0), Size::new(iside, iside));
|
||||
texture.write(rect, &image);
|
||||
|
||||
let allocator = AtlasAllocator::new(AtlasSize::new(side.try_into()?, side.try_into()?));
|
||||
Ok(Self {
|
||||
texture: Rc::clone(texture),
|
||||
@ -54,6 +60,14 @@ where
|
||||
|
||||
/// Reserve space for a sprite of the given size
|
||||
pub fn allocate(&mut self, im: &dyn BitmapImage) -> Result<Sprite<T>, OutOfTextureSpace> {
|
||||
self.allocate_with_padding(im, None)
|
||||
}
|
||||
|
||||
pub fn allocate_with_padding(
|
||||
&mut self,
|
||||
im: &dyn BitmapImage,
|
||||
padding: Option<usize>,
|
||||
) -> Result<Sprite<T>, OutOfTextureSpace> {
|
||||
let (width, height) = im.image_dimensions();
|
||||
|
||||
// If we can't convert the sizes to i32, then we'll never
|
||||
@ -68,8 +82,8 @@ where
|
||||
// We pad each sprite reservation with blank space to avoid
|
||||
// surprising and unexpected artifacts when the texture is
|
||||
// interpolated on to the render surface.
|
||||
let reserve_width = reserve_width + PADDING * 2;
|
||||
let reserve_height = reserve_height + PADDING * 2;
|
||||
let reserve_width = reserve_width + padding.unwrap_or(0) as i32 + PADDING * 2;
|
||||
let reserve_height = reserve_height + padding.unwrap_or(0) as i32 + PADDING * 2;
|
||||
|
||||
if let Some(allocation) = self
|
||||
.allocator
|
||||
|
Loading…
Reference in New Issue
Block a user