summaryrefslogtreecommitdiff
path: root/alacritty_terminal
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal')
-rw-r--r--alacritty_terminal/src/display.rs4
-rw-r--r--alacritty_terminal/src/renderer/rects.rs175
2 files changed, 80 insertions, 99 deletions
diff --git a/alacritty_terminal/src/display.rs b/alacritty_terminal/src/display.rs
index 4a2e57c4..8e094129 100644
--- a/alacritty_terminal/src/display.rs
+++ b/alacritty_terminal/src/display.rs
@@ -511,7 +511,7 @@ impl Display {
{
let glyph_cache = &mut self.glyph_cache;
- let mut rects = Rects::new(&metrics, &size_info);
+ let mut rects = Rects::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(&size_info, &cell);
+ rects.update_lines(&cell, &size_info, &metrics);
// Draw the cell
api.render_cell(cell, glyph_cache);
diff --git a/alacritty_terminal/src/renderer/rects.rs b/alacritty_terminal/src/renderer/rects.rs
index b4f8a012..a2844c02 100644
--- a/alacritty_terminal/src/renderer/rects.rs
+++ b/alacritty_terminal/src/renderer/rects.rs
@@ -11,6 +11,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+use std::collections::HashMap;
+
use font::Metrics;
use crate::index::Point;
@@ -32,125 +34,104 @@ impl<T> Rect<T> {
}
}
-#[derive(Debug)]
struct Line {
- flag: Flags,
- range: Option<(RenderableCell, Point)>,
+ rect: Rect<f32>,
+ start: Point,
+ color: Rgb,
}
impl Line {
- fn new(flag: Flags) -> Self {
- Self { flag, range: None }
+ /// 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;
+
+ let (position, mut height) = match flag {
+ Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness),
+ Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness),
+ _ => unimplemented!("Invalid flag for cell line drawing specified"),
+ };
+
+ // 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 mut y = baseline - position - height / 2.;
+ let max_y = cell_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;
}
}
/// Rects for underline, strikeout and more.
-pub struct Rects<'a> {
- inner: Vec<(Rect<f32>, Rgb)>,
- active_lines: Vec<Line>,
- metrics: &'a Metrics,
- size: &'a SizeInfo,
+#[derive(Default)]
+pub struct Rects {
+ inner: HashMap<Flags, Vec<Line>>,
}
-impl<'a> Rects<'a> {
- pub fn new(metrics: &'a Metrics, size: &'a SizeInfo) -> Self {
- let active_lines = vec![Line::new(Flags::UNDERLINE), Line::new(Flags::STRIKEOUT)];
- Self { inner: Vec::new(), active_lines, metrics, size }
+impl Rects {
+ pub fn new() -> Self {
+ Self::default()
}
/// Convert the stored rects to rectangles for the renderer.
- pub fn rects(&self) -> &Vec<(Rect<f32>, Rgb)> {
- &self.inner
+ pub fn rects(&self) -> Vec<(Rect<f32>, Rgb)> {
+ self.inner
+ .iter()
+ .map(|(_, lines)| lines)
+ .flatten()
+ .map(|line| (line.rect, line.color))
+ .collect()
}
/// Update the stored lines with the next cell info.
- pub fn update_lines(&mut self, size_info: &SizeInfo, cell: &RenderableCell) {
- for line in self.active_lines.iter_mut() {
- match line.range {
- // Check for end if line is present
- Some((ref mut start, ref mut end)) => {
- // No change in line
- if cell.line == start.line
- && cell.flags.contains(line.flag)
- && cell.fg == start.fg
- && cell.column == end.col + 1
- {
- if size_info.cols() == cell.column && size_info.lines() == cell.line {
- // Add the last rect if we've reached the end of the terminal
- self.inner.push(create_rect(
- &start,
- cell.into(),
- line.flag,
- &self.metrics,
- &self.size,
- ));
- } else {
- // Update the length of the line
- *end = cell.into();
- }
-
- continue;
- }
-
- self.inner.push(create_rect(start, *end, line.flag, &self.metrics, &self.size));
-
- // Start a new line if the flag is present
- if cell.flags.contains(line.flag) {
- *start = cell.clone();
- *end = cell.into();
- } else {
- line.range = None;
- }
- },
- // Check for new start of line
+ pub fn update_lines(&mut self, cell: &RenderableCell, size: &SizeInfo, metrics: &Metrics) {
+ for flag in &[Flags::UNDERLINE, Flags::STRIKEOUT] {
+ if !cell.flags.contains(*flag) {
+ continue;
+ }
+
+ // 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 {
+ // Update the length of the line
+ line.update_end(cell.into(), size);
+
+ continue;
+ }
+ }
+
+ // Start new line if there currently is none
+ let rect = Line::from_cell(cell, *flag, metrics, size);
+ match self.inner.get_mut(flag) {
+ Some(lines) => lines.push(rect),
None => {
- if cell.flags.contains(line.flag) {
- line.range = Some((cell.clone(), cell.into()));
- }
+ self.inner.insert(*flag, vec![rect]);
},
- };
+ }
}
}
// Add a rectangle
pub fn push(&mut self, rect: Rect<f32>, color: Rgb) {
- self.inner.push((rect, color));
- }
-}
-
-/// Create a rectangle that starts on the left of `start` and ends on the right
-/// of `end`, based on the given flag and size metrics.
-fn create_rect(
- start: &RenderableCell,
- end: Point,
- flag: Flags,
- metrics: &Metrics,
- size: &SizeInfo,
-) -> (Rect<f32>, Rgb) {
- let start_x = start.column.0 as f32 * size.cell_width;
- let end_x = (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),
- Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness),
- _ => unimplemented!("Invalid flag for cell line drawing specified"),
- };
-
- // Make sure lines are always visible
- height = height.max(1.);
-
- let cell_bottom = (start.line.0 as f32 + 1.) * size.cell_height;
- let baseline = cell_bottom + metrics.descent;
-
- let mut y = baseline - position - height / 2.;
- let max_y = cell_bottom - height;
- if y > max_y {
- y = max_y;
+ 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]);
+ },
+ }
}
-
- let rect =
- Rect::new(start_x + size.padding_x, y.round() + size.padding_y, width, height.round());
-
- (rect, start.fg)
}