diff --git a/alacritty_terminal/src/display.rs b/alacritty_terminal/src/display.rs index 8e09412..c8ef805 100644 --- a/alacritty_terminal/src/display.rs +++ b/alacritty_terminal/src/display.rs @@ -27,7 +27,7 @@ use crate::config::{Config, StartupMode}; use crate::index::Line; use crate::message_bar::Message; use crate::meter::Meter; -use crate::renderer::rects::{Rect, Rects}; +use crate::renderer::rects::{RenderRect, RenderLines}; use crate::renderer::{self, GlyphCache, QuadRenderer}; use crate::sync::FairMutex; use crate::term::color::Rgb; @@ -511,7 +511,7 @@ impl Display { { let glyph_cache = &mut self.glyph_cache; - let mut rects = Rects::new(); + let mut lines = RenderLines::new(); // Draw grid { @@ -521,7 +521,7 @@ impl Display { // Iterate over all non-empty cells in the grid for cell in grid_cells { // Update underline/strikeout - rects.update_lines(&cell, &size_info, &metrics); + lines.update(&cell); // Draw the cell api.render_cell(cell, glyph_cache); @@ -529,14 +529,21 @@ impl Display { }); } + let mut rects = lines.into_rects(&metrics, &size_info); + if let Some(message) = message_buffer { let text = message.text(&size_info); // Create a new rectangle for the background let start_line = size_info.lines().0 - text.len(); let y = size_info.padding_y + size_info.cell_height * start_line as f32; - let rect = Rect::new(0., y, size_info.width, size_info.height - y); - rects.push(rect, message.color()); + rects.push(RenderRect::new( + 0., + y, + size_info.width, + size_info.height - y, + message.color(), + )); // Draw rectangles including the new background self.renderer.draw_rects(config, &size_info, visual_bell_intensity, rects); diff --git a/alacritty_terminal/src/renderer/mod.rs b/alacritty_terminal/src/renderer/mod.rs index cd94247..f074c6d 100644 --- a/alacritty_terminal/src/renderer/mod.rs +++ b/alacritty_terminal/src/renderer/mod.rs @@ -31,7 +31,7 @@ use crate::cursor::{get_cursor_glyph, CursorKey}; use crate::gl; use crate::gl::types::*; use crate::index::{Column, Line}; -use crate::renderer::rects::{Rect, Rects}; +use crate::renderer::rects::RenderRect; use crate::term::color::Rgb; use crate::term::{self, cell, RenderableCell, RenderableCellContent}; @@ -679,7 +679,7 @@ impl QuadRenderer { config: &Config, props: &term::SizeInfo, visual_bell_intensity: f64, - cell_line_rects: Rects, + cell_line_rects: Vec, ) { // Swap to rectangle rendering program unsafe { @@ -710,12 +710,12 @@ impl QuadRenderer { // Draw visual bell let color = config.visual_bell.color; - let rect = Rect::new(0., 0., props.width, props.height); - self.render_rect(&rect, color, visual_bell_intensity as f32, props); + let rect = RenderRect::new(0., 0., props.width, props.height, color); + self.render_rect(&rect, visual_bell_intensity as f32, props); // Draw underlines and strikeouts - for cell_line_rect in cell_line_rects.rects() { - self.render_rect(&cell_line_rect.0, cell_line_rect.1, 255., props); + for cell_line_rect in cell_line_rects { + self.render_rect(&cell_line_rect, 255., props); } // Deactivate rectangle program again @@ -849,7 +849,7 @@ impl QuadRenderer { // Render a rectangle // // This requires the rectangle program to be activated - fn render_rect(&mut self, rect: &Rect, color: Rgb, alpha: f32, size: &term::SizeInfo) { + fn render_rect(&mut self, rect: &RenderRect, alpha: f32, size: &term::SizeInfo) { // Do nothing when alpha is fully transparent if alpha == 0. { return; @@ -876,7 +876,7 @@ impl QuadRenderer { ); // Color - self.rect_program.set_color(color, alpha); + self.rect_program.set_color(rect.color, alpha); // Draw the rectangle gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null()); diff --git a/alacritty_terminal/src/renderer/rects.rs b/alacritty_terminal/src/renderer/rects.rs index a2844c0..72139e3 100644 --- a/alacritty_terminal/src/renderer/rects.rs +++ b/alacritty_terminal/src/renderer/rects.rs @@ -21,29 +21,31 @@ use crate::term::color::Rgb; use crate::term::{RenderableCell, SizeInfo}; #[derive(Debug, Copy, Clone)] -pub struct Rect { - pub x: T, - pub y: T, - pub width: T, - pub height: T, +pub struct RenderRect { + pub x: f32, + pub y: f32, + pub width: f32, + pub height: f32, + pub color: Rgb, } -impl Rect { - pub fn new(x: T, y: T, width: T, height: T) -> Self { - Rect { x, y, width, height } +impl RenderRect { + pub fn new(x: f32, y: f32, width: f32, height: f32, color: Rgb) -> Self { + RenderRect { x, y, width, height, color } } } -struct Line { - rect: Rect, +struct RenderLine { start: Point, + end: Point, color: Rgb, } -impl Line { - /// Create a line that starts on the left of `cell` and is one cell wide - fn from_cell(cell: &RenderableCell, flag: Flags, metrics: &Metrics, size: &SizeInfo) -> Line { - let cell_x = cell.column.0 as f32 * size.cell_width; +impl RenderLine { + fn into_rect(self, flag: Flags, metrics: &Metrics, size: &SizeInfo) -> RenderRect { + let start_x = self.start.col.0 as f32 * size.cell_width; + let end_x = (self.end.col.0 + 1) as f32 * size.cell_width; + let width = end_x - start_x; let (position, mut height) = match flag { Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness), @@ -54,48 +56,42 @@ impl Line { // Make sure lines are always visible height = height.max(1.); - let cell_bottom = (cell.line.0 as f32 + 1.) * size.cell_height; - let baseline = cell_bottom + metrics.descent; + let line_bottom = (self.start.line.0 as f32 + 1.) * size.cell_height; + let baseline = line_bottom + metrics.descent; let mut y = baseline - position - height / 2.; - let max_y = cell_bottom - height; + let max_y = line_bottom - height; if y > max_y { y = max_y; } - let rect = Rect::new(cell_x + size.padding_x, y + size.padding_y, size.cell_width, height); - - Self { start: cell.into(), color: cell.fg, rect } - } - - fn update_end(&mut self, end: Point, size: &SizeInfo) { - self.rect.width = (end.col + 1 - self.start.col).0 as f32 * size.cell_width; + RenderRect::new(start_x + size.padding_x, y + size.padding_y, width, height, self.color) } } -/// Rects for underline, strikeout and more. +/// Lines for underline and strikeout. #[derive(Default)] -pub struct Rects { - inner: HashMap>, +pub struct RenderLines { + inner: HashMap>, } -impl Rects { +impl RenderLines { pub fn new() -> Self { Self::default() } - /// Convert the stored rects to rectangles for the renderer. - pub fn rects(&self) -> Vec<(Rect, Rgb)> { + pub fn into_rects(self, metrics: &Metrics, size: &SizeInfo) -> Vec { self.inner - .iter() - .map(|(_, lines)| lines) + .into_iter() + .map(|(flag, lines)| -> Vec { + lines.into_iter().map(|line| line.into_rect(flag, &metrics, &size)).collect() + }) .flatten() - .map(|line| (line.rect, line.color)) .collect() } /// Update the stored lines with the next cell info. - pub fn update_lines(&mut self, cell: &RenderableCell, size: &SizeInfo, metrics: &Metrics) { + pub fn update(&mut self, cell: &RenderableCell) { for flag in &[Flags::UNDERLINE, Flags::STRIKEOUT] { if !cell.flags.contains(*flag) { continue; @@ -103,35 +99,24 @@ impl Rects { // Check if there's an active line if let Some(line) = self.inner.get_mut(flag).and_then(|lines| lines.last_mut()) { - if cell.line == line.start.line && cell.fg == line.color { + if cell.line == line.start.line + && cell.fg == line.color + && cell.column == line.end.col + 1 + { // Update the length of the line - line.update_end(cell.into(), size); - + line.end = cell.into(); continue; } } // Start new line if there currently is none - let rect = Line::from_cell(cell, *flag, metrics, size); + let line = RenderLine { start: cell.into(), end: cell.into(), color: cell.fg }; match self.inner.get_mut(flag) { - Some(lines) => lines.push(rect), + Some(lines) => lines.push(line), None => { - self.inner.insert(*flag, vec![rect]); + self.inner.insert(*flag, vec![line]); }, } } } - - // Add a rectangle - pub fn push(&mut self, rect: Rect, color: Rgb) { - let line = Line { start: Point::default(), color, rect }; - - // Flag `HIDDEN` for hashmap index is arbitrary - match self.inner.get_mut(&Flags::HIDDEN) { - Some(lines) => lines.push(line), - None => { - self.inner.insert(Flags::HIDDEN, vec![line]); - }, - } - } }