aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZnarf <90558133+FrancisTheCat@users.noreply.github.com>2025-07-31 18:03:31 +0200
committerGitHub <noreply@github.com>2025-07-31 16:03:31 +0000
commitf07622e9082af24dee1501889e13b298c57a1c4d (patch)
treebdf240fb41c11ddbe20cb3e0ecf93800ccc953aa
parent9f8fed7c9e76b013f8c2632105d1abec18e6a64e (diff)
downloadr-alacritty-f07622e9082af24dee1501889e13b298c57a1c4d.tar.gz
r-alacritty-f07622e9082af24dee1501889e13b298c57a1c4d.tar.bz2
r-alacritty-f07622e9082af24dee1501889e13b298c57a1c4d.zip
Improve builtin font ellipse rendering
-rw-r--r--CHANGELOG.md1
-rw-r--r--alacritty/src/renderer/text/builtin_font.rs137
2 files changed, 63 insertions, 75 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2f8dbeb7..2054e25c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its
### Changed
- Hide login message if `~/.hushlogin` is present
+- Improve rendering of rounded corners with builtin box drawing
### Fixed
diff --git a/alacritty/src/renderer/text/builtin_font.rs b/alacritty/src/renderer/text/builtin_font.rs
index 1d7664f9..ce4b3bfd 100644
--- a/alacritty/src/renderer/text/builtin_font.rs
+++ b/alacritty/src/renderer/text/builtin_font.rs
@@ -349,7 +349,7 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
},
// Arcs: '╭', '╮', '╯', '╰'.
'\u{256d}' | '\u{256e}' | '\u{256f}' | '\u{2570}' => {
- canvas.draw_ellipse_arc(stroke_size);
+ canvas.draw_rounded_corner(stroke_size);
// Mirror `X` axis.
if character == '\u{256d}' || character == '\u{2570}' {
@@ -875,86 +875,73 @@ impl Canvas {
}
}
- /// Draws a part of an ellipse centered in `(0., 0.)` with `self.x_center()` and `self.y_center`
- /// vertex and co-vertex respectively using a given `stroke` in the bottom-right quadrant of the
- /// `Canvas` coordinate system.
- fn draw_ellipse_arc(&mut self, stroke_size: usize) {
- fn colors_with_error(error: f32, max_transparency: f32) -> (Pixel, Pixel) {
- let transparency = error * max_transparency;
- let alpha_1 = 1. - transparency;
- let alpha_2 = 1. - (max_transparency - transparency);
- let color_1 = Pixel::gray((COLOR_FILL._r as f32 * alpha_1) as u8);
- let color_2 = Pixel::gray((COLOR_FILL._r as f32 * alpha_2) as u8);
- (color_1, color_2)
+ /// Draws a quarter of a circle centered in `(0., self.height - radius)` with radius
+ /// `self.width` and an attached rectangle to form a "╭" using a given `stroke_size` in the
+ /// bottom-right quadrant of the `Canvas` coordinate system.
+ fn draw_rounded_corner(&mut self, stroke_size: usize) {
+ let radius = (self.width.min(self.height) + stroke_size) as f32 / 2.;
+ let stroke_size_f = stroke_size as f32;
+
+ let mut x_offset = 0.;
+ let mut y_offset = 0.;
+ let (long_side, short_side, offset) = if self.height > self.width {
+ (&self.height, &self.width, &mut y_offset)
+ } else {
+ (&self.width, &self.height, &mut x_offset)
+ };
+ let distance_bias = if short_side % 2 == stroke_size % 2 { 0. } else { 0.5 };
+ *offset = *long_side as f32 / 2. - radius + stroke_size_f / 2.;
+ if (self.width % 2 != self.height % 2) && (long_side % 2 == stroke_size % 2) {
+ *offset += 1.;
}
- let h_line_bounds = self.h_line_bounds(self.y_center(), stroke_size);
- let v_line_bounds = self.v_line_bounds(self.x_center(), stroke_size);
- let h_line_bounds = (h_line_bounds.0 as usize, h_line_bounds.1 as usize);
- let v_line_bounds = (v_line_bounds.0 as usize, v_line_bounds.1 as usize);
- let max_transparency = 0.5;
-
- for (radius_y, radius_x) in
- (h_line_bounds.0..h_line_bounds.1).zip(v_line_bounds.0..v_line_bounds.1)
- {
- let radius_x = radius_x as f32;
- let radius_y = radius_y as f32;
- let radius_x2 = radius_x * radius_x;
- let radius_y2 = radius_y * radius_y;
- let quarter = f32::round(radius_x2 / f32::sqrt(radius_x2 + radius_y2)) as usize;
-
- for x in 0..=quarter {
- let x = x as f32;
- let y = radius_y * f32::sqrt(1. - x * x / radius_x2);
- let error = y.fract();
-
- let (color_1, color_2) = colors_with_error(error, max_transparency);
-
- let x = x.clamp(0., radius_x);
- let y_next = (y + 1.).clamp(0., h_line_bounds.1 as f32 - 1.);
- let y = y.clamp(0., h_line_bounds.1 as f32 - 1.);
-
- self.put_pixel(x, y, color_1);
- self.put_pixel(x, y_next, color_2);
- }
-
- let quarter = f32::round(radius_y2 / f32::sqrt(radius_x2 + radius_y2)) as usize;
- for y in 0..=quarter {
+ let radius_i = (short_side + stroke_size + 1) / 2;
+ for y in 0..radius_i {
+ for x in 0..radius_i {
let y = y as f32;
- let x = radius_x * f32::sqrt(1. - y * y / radius_y2);
- let error = x - x.fract();
-
- let (color_1, color_2) = colors_with_error(error, max_transparency);
-
- let x_next = (x + 1.).clamp(0., v_line_bounds.1 as f32 - 1.);
- let x = x.clamp(0., v_line_bounds.1 as f32 - 1.);
- let y = y.clamp(0., radius_y);
-
- self.put_pixel(x, y, color_1);
- self.put_pixel(x_next, y, color_2);
+ let x = x as f32;
+ let distance = x.hypot(y) + distance_bias;
+ let value = if distance < radius - stroke_size_f - 1. {
+ // Inside the circle.
+ 0.
+ } else if distance < radius - stroke_size_f {
+ // On the inner border.
+ 1. + distance - (radius - stroke_size_f)
+ } else if distance < radius - 1. {
+ // Inside the stroke.
+ 1.
+ } else if distance < radius {
+ // On the outer border.
+ radius - distance
+ } else {
+ // Outside of the circle.
+ 0.
+ };
+
+ self.put_pixel(
+ x + x_offset,
+ y + y_offset,
+ Pixel::gray((COLOR_FILL._r as f32 * value) as u8),
+ );
}
}
- // Ensure the part closer to edges is properly filled.
- self.draw_h_line(0., self.y_center(), stroke_size as f32, stroke_size);
- self.draw_v_line(self.x_center(), 0., stroke_size as f32, stroke_size);
-
- // Fill the resulted arc, since it could have gaps in-between.
- for y in 0..self.height {
- let row = y * self.width;
- let left = match self.buffer[row..row + self.width].iter().position(|p| p._r != 0) {
- Some(left) => row + left,
- _ => continue,
- };
- let right = match self.buffer[row..row + self.width].iter().rposition(|p| p._r != 0) {
- Some(right) => row + right,
- _ => continue,
- };
-
- for index in left + 1..right {
- self.buffer[index] =
- self.buffer[index] + self.buffer[index - 1] / 2 + self.buffer[index + 1] / 2;
- }
+ if self.height > self.width {
+ self.draw_rect(
+ self.x_center() - stroke_size_f * 0.5,
+ 0.,
+ stroke_size_f,
+ y_offset,
+ COLOR_FILL,
+ );
+ } else {
+ self.draw_rect(
+ 0.,
+ self.y_center() - stroke_size_f * 0.5,
+ x_offset,
+ stroke_size_f,
+ COLOR_FILL,
+ );
}
}