blob: f3a782cc62865996e7477f984999096e1e8460aa [file] [log] [blame]
//! Convert a cursor into an iterator of rects.
use alacritty_terminal::ansi::CursorShape;
use alacritty_terminal::term::color::Rgb;
use alacritty_terminal::term::SizeInfo;
use crate::display::content::RenderableCursor;
use crate::renderer::rects::RenderRect;
/// Trait for conversion into the iterator.
pub trait IntoRects {
/// Consume the cursor for an iterator of rects.
fn rects(self, size_info: &SizeInfo, thickness: f32) -> CursorRects;
}
impl IntoRects for RenderableCursor {
fn rects(self, size_info: &SizeInfo, thickness: f32) -> CursorRects {
let point = self.point();
let x = point.column.0 as f32 * size_info.cell_width() + size_info.padding_x();
let y = point.line as f32 * size_info.cell_height() + size_info.padding_y();
let mut width = size_info.cell_width();
let height = size_info.cell_height();
let thickness = (thickness * width as f32).round().max(1.);
if self.is_wide() {
width *= 2.;
}
match self.shape() {
CursorShape::Beam => beam(x, y, height, thickness, self.color()),
CursorShape::Underline => underline(x, y, width, height, thickness, self.color()),
CursorShape::HollowBlock => hollow(x, y, width, height, thickness, self.color()),
_ => CursorRects::default(),
}
}
}
/// Cursor rect iterator.
#[derive(Default)]
pub struct CursorRects {
rects: [Option<RenderRect>; 4],
index: usize,
}
impl From<RenderRect> for CursorRects {
fn from(rect: RenderRect) -> Self {
Self { rects: [Some(rect), None, None, None], index: 0 }
}
}
impl Iterator for CursorRects {
type Item = RenderRect;
fn next(&mut self) -> Option<Self::Item> {
let rect = self.rects.get_mut(self.index)?;
self.index += 1;
rect.take()
}
}
/// Create an iterator yielding a single beam rect.
fn beam(x: f32, y: f32, height: f32, thickness: f32, color: Rgb) -> CursorRects {
RenderRect::new(x, y, thickness, height, color, 1.).into()
}
/// Create an iterator yielding a single underline rect.
fn underline(x: f32, y: f32, width: f32, height: f32, thickness: f32, color: Rgb) -> CursorRects {
let y = y + height - thickness;
RenderRect::new(x, y, width, thickness, color, 1.).into()
}
/// Create an iterator yielding a rect for each side of the hollow block cursor.
fn hollow(x: f32, y: f32, width: f32, height: f32, thickness: f32, color: Rgb) -> CursorRects {
let top_line = RenderRect::new(x, y, width, thickness, color, 1.);
let vertical_y = y + thickness;
let vertical_height = height - 2. * thickness;
let left_line = RenderRect::new(x, vertical_y, thickness, vertical_height, color, 1.);
let bottom_y = y + height - thickness;
let bottom_line = RenderRect::new(x, bottom_y, width, thickness, color, 1.);
let right_x = x + width - thickness;
let right_line = RenderRect::new(right_x, vertical_y, thickness, vertical_height, color, 1.);
CursorRects {
rects: [Some(top_line), Some(bottom_line), Some(left_line), Some(right_line)],
index: 0,
}
}