mirror of
https://github.com/alacritty/alacritty.git
synced 2025-04-14 17:53:03 -04:00
Add a Grid
The grid holds the state of the terminal with row-major ordering. Eventually, the grid::Cell type will hold other attributes such as color, background color, decorations, and weight. An initialization list is added for common ASCII symbols.
This commit is contained in:
parent
99474ef78a
commit
b84eb9e921
3 changed files with 159 additions and 9 deletions
95
src/grid.rs
Normal file
95
src/grid.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
//! Functions for computing properties of the terminal grid
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
/// Calculate the number of cells for an axis
|
||||
pub fn num_cells_axis(cell_width: u32, cell_sep: i32, screen_width: u32) -> u32 {
|
||||
((screen_width as i32 + cell_sep) as f64 / (cell_width as i32 - cell_sep) as f64) as u32
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Cell {
|
||||
pub character: Option<String>,
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
pub fn new(c: Option<String>) -> Cell {
|
||||
Cell {
|
||||
character: c,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the terminal display contents
|
||||
pub struct Grid {
|
||||
/// Rows in the grid. Each row holds a list of cells corresponding to the columns in that row.
|
||||
raw: Vec<Row>,
|
||||
|
||||
/// Number of columns
|
||||
_cols: usize,
|
||||
|
||||
/// Number of rows.
|
||||
///
|
||||
/// Invariant: rows is equivalent to cells.len()
|
||||
rows: usize,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
pub fn new(rows: usize, cols: usize) -> Grid {
|
||||
let mut raw = Vec::with_capacity(rows);
|
||||
for _ in 0..raw.capacity() {
|
||||
raw.push(Row::new(cols));
|
||||
}
|
||||
|
||||
Grid {
|
||||
raw: raw,
|
||||
_cols: cols,
|
||||
rows: rows,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rows(&self) -> usize {
|
||||
self.rows
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Grid {
|
||||
type Output = Row;
|
||||
|
||||
fn index<'a>(&'a self, index: usize) -> &'a Row {
|
||||
&self.raw[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Grid {
|
||||
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Row {
|
||||
&mut self.raw[index]
|
||||
}
|
||||
}
|
||||
|
||||
/// A row in the grid
|
||||
pub struct Row(Vec<Cell>);
|
||||
|
||||
impl Row {
|
||||
pub fn new(columns: usize) -> Row {
|
||||
Row(vec![Cell::new(None); columns])
|
||||
}
|
||||
|
||||
pub fn cols(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Row {
|
||||
type Output = Cell;
|
||||
|
||||
fn index<'a>(&'a self, index: usize) -> &'a Cell {
|
||||
&self.0[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Row {
|
||||
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Cell {
|
||||
&mut self.0[index]
|
||||
}
|
||||
}
|
57
src/main.rs
57
src/main.rs
|
@ -6,13 +6,21 @@ extern crate gl;
|
|||
extern crate cgmath;
|
||||
extern crate euclid;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
mod list_fonts;
|
||||
mod text;
|
||||
mod renderer;
|
||||
mod grid;
|
||||
|
||||
use renderer::{Glyph, QuadRenderer};
|
||||
use text::FontDesc;
|
||||
use grid::Grid;
|
||||
|
||||
static INIT_LIST: &'static str = "abcdefghijklmnopqrstuvwxyz\
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
01234567890\
|
||||
~`!@#$%^&*()[]{}-_=+\\|\"/?.,<>";
|
||||
|
||||
fn main() {
|
||||
let window = glutin::Window::new().unwrap();
|
||||
|
@ -29,13 +37,34 @@ fn main() {
|
|||
let (dpi_x, dpi_y) = window.get_dpi().unwrap();
|
||||
let dpr = window.hidpi_factor();
|
||||
|
||||
let font_size = 12.0;
|
||||
|
||||
let sep_x = 2;
|
||||
let sep_y = 2;
|
||||
|
||||
let desc = FontDesc::new("Ubuntu Mono", "Regular");
|
||||
let mut rasterizer = text::Rasterizer::new(dpi_x, dpi_y, dpr);
|
||||
|
||||
let glyph_r = Glyph::new(&rasterizer.get_glyph(&desc, 180., 'R'));
|
||||
let glyph_u = Glyph::new(&rasterizer.get_glyph(&desc, 180., 'u'));
|
||||
let glyph_s = Glyph::new(&rasterizer.get_glyph(&desc, 180., 's'));
|
||||
let glyph_t = Glyph::new(&rasterizer.get_glyph(&desc, 180., 't'));
|
||||
let (cell_width, cell_height) = rasterizer.box_size_for_font(&desc, font_size);
|
||||
|
||||
let num_cols = grid::num_cells_axis(cell_width, sep_x, width);
|
||||
let num_rows = grid::num_cells_axis(cell_height, sep_y, height);
|
||||
|
||||
println!("num_cols, num_rows = {}, {}", num_cols, num_rows);
|
||||
|
||||
let mut grid = Grid::new(num_rows as usize, num_cols as usize);
|
||||
|
||||
grid[0][0] = grid::Cell::new(Some(String::from("R")));
|
||||
grid[0][1] = grid::Cell::new(Some(String::from("u")));
|
||||
grid[0][2] = grid::Cell::new(Some(String::from("s")));
|
||||
grid[0][3] = grid::Cell::new(Some(String::from("t")));
|
||||
|
||||
let mut glyph_cache = HashMap::new();
|
||||
for c in INIT_LIST.chars() {
|
||||
let glyph = Glyph::new(&rasterizer.get_glyph(&desc, font_size, c));
|
||||
let string: String = c.escape_default().collect();
|
||||
glyph_cache.insert(string, glyph);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::Enable(gl::BLEND);
|
||||
|
@ -51,10 +80,22 @@ fn main() {
|
|||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
renderer.render(&glyph_r, 10.0, 10.0);
|
||||
renderer.render(&glyph_u, 130.0, 10.0);
|
||||
renderer.render(&glyph_s, 250.0, 10.0);
|
||||
renderer.render(&glyph_t, 370.0, 10.0);
|
||||
for i in 0..grid.rows() {
|
||||
let row = &grid[i];
|
||||
for j in 0..row.cols() {
|
||||
let cell = &row[j];
|
||||
if let Some(ref c) = cell.character {
|
||||
if let Some(glyph) = glyph_cache.get(&c[..]) {
|
||||
let y = (cell_height as f32 + sep_y as f32) * (i as f32);
|
||||
let x = (cell_width as f32 + sep_x as f32) * (j as f32);
|
||||
|
||||
let y_inverted = (height as f32) - y - (cell_height as f32);
|
||||
|
||||
renderer.render(glyph, x, y_inverted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.swap_buffers().unwrap();
|
||||
|
||||
|
|
16
src/text.rs
16
src/text.rs
|
@ -51,6 +51,21 @@ impl Rasterizer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn box_size_for_font(&mut self, desc: &FontDesc, size: f32) -> (u32, u32) {
|
||||
let face = self.get_face(&desc).unwrap();
|
||||
|
||||
let scale_size = self.dpr * size;
|
||||
|
||||
let em_size = face.em_size() as f32;
|
||||
let w = face.max_advance_width() as f32;
|
||||
let h = face.height() as f32;
|
||||
|
||||
let w_scale = w / em_size;
|
||||
let h_scale = h / em_size;
|
||||
|
||||
((w_scale * scale_size) as u32, (h_scale * scale_size) as u32)
|
||||
}
|
||||
|
||||
pub fn get_face(&mut self, desc: &FontDesc) -> Option<Face<'static>> {
|
||||
if let Some(face) = self.faces.get(desc) {
|
||||
return Some(face.clone());
|
||||
|
@ -71,7 +86,6 @@ impl Rasterizer {
|
|||
|
||||
pub fn get_glyph(&mut self, desc: &FontDesc, size: f32, c: char) -> RasterizedGlyph {
|
||||
let face = self.get_face(desc).expect("TODO handle get_face error");
|
||||
// TODO DPI
|
||||
face.set_char_size(to_freetype_26_6(size * self.dpr), 0, self.dpi_x, self.dpi_y).unwrap();
|
||||
face.load_char(c as usize, freetype::face::RENDER).unwrap();
|
||||
let glyph = face.glyph();
|
||||
|
|
Loading…
Add table
Reference in a new issue