mirror of
https://github.com/wez/wezterm.git
synced 2024-12-26 14:54:16 +03:00
CellAttributes: split color into thin/fat components
The common palette indices are in the main cell attributes. Using true color will allocate fat storage. This allows reducing the Cell size from 32 -> 24 across the implementation of storing 10 bpc color (it peaked at 40 in the last couple of commits).
This commit is contained in:
parent
47839adf95
commit
4e99edf6f5
@ -1,5 +1,5 @@
|
|||||||
//! Model a cell in the terminal display
|
//! Model a cell in the terminal display
|
||||||
use crate::color::ColorAttribute;
|
use crate::color::{ColorAttribute, PaletteIndex};
|
||||||
pub use crate::escape::osc::Hyperlink;
|
pub use crate::escape::osc::Hyperlink;
|
||||||
use crate::image::ImageCell;
|
use crate::image::ImageCell;
|
||||||
#[cfg(feature = "use_serde")]
|
#[cfg(feature = "use_serde")]
|
||||||
@ -8,6 +8,28 @@ use std::mem;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
|
enum SmallColor {
|
||||||
|
Default,
|
||||||
|
PaletteIndex(PaletteIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SmallColor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ColorAttribute> for SmallColor {
|
||||||
|
fn into(self) -> ColorAttribute {
|
||||||
|
match self {
|
||||||
|
Self::Default => ColorAttribute::Default,
|
||||||
|
Self::PaletteIndex(idx) => ColorAttribute::PaletteIndex(idx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Holds the attributes for a cell.
|
/// Holds the attributes for a cell.
|
||||||
/// Most style attributes are stored internally as part of a bitfield
|
/// Most style attributes are stored internally as part of a bitfield
|
||||||
/// to reduce per-cell overhead.
|
/// to reduce per-cell overhead.
|
||||||
@ -18,9 +40,9 @@ use unicode_width::UnicodeWidthStr;
|
|||||||
pub struct CellAttributes {
|
pub struct CellAttributes {
|
||||||
attributes: u16,
|
attributes: u16,
|
||||||
/// The foreground color
|
/// The foreground color
|
||||||
foreground: ColorAttribute,
|
foreground: SmallColor,
|
||||||
/// The background color
|
/// The background color
|
||||||
background: ColorAttribute,
|
background: SmallColor,
|
||||||
/// Relatively rarely used attributes spill over to a heap
|
/// Relatively rarely used attributes spill over to a heap
|
||||||
/// allocated struct in order to keep CellAttributes
|
/// allocated struct in order to keep CellAttributes
|
||||||
/// smaller in the common case.
|
/// smaller in the common case.
|
||||||
@ -58,6 +80,8 @@ struct FatAttributes {
|
|||||||
/// 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,
|
||||||
|
foreground: ColorAttribute,
|
||||||
|
background: ColorAttribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define getter and setter for the attributes bitfield.
|
/// Define getter and setter for the attributes bitfield.
|
||||||
@ -227,21 +251,75 @@ impl CellAttributes {
|
|||||||
|
|
||||||
/// Set the foreground color for the cell to that specified
|
/// Set the foreground color for the cell to that specified
|
||||||
pub fn set_foreground<C: Into<ColorAttribute>>(&mut self, foreground: C) -> &mut Self {
|
pub fn set_foreground<C: Into<ColorAttribute>>(&mut self, foreground: C) -> &mut Self {
|
||||||
self.foreground = foreground.into();
|
let foreground: ColorAttribute = foreground.into();
|
||||||
|
match foreground {
|
||||||
|
ColorAttribute::Default => {
|
||||||
|
self.foreground = SmallColor::Default;
|
||||||
|
if let Some(fat) = self.fat.as_mut() {
|
||||||
|
fat.foreground = ColorAttribute::Default;
|
||||||
|
}
|
||||||
|
self.deallocate_fat_attributes_if_none();
|
||||||
|
}
|
||||||
|
ColorAttribute::PaletteIndex(idx) => {
|
||||||
|
self.foreground = SmallColor::PaletteIndex(idx);
|
||||||
|
if let Some(fat) = self.fat.as_mut() {
|
||||||
|
fat.foreground = ColorAttribute::Default;
|
||||||
|
}
|
||||||
|
self.deallocate_fat_attributes_if_none();
|
||||||
|
}
|
||||||
|
foreground => {
|
||||||
|
self.foreground = SmallColor::Default;
|
||||||
|
self.allocate_fat_attributes();
|
||||||
|
self.fat.as_mut().unwrap().foreground = foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foreground(&self) -> ColorAttribute {
|
pub fn foreground(&self) -> ColorAttribute {
|
||||||
self.foreground
|
if let Some(fat) = self.fat.as_ref() {
|
||||||
|
if fat.foreground != ColorAttribute::Default {
|
||||||
|
return fat.foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.foreground.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_background<C: Into<ColorAttribute>>(&mut self, background: C) -> &mut Self {
|
pub fn set_background<C: Into<ColorAttribute>>(&mut self, background: C) -> &mut Self {
|
||||||
self.background = background.into();
|
let background: ColorAttribute = background.into();
|
||||||
|
match background {
|
||||||
|
ColorAttribute::Default => {
|
||||||
|
self.background = SmallColor::Default;
|
||||||
|
if let Some(fat) = self.fat.as_mut() {
|
||||||
|
fat.background = ColorAttribute::Default;
|
||||||
|
}
|
||||||
|
self.deallocate_fat_attributes_if_none();
|
||||||
|
}
|
||||||
|
ColorAttribute::PaletteIndex(idx) => {
|
||||||
|
self.background = SmallColor::PaletteIndex(idx);
|
||||||
|
if let Some(fat) = self.fat.as_mut() {
|
||||||
|
fat.background = ColorAttribute::Default;
|
||||||
|
}
|
||||||
|
self.deallocate_fat_attributes_if_none();
|
||||||
|
}
|
||||||
|
background => {
|
||||||
|
self.background = SmallColor::Default;
|
||||||
|
self.allocate_fat_attributes();
|
||||||
|
self.fat.as_mut().unwrap().background = background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn background(&self) -> ColorAttribute {
|
pub fn background(&self) -> ColorAttribute {
|
||||||
self.background
|
if let Some(fat) = self.fat.as_ref() {
|
||||||
|
if fat.background != ColorAttribute::Default {
|
||||||
|
return fat.background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.background.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_fat_attributes(&mut self) {
|
fn allocate_fat_attributes(&mut self) {
|
||||||
@ -250,6 +328,8 @@ impl CellAttributes {
|
|||||||
hyperlink: None,
|
hyperlink: None,
|
||||||
image: None,
|
image: None,
|
||||||
underline_color: ColorAttribute::Default,
|
underline_color: ColorAttribute::Default,
|
||||||
|
foreground: ColorAttribute::Default,
|
||||||
|
background: ColorAttribute::Default,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,6 +342,8 @@ impl CellAttributes {
|
|||||||
fat.image.is_none()
|
fat.image.is_none()
|
||||||
&& fat.hyperlink.is_none()
|
&& fat.hyperlink.is_none()
|
||||||
&& fat.underline_color == ColorAttribute::Default
|
&& fat.underline_color == ColorAttribute::Default
|
||||||
|
&& fat.foreground == ColorAttribute::Default
|
||||||
|
&& fat.background == ColorAttribute::Default
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if deallocate {
|
if deallocate {
|
||||||
@ -640,8 +722,8 @@ mod test {
|
|||||||
fn memory_usage() {
|
fn memory_usage() {
|
||||||
assert_eq!(std::mem::size_of::<crate::color::RgbColor>(), 4);
|
assert_eq!(std::mem::size_of::<crate::color::RgbColor>(), 4);
|
||||||
assert_eq!(std::mem::size_of::<ColorAttribute>(), 8);
|
assert_eq!(std::mem::size_of::<ColorAttribute>(), 8);
|
||||||
assert_eq!(std::mem::size_of::<CellAttributes>(), 32);
|
assert_eq!(std::mem::size_of::<CellAttributes>(), 16);
|
||||||
assert_eq!(std::mem::size_of::<Cell>(), 40);
|
assert_eq!(std::mem::size_of::<Cell>(), 24);
|
||||||
assert_eq!(std::mem::size_of::<Vec<u8>>(), 24);
|
assert_eq!(std::mem::size_of::<Vec<u8>>(), 24);
|
||||||
assert_eq!(std::mem::size_of::<char>(), 4);
|
assert_eq!(std::mem::size_of::<char>(), 4);
|
||||||
assert_eq!(std::mem::size_of::<TeenyString>(), 8);
|
assert_eq!(std::mem::size_of::<TeenyString>(), 8);
|
||||||
|
Loading…
Reference in New Issue
Block a user