Refactor color list management
There's now a ColorList type that provides strongly typed indexing for not only usize but NamedColor as well. Previously, the `NamedColor` was casted to a `usize` when indexing the colors. Additionally, only one copy of the ColorList needs to exist;it's borrowed from the `Config` when rendering, and the renderer doesn't need a copy.
This commit is contained in:
parent
23e36f1925
commit
ce32eee099
16
src/ansi.rs
16
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),
|
||||
|
|
216
src/config.rs
216
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
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue