1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 13:52:55 +03:00

conceptually allow for multiple image attachments in a cell

refs: #986
This commit is contained in:
Wez Furlong 2021-07-29 19:41:52 -07:00
parent 96f15a065c
commit 71e88a4fea
5 changed files with 99 additions and 50 deletions

View File

@ -2020,11 +2020,11 @@ impl TerminalState {
.get_cell(cursor_x + x, cursor_y) .get_cell(cursor_x + x, cursor_y)
.cloned() .cloned()
.unwrap_or_else(|| Cell::new(' ', CellAttributes::default())); .unwrap_or_else(|| Cell::new(' ', CellAttributes::default()));
cell.attrs_mut().set_image(Some(Box::new(ImageCell::new( cell.attrs_mut().set_image(Box::new(ImageCell::new(
TextureCoordinate::new(xpos, ypos), TextureCoordinate::new(xpos, ypos),
TextureCoordinate::new(xpos + x_delta, ypos + y_delta), TextureCoordinate::new(xpos + x_delta, ypos + y_delta),
image_data.clone(), image_data.clone(),
)))); )));
self.screen_mut().set_cell(cursor_x + x, cursor_y, &cell); self.screen_mut().set_cell(cursor_x + x, cursor_y, &cell);
xpos += x_delta; xpos += x_delta;

View File

@ -76,7 +76,7 @@ struct FatAttributes {
/// The hyperlink content, if any /// The hyperlink content, if any
hyperlink: Option<Arc<Hyperlink>>, hyperlink: Option<Arc<Hyperlink>>,
/// The image data, if any /// The image data, if any
image: Option<Box<ImageCell>>, image: Vec<Box<ImageCell>>,
/// The color of the underline. If None, then /// The color of the underline. If None, then
/// the foreground color is to be used /// the foreground color is to be used
underline_color: ColorAttribute, underline_color: ColorAttribute,
@ -326,7 +326,7 @@ impl CellAttributes {
if self.fat.is_none() { if self.fat.is_none() {
self.fat.replace(Box::new(FatAttributes { self.fat.replace(Box::new(FatAttributes {
hyperlink: None, hyperlink: None,
image: None, image: vec![],
underline_color: ColorAttribute::Default, underline_color: ColorAttribute::Default,
foreground: ColorAttribute::Default, foreground: ColorAttribute::Default,
background: ColorAttribute::Default, background: ColorAttribute::Default,
@ -339,7 +339,7 @@ impl CellAttributes {
.fat .fat
.as_ref() .as_ref()
.map(|fat| { .map(|fat| {
fat.image.is_none() fat.image.is_empty()
&& fat.hyperlink.is_none() && fat.hyperlink.is_none()
&& fat.underline_color == ColorAttribute::Default && fat.underline_color == ColorAttribute::Default
&& fat.foreground == ColorAttribute::Default && fat.foreground == ColorAttribute::Default
@ -362,15 +362,35 @@ impl CellAttributes {
} }
} }
pub fn set_image(&mut self, image: Option<Box<ImageCell>>) -> &mut Self { /// Assign a single image to a cell.
if image.is_none() && self.fat.is_none() { pub fn set_image(&mut self, image: Box<ImageCell>) -> &mut Self {
self self.allocate_fat_attributes();
} else { self.fat.as_mut().unwrap().image = vec![image];
self.allocate_fat_attributes(); self
self.fat.as_mut().unwrap().image = image; }
self.deallocate_fat_attributes_if_none();
self /// Clear all images from a cell
pub fn clear_images(&mut self) -> &mut Self {
if let Some(fat) = self.fat.as_mut() {
fat.image.clear();
} }
self.deallocate_fat_attributes_if_none();
self
}
/// Add an image attachement, preserving any existing attachments.
/// The list of images is maintained in z-index order
pub fn attach_image(&mut self, image: Box<ImageCell>) -> &mut Self {
self.allocate_fat_attributes();
let fat = self.fat.as_mut().unwrap();
let z_index = image.z_index();
match fat
.image
.binary_search_by(|probe| probe.z_index().cmp(&z_index))
{
Ok(idx) | Err(idx) => fat.image.insert(idx, image),
}
self
} }
pub fn set_underline_color<C: Into<ColorAttribute>>( pub fn set_underline_color<C: Into<ColorAttribute>>(
@ -420,10 +440,15 @@ impl CellAttributes {
self.fat.as_ref().and_then(|fat| fat.hyperlink.as_ref()) self.fat.as_ref().and_then(|fat| fat.hyperlink.as_ref())
} }
pub fn image(&self) -> Option<&ImageCell> { /// Returns the list of attached images in z-index order.
self.fat /// Returns None if there are no attached images; will
.as_ref() /// never return Some(vec![]).
.and_then(|fat| fat.image.as_ref().map(|im| im.as_ref())) pub fn images(&self) -> Option<Vec<ImageCell>> {
let fat = self.fat.as_ref()?;
if fat.image.is_empty() {
return None;
}
Some(fat.image.iter().map(|im| im.as_ref().clone()).collect())
} }
pub fn underline_color(&self) -> ColorAttribute { pub fn underline_color(&self) -> ColorAttribute {

View File

@ -83,6 +83,7 @@ pub struct ImageCell {
bottom_right: TextureCoordinate, bottom_right: TextureCoordinate,
/// References the underlying image data /// References the underlying image data
data: Arc<ImageData>, data: Arc<ImageData>,
z_index: i32,
} }
impl ImageCell { impl ImageCell {
@ -90,11 +91,21 @@ impl ImageCell {
top_left: TextureCoordinate, top_left: TextureCoordinate,
bottom_right: TextureCoordinate, bottom_right: TextureCoordinate,
data: Arc<ImageData>, data: Arc<ImageData>,
) -> Self {
Self::with_z_index(top_left, bottom_right, data, 0)
}
pub fn with_z_index(
top_left: TextureCoordinate,
bottom_right: TextureCoordinate,
data: Arc<ImageData>,
z_index: i32,
) -> Self { ) -> Self {
Self { Self {
top_left, top_left,
bottom_right, bottom_right,
data, data,
z_index,
} }
} }
@ -109,6 +120,14 @@ impl ImageCell {
pub fn image_data(&self) -> &Arc<ImageData> { pub fn image_data(&self) -> &Arc<ImageData> {
&self.data &self.data
} }
/// negative z_index is rendered beneath the text layer.
/// >= 0 is rendered above the text.
/// negative z_index < INT32_MIN/2 will be drawn under cells
/// with non-default background colors
pub fn z_index(&self) -> i32 {
self.z_index
}
} }
static IMAGE_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0); static IMAGE_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);

View File

@ -326,7 +326,7 @@ impl Surface {
' ', ' ',
self.attributes self.attributes
.clone() .clone()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new( TextureCoordinate::new(
image.top_left.x + xpos, image.top_left.x + xpos,
image.top_left.y + ypos, image.top_left.y + ypos,
@ -336,7 +336,7 @@ impl Surface {
image.top_left.y + ypos + ysize, image.top_left.y + ypos + ysize,
), ),
image.image.clone(), image.image.clone(),
)))) )))
.clone(), .clone(),
), ),
); );
@ -1596,41 +1596,41 @@ mod test {
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.0, 0.0), TextureCoordinate::new_f32(0.0, 0.0),
TextureCoordinate::new_f32(0.25, 0.5), TextureCoordinate::new_f32(0.25, 0.5),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.25, 0.0), TextureCoordinate::new_f32(0.25, 0.0),
TextureCoordinate::new_f32(0.5, 0.5), TextureCoordinate::new_f32(0.5, 0.5),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.5, 0.0), TextureCoordinate::new_f32(0.5, 0.0),
TextureCoordinate::new_f32(0.75, 0.5), TextureCoordinate::new_f32(0.75, 0.5),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.75, 0.0), TextureCoordinate::new_f32(0.75, 0.0),
TextureCoordinate::new_f32(1.0, 0.5), TextureCoordinate::new_f32(1.0, 0.5),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
], ],
@ -1638,41 +1638,41 @@ mod test {
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.0, 0.5), TextureCoordinate::new_f32(0.0, 0.5),
TextureCoordinate::new_f32(0.25, 1.0), TextureCoordinate::new_f32(0.25, 1.0),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.25, 0.5), TextureCoordinate::new_f32(0.25, 0.5),
TextureCoordinate::new_f32(0.5, 1.0), TextureCoordinate::new_f32(0.5, 1.0),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.5, 0.5), TextureCoordinate::new_f32(0.5, 0.5),
TextureCoordinate::new_f32(0.75, 1.0), TextureCoordinate::new_f32(0.75, 1.0),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
Cell::new( Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.75, 0.5), TextureCoordinate::new_f32(0.75, 0.5),
TextureCoordinate::new_f32(1.0, 1.0), TextureCoordinate::new_f32(1.0, 1.0),
data.clone() data.clone()
)))) )))
.clone() .clone()
), ),
], ],
@ -1694,11 +1694,11 @@ mod test {
[[Cell::new( [[Cell::new(
' ', ' ',
CellAttributes::default() CellAttributes::default()
.set_image(Some(Box::new(ImageCell::new( .set_image(Box::new(ImageCell::new(
TextureCoordinate::new_f32(0.25, 0.3), TextureCoordinate::new_f32(0.25, 0.3),
TextureCoordinate::new_f32(0.75, 0.8), TextureCoordinate::new_f32(0.75, 0.8),
data.clone() data.clone()
)))) )))
.clone() .clone()
),]] ),]]
); );

View File

@ -871,19 +871,24 @@ impl super::TermWindow {
cursor_bg: params.cursor_bg, cursor_bg: params.cursor_bg,
}); });
if let Some(image) = cluster.attrs.image() { if let Some(images) = cluster.attrs.images() {
self.populate_image_quad( // FIXME: This is where we need to allocate distinct quads for each of
image, // these images
gl_state,
quads, for image in images {
cell_idx, self.populate_image_quad(
&params, &image,
hsv, gl_state,
cursor_shape, quads,
glyph_color, cell_idx,
style_params.underline_color, &params,
bg_color, hsv,
)?; cursor_shape,
glyph_color,
style_params.underline_color,
bg_color,
)?;
}
} }
if self.config.custom_block_glyphs && glyph_idx == 0 { if self.config.custom_block_glyphs && glyph_idx == 0 {