diff --git a/wezterm/src/gui/glyphcache.rs b/wezterm/src/gui/glyphcache.rs index 15b4f7836..07282eef3 100644 --- a/wezterm/src/gui/glyphcache.rs +++ b/wezterm/src/gui/glyphcache.rs @@ -253,7 +253,11 @@ impl GlyphCache { Ok(Rc::new(glyph)) } - pub fn cached_image(&mut self, image_data: &Arc) -> anyhow::Result> { + pub fn cached_image( + &mut self, + image_data: &Arc, + padding: Option, + ) -> anyhow::Result> { if let Some(sprite) = self.image_cache.get(&image_data.id()) { return Ok(sprite.clone()); } @@ -266,7 +270,7 @@ impl GlyphCache { 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()); diff --git a/wezterm/src/gui/termwindow.rs b/wezterm/src/gui/termwindow.rs index bf7d00dfb..5ed6a8dd6 100644 --- a/wezterm/src/gui/termwindow.rs +++ b/wezterm/src/gui/termwindow.rs @@ -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; diff --git a/window/src/bitmaps/atlas.rs b/window/src/bitmaps/atlas.rs index 957361d89..602c58ea7 100644 --- a/window/src/bitmaps/atlas.rs +++ b/window/src/bitmaps/atlas.rs @@ -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, OutOfTextureSpace> { + self.allocate_with_padding(im, None) + } + + pub fn allocate_with_padding( + &mut self, + im: &dyn BitmapImage, + padding: Option, + ) -> Result, 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