diff options
-rw-r--r-- | src/ansi.rs | 16 | ||||
-rw-r--r-- | src/config.rs | 216 | ||||
-rw-r--r-- | src/main.rs | 8 | ||||
-rw-r--r-- | src/renderer/mod.rs | 45 |
4 files changed, 196 insertions, 89 deletions
diff --git a/src/ansi.rs b/src/ansi.rs index 089bc277..8ff0a2e4 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -349,6 +349,22 @@ pub enum NamedColor { Background, } +impl NamedColor { + pub fn to_bright(&self) -> Self { + match *self { + NamedColor::Black => NamedColor::BrightBlack, + NamedColor::Red => NamedColor::BrightRed, + NamedColor::Green => NamedColor::BrightGreen, + NamedColor::Yellow => NamedColor::BrightYellow, + NamedColor::Blue => NamedColor::BrightBlue, + NamedColor::Magenta => NamedColor::BrightMagenta, + NamedColor::Cyan => NamedColor::BrightCyan, + NamedColor::White => NamedColor::BrightWhite, + val => val + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum Color { Named(NamedColor), diff --git a/src/config.rs b/src/config.rs index 60887720..5911fdb9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,11 +4,13 @@ //! parameters including font family and style, font size, etc. In the future, //! the config file will also hold user and platform specific keybindings. use std::env; +use std::fmt; use std::fs; use std::io::{self, Read}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::mpsc; +use std::ops::{Index, IndexMut}; use ::Rgb; use font::Size; @@ -19,11 +21,150 @@ use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op}; use input::{Action, Binding, MouseBinding, KeyBinding}; +use ansi; + /// Function that returns true for serde default fn true_bool() -> bool { true } +/// List of indexed colors +/// +/// The first 16 entries are the standard ansi named colors. Items 16..232 are +/// the color cube. Items 233..256 are the grayscale ramp. Finally, item 256 is +/// the configured foreground color, and item 257 is the configured background +/// color. +pub struct ColorList([Rgb; 258]); + +impl fmt::Debug for ColorList { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("ColorList[..]") + } +} + +impl Default for ColorList { + fn default() -> ColorList { + ColorList::from(Colors::default()) + } +} + +impl From<Colors> for ColorList { + fn from(colors: Colors) -> ColorList { + // Type inference fails without this annotation + let mut list: ColorList = unsafe { ::std::mem::uninitialized() }; + + list.fill_named(&colors); + list.fill_cube(); + list.fill_gray_ramp(); + + list + } +} + +impl ColorList { + fn fill_named(&mut self, colors: &Colors) { + // Normals + self[ansi::NamedColor::Black] = colors.normal.black; + self[ansi::NamedColor::Red] = colors.normal.red; + self[ansi::NamedColor::Green] = colors.normal.green; + self[ansi::NamedColor::Yellow] = colors.normal.yellow; + self[ansi::NamedColor::Blue] = colors.normal.blue; + self[ansi::NamedColor::Magenta] = colors.normal.magenta; + self[ansi::NamedColor::Cyan] = colors.normal.cyan; + self[ansi::NamedColor::White] = colors.normal.white; + + // Brights + self[ansi::NamedColor::BrightBlack] = colors.bright.black; + self[ansi::NamedColor::BrightRed] = colors.bright.red; + self[ansi::NamedColor::BrightGreen] = colors.bright.green; + self[ansi::NamedColor::BrightYellow] = colors.bright.yellow; + self[ansi::NamedColor::BrightBlue] = colors.bright.blue; + self[ansi::NamedColor::BrightMagenta] = colors.bright.magenta; + self[ansi::NamedColor::BrightCyan] = colors.bright.cyan; + self[ansi::NamedColor::BrightWhite] = colors.bright.white; + + // Foreground and background + self[ansi::NamedColor::Foreground] = colors.primary.foreground; + self[ansi::NamedColor::Background] = colors.primary.background; + } + + fn fill_cube(&mut self) { + let mut index = 16; + // Build colors + for r in 0..6 { + for g in 0..6 { + for b in 0..6 { + self[index] = Rgb { + r: if r == 0 { 0 } else { r * 40 + 55 }, + b: if b == 0 { 0 } else { b * 40 + 55 }, + g: if g == 0 { 0 } else { g * 40 + 55 }, + }; + index += 1; + } + } + } + + debug_assert!(index == 232); + } + + fn fill_gray_ramp(&mut self) { + let mut index = 232; + + for i in 0..24 { + let value = i * 10 + 8; + self[index] = Rgb { + r: value, + g: value, + b: value + }; + index += 1; + } + + debug_assert!(index == 256); + } +} + +impl Index<ansi::NamedColor> for ColorList { + type Output = Rgb; + + #[inline] + fn index(&self, idx: ansi::NamedColor) -> &Self::Output { + &self.0[idx as usize] + } +} + +impl IndexMut<ansi::NamedColor> for ColorList { + #[inline] + fn index_mut(&mut self, idx: ansi::NamedColor) -> &mut Self::Output { + &mut self.0[idx as usize] + } +} + +impl Index<usize> for ColorList { + type Output = Rgb; + + #[inline] + fn index(&self, idx: usize) -> &Self::Output { + &self.0[idx] + } +} + +impl Index<u8> for ColorList { + type Output = Rgb; + + #[inline] + fn index(&self, idx: u8) -> &Self::Output { + &self.0[idx as usize] + } +} + +impl IndexMut<usize> for ColorList { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut Self::Output { + &mut self.0[idx] + } +} + /// Top-level config type #[derive(Debug, Deserialize)] pub struct Config { @@ -43,9 +184,8 @@ pub struct Config { #[serde(default="true_bool")] draw_bold_text_with_bright_colors: bool, - /// The standard ANSI colors to use #[serde(default)] - colors: Colors, + colors: ColorList, /// Keybindings #[serde(default)] @@ -415,6 +555,15 @@ impl de::Deserialize for RawBinding { } } +impl de::Deserialize for ColorList { + fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<Self, D::Error> + where D: de::Deserializer + { + let named_colors = Colors::deserialize(deserializer)?; + Ok(ColorList::from(named_colors)) + } +} + impl de::Deserialize for MouseBinding { fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<Self, D::Error> where D: de::Deserializer @@ -665,59 +814,8 @@ impl Config { /// /// The ordering returned here is expected by the terminal. Colors are simply indexed in this /// array for performance. - pub fn color_list(&self) -> Vec<Rgb> { - let mut colors = Vec::with_capacity(258); - - // Normals - colors.push(self.colors.normal.black); - colors.push(self.colors.normal.red); - colors.push(self.colors.normal.green); - colors.push(self.colors.normal.yellow); - colors.push(self.colors.normal.blue); - colors.push(self.colors.normal.magenta); - colors.push(self.colors.normal.cyan); - colors.push(self.colors.normal.white); - - // Brights - colors.push(self.colors.bright.black); - colors.push(self.colors.bright.red); - colors.push(self.colors.bright.green); - colors.push(self.colors.bright.yellow); - colors.push(self.colors.bright.blue); - colors.push(self.colors.bright.magenta); - colors.push(self.colors.bright.cyan); - colors.push(self.colors.bright.white); - - // Build colors - for r in 0..6 { - for g in 0..6 { - for b in 0..6 { - colors.push(Rgb { - r: if r == 0 { 0 } else { r * 40 + 55 }, - b: if b == 0 { 0 } else { b * 40 + 55 }, - g: if g == 0 { 0 } else { g * 40 + 55 }, - }); - } - } - } - - // Build grays - for i in 0..24 { - let value = i * 10 + 8; - colors.push(Rgb { - r: value, - g: value, - b: value - }); - } - - debug_assert!(colors.len() == 256); - - // Foreground and background - colors.push(self.colors.primary.foreground); - colors.push(self.colors.primary.background); - - colors + pub fn color_list(&self) -> &ColorList { + &self.colors } pub fn key_bindings(&self) -> &[KeyBinding] { @@ -728,14 +826,6 @@ impl Config { &self.mouse_bindings[..] } - pub fn fg_color(&self) -> Rgb { - self.colors.primary.foreground - } - - pub fn bg_color(&self) -> Rgb { - self.colors.primary.background - } - #[inline] pub fn draw_bold_text_with_bright_colors(&self) -> bool { self.draw_bold_text_with_bright_colors diff --git a/src/main.rs b/src/main.rs index f25c2111..80389b2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -256,7 +256,7 @@ fn main() { let terminal = terminal.lock(); signal_flag.set(false); if terminal.dirty { - display.draw(terminal); + display.draw(terminal, &config); } if process_should_exit() { @@ -330,7 +330,7 @@ impl Display { /// A reference to Term whose state is being drawn must be provided. /// /// This call may block if vsync is enabled - pub fn draw(&mut self, mut terminal: MutexGuard<Term>) { + pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config) { terminal.dirty = false; // Resize events new_size and are handled outside the poll_events @@ -360,7 +360,7 @@ impl Display { let _sampler = self.meter.sampler(); let size_info = terminal.size_info().clone(); - self.renderer.with_api(&size_info, |mut api| { + self.renderer.with_api(config, &size_info, |mut api| { api.clear(); // Draw the grid @@ -372,7 +372,7 @@ impl Display { if self.render_timer { let timing = format!("{:.3} usec", self.meter.average()); let color = alacritty::ansi::Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 }); - self.renderer.with_api(terminal.size_info(), |mut api| { + self.renderer.with_api(config, terminal.size_info(), |mut api| { api.render_string(&timing[..], glyph_cache, &color); }); } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 2073be30..2728ad5f 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -28,7 +28,7 @@ use index::{Line, Column}; use ansi::{Color, NamedColor}; -use config::Config; +use config::{Config, ColorList}; use term::{self, cell, IndexedCell, Cell}; use super::Rgb; @@ -243,7 +243,6 @@ pub struct QuadRenderer { atlas: Vec<Atlas>, active_tex: GLuint, batch: Batch, - colors: Vec<Rgb>, draw_bold_text_with_bright_colors: bool, rx: mpsc::Receiver<Msg>, } @@ -254,7 +253,7 @@ pub struct RenderApi<'a> { batch: &'a mut Batch, atlas: &'a mut Vec<Atlas>, program: &'a mut ShaderProgram, - colors: &'a [Rgb], + colors: &'a ColorList, } #[derive(Debug)] @@ -273,7 +272,6 @@ pub struct PackedVertex { pub struct Batch { tex: GLuint, instances: Vec<InstanceData>, - colors: Vec<Rgb>, draw_bold_text_with_bright_colors: bool, } @@ -283,12 +281,16 @@ impl Batch { Batch { tex: 0, instances: Vec::with_capacity(BATCH_MAX), - colors: config.color_list(), draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(), } } - pub fn add_item(&mut self, cell: &IndexedCell, glyph: &Glyph) { + pub fn add_item( + &mut self, + cell: &IndexedCell, + glyph: &Glyph, + colors: &ColorList + ) { if self.is_empty() { self.tex = glyph.tex_id; } @@ -296,13 +298,10 @@ impl Batch { let fg = match cell.fg { Color::Spec(rgb) => rgb, Color::Named(ansi) => { - if self.draw_bold_text_with_bright_colors - && cell.bold() - && ansi < NamedColor::BrightBlack - { - self.colors[ansi as usize + 8] + if self.draw_bold_text_with_bright_colors && cell.bold() { + colors[ansi.to_bright()] } else { - self.colors[ansi as usize] + colors[ansi] } }, Color::Indexed(idx) => { @@ -315,14 +314,14 @@ impl Batch { idx }; - self.colors[idx as usize] + colors[idx] } }; let bg = match cell.bg { Color::Spec(rgb) => rgb, - Color::Named(ansi) => self.colors[ansi as usize], - Color::Indexed(idx) => self.colors[idx as usize], + Color::Named(ansi) => colors[ansi], + Color::Indexed(idx) => colors[idx], }; self.instances.push(InstanceData { @@ -528,7 +527,6 @@ impl QuadRenderer { atlas: Vec::new(), active_tex: 0, batch: Batch::new(config), - colors: config.color_list(), rx: msg_rx, draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(), }; @@ -540,12 +538,15 @@ impl QuadRenderer { } pub fn update_config(&mut self, config: &Config) { - self.colors = config.color_list(); - self.batch.colors = config.color_list(); self.batch.draw_bold_text_with_bright_colors = config.draw_bold_text_with_bright_colors(); } - pub fn with_api<F, T>(&mut self, props: &term::SizeInfo, func: F) -> T + pub fn with_api<F, T>( + &mut self, + config: &Config, + props: &term::SizeInfo, + func: F + ) -> T where F: FnOnce(RenderApi) -> T { while let Ok(msg) = self.rx.try_recv() { @@ -571,7 +572,7 @@ impl QuadRenderer { batch: &mut self.batch, atlas: &mut self.atlas, program: &mut self.program, - colors: &self.colors, + colors: &config.color_list(), }); unsafe { @@ -635,7 +636,7 @@ impl QuadRenderer { impl<'a> RenderApi<'a> { pub fn clear(&self) { - let color = self.colors[NamedColor::Background as usize]; + let color = self.colors[NamedColor::Background]; unsafe { gl::ClearColor( color.r as f32 / 255.0, @@ -712,7 +713,7 @@ impl<'a> RenderApi<'a> { } } - self.batch.add_item(cell, glyph); + self.batch.add_item(cell, glyph, self.colors); // Render batch and clear if it's full if self.batch.full() { |