Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle different underlining styles supported by neovim #1469

Merged
merged 11 commits into from
Aug 13, 2022
14 changes: 13 additions & 1 deletion src/editor/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,17 @@ impl Window {
);
}

// Due to the limitations of the current rendering strategy, some underlines get
// clipped by the line below. To mitigate that, we redraw the adjacent lines whenever
// an individual line is redrawn. Unfortunately, some clipping still happens.
// TODO: figure out how to solve this
if row < self.grid.height - 1 {
self.redraw_line(row + 1);
}
self.redraw_line(row);
if row > 0 {
self.redraw_line(row - 1);
}
} else {
warn!("Draw command out of bounds");
}
Expand Down Expand Up @@ -297,7 +307,9 @@ impl Window {

pub fn redraw(&self) {
self.send_command(WindowDrawCommand::Clear);
for row in 0..self.grid.height {
// Draw the lines from the bottom up so that underlines don't get overwritten by the line
// below.
for row in self.grid.height..0 {
MultisampledNight marked this conversation as resolved.
Show resolved Hide resolved
self.redraw_line(row);
}
}
Expand Down
41 changes: 31 additions & 10 deletions src/renderer/grid_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,13 @@ impl GridRenderer {
let width = cell_width * self.font_dimensions.width;

let style = style.as_ref().unwrap_or(&self.default_style);
canvas.save();

// We don't want to clip text in the x position, only the y so we add a buffer of 1
// character on either side of the region so that we clip vertically but not horizontally
let (grid_x, grid_y) = grid_position;
let clip_position = (grid_x.saturating_sub(1), grid_y);
let region = self.compute_text_region(clip_position, cell_width + 2);

canvas.clip_rect(region, None, Some(false));

if let Some(underline_style) = style.underline {
let line_position = self.shaper.underline_position();
let p1 = (
Expand All @@ -160,6 +157,9 @@ impl GridRenderer {
self.draw_underline(canvas, &style, underline_style, p1.into(), p2.into())
}

canvas.save();
canvas.clip_rect(region, None, Some(false));

let y_adjustment = self.shaper.y_adjustment();

if SETTINGS.get::<RendererSettings>().debug_renderer {
Expand Down Expand Up @@ -202,10 +202,23 @@ impl GridRenderer {
p1: Point,
p2: Point,
) {
canvas.save();

let mut underline_paint = self.paint.clone();
let auto_scaling = SETTINGS.get::<RendererSettings>().underline_automatic_scaling;
// Arbitrary value under which we simply round the line thickness to 1. Anything else
// results in ugly aliasing artifacts.
let stroke_width = if self.shaper.current_size() < 15. || auto_scaling == false {
underline_paint.set_anti_alias(false);
1.0
} else {
underline_paint.set_anti_alias(true);
self.shaper.current_size() / 10.
};

underline_paint.set_color(style.special(&self.default_style.colors).to_color());
underline_paint.set_stroke_width(1.);
underline_paint
.set_color(style.special(&self.default_style.colors).to_color())
.set_stroke_width(stroke_width);

match underline_style {
UnderlineStyle::Underline => {
Expand All @@ -229,22 +242,30 @@ impl GridRenderer {
let mut path = Path::default();
path.move_to(p1);
let mut i = p1.0;
let mut sin = -2.;
let mut sin = -2. * stroke_width;
while i <= p2.0 {
sin *= -1.;
i += 4.;
path.quad_to((i - 2., p1.1 + sin), (i, p1.1));
i += 4. * stroke_width;
path.quad_to((i - 2. * stroke_width, p1.1 + sin), (i, p1.1));
}
canvas.draw_path(&path, &underline_paint);
}
UnderlineStyle::UnderDash => {
underline_paint.set_path_effect(dash_path_effect::new(&[6.0, 2.0], 0.0));
underline_paint.set_path_effect(dash_path_effect::new(
&[6.0 * stroke_width, 2.0 * stroke_width],
0.0,
));
canvas.draw_line(p1, p2, &underline_paint);
}
UnderlineStyle::UnderDot => {
underline_paint.set_path_effect(dash_path_effect::new(&[1.0, 1.0], 0.0));
underline_paint.set_path_effect(dash_path_effect::new(
&[1.0 * stroke_width, 1.0 * stroke_width],
0.0,
));
canvas.draw_line(p1, p2, &underline_paint);
}
}

canvas.restore();
}
}
2 changes: 2 additions & 0 deletions src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub struct RendererSettings {
floating_blur_amount_y: f32,
debug_renderer: bool,
profiler: bool,
underline_automatic_scaling: bool,
}

impl Default for RendererSettings {
Expand All @@ -52,6 +53,7 @@ impl Default for RendererSettings {
floating_blur_amount_y: 2.0,
debug_renderer: false,
profiler: false,
underline_automatic_scaling: false,
}
}
}
Expand Down