1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-26 16:34:23 +03:00

add terminal cell and colors

This commit is contained in:
Wez Furlong 2018-01-23 08:57:59 -08:00
parent 36a884b872
commit 641e85650d
4 changed files with 205 additions and 1 deletions

View File

@ -9,6 +9,7 @@ freetype = "0.3.0"
harfbuzz-sys = "0.1.15"
resize = "0.3.0"
servo-fontconfig = "0.4.0"
unicode-segmentation = "1.2.0"
unicode-width = "0.1.4"
vte = "0.3.2"
xcb = "0.8.1"

View File

@ -1,6 +1,7 @@
#[macro_use]
extern crate failure;
extern crate unicode_width;
extern crate unicode_segmentation;
extern crate harfbuzz_sys;
#[cfg(not(target_os = "macos"))]
extern crate fontconfig; // from servo-fontconfig
@ -22,6 +23,8 @@ mod xgfx;
mod font;
use font::{Font, FontPattern, ftwrap};
mod term;
struct TerminalWindow<'a> {
window: xgfx::Window<'a>,
conn: &'a xcb::Connection,
@ -127,12 +130,14 @@ impl<'a> TerminalWindow<'a> {
self.need_paint = false;
let message = "x_advance != foo->bar(); ❤ 😍🤢";
let cells = term::Line::from_text(message);
println!("cells {:?}", cells);
self.buffer_image.clear(xgfx::Color::rgb(0, 0, 0));
let mut x = 0 as isize;
let mut y = self.cell_height.ceil() as isize;
let glyph_info = self.font.shape(0, message)?;
let glyph_info = self.font.shape(0, &cells.as_str())?;
for info in glyph_info {
let has_color = self.font.has_color(info.font_idx)?;
let ft_glyph = self.font.load_glyph(info.font_idx, info.glyph_pos)?;

144
src/term/color.rs Normal file
View File

@ -0,0 +1,144 @@
//! Colors for attributes
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
/// These correspond to the classic ANSI color indices and are
/// used for convenience/readability here in the code
pub enum AnsiColor {
Black = 0,
Maroon,
Green,
Olive,
Navy,
Purple,
Teal,
Silver,
Grey,
Red,
Lime,
Yellow,
Blue,
Fuschia,
Aqua,
White,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct RgbColor {
pub red: u8,
pub green: u8,
pub blue: u8,
}
impl RgbColor {}
#[derive(Debug, Clone)]
pub enum ColorAttribute {
Foreground,
Background,
PaletteIndex(u8),
Rgb(RgbColor),
}
#[derive(Clone)]
pub struct ColorPalette {
colors: [RgbColor; 256],
foreground: RgbColor,
background: RgbColor,
}
impl ColorPalette {
pub fn resolve(&self, color: &ColorAttribute) -> RgbColor {
match color {
&ColorAttribute::Foreground => self.foreground,
&ColorAttribute::Background => self.background,
&ColorAttribute::PaletteIndex(idx) => self.colors[idx as usize],
&ColorAttribute::Rgb(color) => color,
}
}
}
impl Default for ColorPalette {
/// Construct a default color palette
fn default() -> ColorPalette {
let mut colors = [RgbColor::default(); 256];
// The XTerm ansi color set
static ANSI: [RgbColor; 16] = [
RgbColor{ red: 0x00, green: 0x00, blue: 0x00}, // Black
RgbColor{ red: 0x80, green: 0x00, blue: 0x00}, // Maroon
RgbColor{ red: 0x00, green: 0x80, blue: 0x00}, // Green
RgbColor{ red: 0x80, green: 0x80, blue: 0x00}, // Olive
RgbColor{ red: 0x00, green: 0x00, blue: 0x80}, // Navy
RgbColor{ red: 0x80, green: 0x00, blue: 0x80}, // Purple
RgbColor{ red: 0x00, green: 0x80, blue: 0x80}, // Teal
RgbColor{ red: 0xc0, green: 0xc0, blue: 0xc0}, // Silver
RgbColor{ red: 0x80, green: 0x80, blue: 0x80}, // Grey
RgbColor{ red: 0xff, green: 0x00, blue: 0x00}, // Red
RgbColor{ red: 0x00, green: 0xff, blue: 0x00}, // Lime
RgbColor{ red: 0xff, green: 0xff, blue: 0x00}, // Yellow
RgbColor{ red: 0x00, green: 0x00, blue: 0xff}, // Blue
RgbColor{ red: 0xff, green: 0x00, blue: 0xff}, // Fuschia
RgbColor{ red: 0x00, green: 0xff, blue: 0xff}, // Aqua
RgbColor{ red: 0xff, green: 0xff, blue: 0xff}, // White
];
colors[0..16].copy_from_slice(&ANSI);
// 216 color cube
static RAMP6: [u8; 6] = [0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF];
for idx in 0..216 {
let red = RAMP6[idx % 6];
let green = RAMP6[idx / 6 % 6];
let blue = RAMP6[idx / 6 / 6 % 6];
colors[16 + idx] = RgbColor { red, green, blue };
}
// 24 grey scales
static GREYS: [u8; 24] = [
0x08,
0x12,
0x1c,
0x26,
0x30,
0x3a,
0x44,
0x4e,
0x58,
0x62,
0x6c,
0x76,
0x80,
0x8a,
0x94,
0x9e,
0xa8,
0xb2, // Grey70
0xbc,
0xc6,
0xd0,
0xda,
0xe4,
0xee,
];
for idx in 0..24 {
let grey = GREYS[idx];
colors[232 + idx] = RgbColor {
red: grey,
green: grey,
blue: grey,
};
}
let foreground = colors[249]; // Grey70
let background = colors[AnsiColor::Black as usize];
ColorPalette {
colors,
foreground,
background,
}
}
}

54
src/term/mod.rs Normal file
View File

@ -0,0 +1,54 @@
//! Terminal model
use std;
use unicode_segmentation;
pub mod color;
#[derive(Debug, Clone)]
pub struct Cell {
chars: [u8; 8],
}
impl Cell {
#[inline]
pub fn chars(&self) -> &[u8] {
if let Some(len) = self.chars.iter().position(|&c| c == 0) {
&self.chars[0..len]
} else {
&self.chars
}
}
}
#[derive(Debug)]
pub struct Line {
cells: Vec<Cell>,
}
impl Line {
/// Recompose line into the corresponding utf8 string.
/// In the future, we'll want to decompose into clusters of Cells that share
/// the same render attributes
pub fn as_str(&self) -> String {
let mut s = String::new();
for c in self.cells.iter() {
s.push_str(std::str::from_utf8(c.chars()).unwrap_or("?"));
}
s
}
pub fn from_text(s: &str) -> Line {
let mut cells = Vec::new();
for (_, sub) in unicode_segmentation::UnicodeSegmentation::grapheme_indices(s, true) {
let mut chars = [0u8; 8];
let len = sub.len().min(8);
chars[0..len].copy_from_slice(sub.as_bytes());
cells.push(Cell { chars });
}
Line { cells }
}
}