diff options
Diffstat (limited to 'alacritty/src/renderer/rects.rs')
-rw-r--r-- | alacritty/src/renderer/rects.rs | 201 |
1 files changed, 187 insertions, 14 deletions
diff --git a/alacritty/src/renderer/rects.rs b/alacritty/src/renderer/rects.rs index 77c22011..25ae93d6 100644 --- a/alacritty/src/renderer/rects.rs +++ b/alacritty/src/renderer/rects.rs @@ -62,7 +62,18 @@ impl RenderLine { end: Point<usize>, color: Rgb, ) { - let (position, thickness) = match flag { + match flag { + Flags::UNDERCURL => { + Self::push_undercurl_rects( + rects, + size, + metrics.descent, + start, + end, + metrics.underline_position + 1., + metrics.underline_thickness, + color) + } Flags::DOUBLE_UNDERLINE => { // Position underlines so each one has 50% of descent available. let top_pos = 0.25 * metrics.descent; @@ -78,22 +89,181 @@ impl RenderLine { color, )); - (bottom_pos, metrics.underline_thickness) + rects.push(Self::create_rect( + size, + metrics.descent, + start, + end, + bottom_pos, + metrics.underline_thickness, + color, + )); + }, + Flags::UNDERLINE => { + rects.push(Self::create_rect( + size, + metrics.descent, + start, + end, + metrics.underline_position + 1., + metrics.underline_thickness, + color, + )); }, - Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness), - Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness), + Flags::OVERLINE => { + let start_x = start.column.0 as f32 * size.cell_width(); + let end_x = (end.column.0 + 1) as f32 * size.cell_width(); + rects.push(RenderRect::new( + start_x + size.padding_x(), + (start.line as f32 * size.cell_height()) + (size.cell_height() / 8.), + end_x - start_x, + metrics.underline_thickness, + color, + 1., + )); + }, + Flags::STRIKEOUT => { + rects.push(Self::create_rect( + size, + metrics.descent, + start, + end, + metrics.strikeout_position, + metrics.strikeout_thickness, + color, + )); + }, + Flags::DOTTED_UNDERLINE => { + Self::push_dotted_underline_rects( + rects, + size, + metrics.descent, + start, + end, + metrics.underline_position + 1., + metrics.underline_thickness, + color) + } _ => unimplemented!("Invalid flag for cell line drawing specified"), }; + } - rects.push(Self::create_rect( - size, - metrics.descent, - start, - end, - position, - thickness, - color, - )); + fn push_undercurl_rects( + rects: &mut Vec<RenderRect>, + size: &SizeInfo, + descent: f32, + start: Point<usize>, + end: Point<usize>, + position: f32, + mut thickness: f32, + color: Rgb, + ) { + let start_x = start.column.0 as f32 * size.cell_width(); + let end_x = (end.column.0 + 1) as f32 * size.cell_width(); + + // Make sure lines are always visible. + thickness = thickness.max(1.); + + let line_bottom = (start.line as f32 + 1.) * size.cell_height(); + let baseline = line_bottom + descent; + + let mut y = (baseline - position - thickness / 2.).ceil(); + let max_y = line_bottom - thickness; + if y > max_y { + y = max_y; + } + + let period_div = 1.5 * (2. * std::f32::consts::PI) / size.cell_width(); + let amplitude_mul = size.cell_height() / 10.; + + let mut x = start_x; + let mut idx = 0; + while x < end_x { + let altr = [1., 0., -1., 0.][idx % 4]; + + let fl = (x * period_div).sin() * amplitude_mul; + let al = (fl.round() - fl).abs(); + + rects.push(RenderRect::new( + x + size.padding_x(), + y + size.padding_y() + fl, + 1., + thickness, + color, + (1. - al).powf(2.), + )); + + let fl = (x * period_div).sin() * amplitude_mul - 0.5; + let al = (fl.round() - fl).abs(); + + rects.push(RenderRect::new( + x + size.padding_x(), + y + size.padding_y() + fl, + 1., + thickness, + color, + (1. - al).powf(2.), + )); + + let fl = (x * period_div).sin() * amplitude_mul + 0.5; + let al = (fl.round() - fl).abs(); + + rects.push(RenderRect::new( + x + size.padding_x(), + y + size.padding_y() + fl, + 1., + thickness, + color, + (1. - al).powf(2.), + )); + + x += 1.; + idx += 1; + } + } + + fn push_dotted_underline_rects( + rects: &mut Vec<RenderRect>, + size: &SizeInfo, + descent: f32, + start: Point<usize>, + end: Point<usize>, + position: f32, + mut thickness: f32, + color: Rgb, + ) { + let start_x = start.column.0 as f32 * size.cell_width(); + let end_x = (end.column.0 + 1) as f32 * size.cell_width(); + + // Make sure lines are always visible. + thickness = thickness.max(1.); + + let line_bottom = (start.line as f32 + 1.) * size.cell_height(); + let baseline = line_bottom + descent; + + let mut y = (baseline - position - thickness / 2.).ceil(); + let max_y = line_bottom - thickness; + if y > max_y { + y = max_y; + } + + let mut x = start_x; + let mut idx = 0; + while x < end_x { + if idx % 4 == 0 { + let rect = RenderRect::new( + x + size.padding_x(), + y + size.padding_y(), + thickness + 1., + thickness + 1., + color, + 1., + ); + rects.push(rect); + } + x += 1.; + idx += 1; + } } /// Create a line's rect at a position relative to the baseline. @@ -161,6 +331,9 @@ impl RenderLines { self.update_flag(cell, Flags::UNDERLINE); self.update_flag(cell, Flags::DOUBLE_UNDERLINE); self.update_flag(cell, Flags::STRIKEOUT); + self.update_flag(cell, Flags::UNDERCURL); + self.update_flag(cell, Flags::OVERLINE); + self.update_flag(cell, Flags::DOTTED_UNDERLINE); } /// Update the lines for a specific flag. @@ -188,7 +361,7 @@ impl RenderLines { } // Start new line if there currently is none. - let line = RenderLine { start: cell.point, end, color: cell.fg }; + let line = RenderLine { start: cell.point, end, color: cell.sp }; match self.inner.get_mut(&flag) { Some(lines) => lines.push(line), None => { |