diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2022-01-30 15:46:02 +0300 |
---|---|---|
committer | Kirill Chibisov <contact@kchibisov.com> | 2022-02-10 03:17:21 +0300 |
commit | 5bab2ad2d0b1f3827f55665fe7b1bac98b4726b6 (patch) | |
tree | 62c78d31b2a1073e05b579191fe68ee47655c828 | |
parent | cd0e5c2a17012ddaf273ed1841e4ca546257a6fd (diff) | |
download | alacritty-5bab2ad2d0b1f3827f55665fe7b1bac98b4726b6.tar.gz alacritty-5bab2ad2d0b1f3827f55665fe7b1bac98b4726b6.zip |
Use cell width to compute builtin font thickness
While using underline thickness could sound logical to draw other
lines most fonts don't make underlines thick compared to cell bounding
box if you increase font size. So instead we're using cell width to
scale builtin font nicely.
This commit also adjusts arcs drawing and alignment.
Fixes #5826.
Fixes #5821.
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | alacritty/src/renderer/builtin_font.rs | 60 |
2 files changed, 58 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f48967f..fce012a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Option `font.builtin_box_drawing` to disable the built-in font for drawing box characters +### Changed + +- Builtin font thickness is now based on cell width instead of underline thickness + ### Fixed - OSC 4 not handling `?` @@ -18,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - OSC 104 not clearing colors when second parameter is empty - Builtin font lines not contiguous when `font.offset` is used - `font.glyph_offset` is no longer applied on builtin font +- Buili-in font arcs alignment ## 0.10.0 diff --git a/alacritty/src/renderer/builtin_font.rs b/alacritty/src/renderer/builtin_font.rs index e905a1ef..f3dbe9bb 100644 --- a/alacritty/src/renderer/builtin_font.rs +++ b/alacritty/src/renderer/builtin_font.rs @@ -1,7 +1,7 @@ //! Hand-rolled drawing of unicode [box drawing](http://www.unicode.org/charts/PDF/U2500.pdf) //! and [block elements](https://www.unicode.org/charts/PDF/U2580.pdf). -use std::{cmp, mem}; +use std::{cmp, mem, ops}; use crossfont::{BitmapBuffer, Metrics, RasterizedGlyph}; @@ -39,8 +39,10 @@ pub fn builtin_glyph( fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> RasterizedGlyph { let height = (metrics.line_height as i32 + offset.y as i32) as usize; let width = (metrics.average_advance as i32 + offset.x as i32) as usize; - let stroke_size = cmp::max(metrics.underline_thickness as usize, 1); - let heavy_stroke_size = stroke_size * 3; + // Use one eight of the cell width, since this is used as a step size for block elemenets. + let stroke_size = cmp::max((width as f32 / 8.).round() as usize, 1); + let heavy_stroke_size = stroke_size * 2; + // Certain symbols require larger canvas than the cell itself, since for proper contiguous // lines they require drawing on neighbour cells. So treat them specially early on and handle // 'normal' characters later. @@ -66,7 +68,7 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster let from_x = 0.; let to_x = x_end + 1.; - for stroke_size in stroke_size..2 * stroke_size { + for stroke_size in 0..2 * stroke_size { let stroke_size = stroke_size as f32 / 2.; if character == '\u{2571}' || character == '\u{2573}' { let h = y_end - stroke_size as f32; @@ -341,7 +343,9 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster // Mirror `X` axis. if character == '\u{256d}' || character == '\u{2570}' { let center = canvas.x_center() as usize; - let extra_offset = if width % 2 == 0 { 1 } else { 0 }; + + let extra_offset = if stroke_size % 2 == width % 2 { 0 } else { 1 }; + let buffer = canvas.buffer_mut(); for y in 1..height { let left = (y - 1) * width; @@ -357,7 +361,9 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster // Mirror `Y` axis. if character == '\u{256d}' || character == '\u{256e}' { let center = canvas.y_center() as usize; - let extra_offset = if height % 2 == 0 { 1 } else { 0 }; + + let extra_offset = if stroke_size % 2 == height % 2 { 0 } else { 1 }; + let buffer = canvas.buffer_mut(); if extra_offset != 0 { let bottom_row = (height - 1) * width; @@ -483,6 +489,28 @@ impl Pixel { } } +impl ops::Add for Pixel { + type Output = Pixel; + + fn add(self, rhs: Pixel) -> Self::Output { + let _r = self._r.saturating_add(rhs._r); + let _g = self._g.saturating_add(rhs._g); + let _b = self._b.saturating_add(rhs._b); + Pixel { _r, _g, _b } + } +} + +impl ops::Div<u8> for Pixel { + type Output = Pixel; + + fn div(self, rhs: u8) -> Self::Output { + let _r = self._r / rhs; + let _g = self._g / rhs; + let _b = self._b / rhs; + Pixel { _r, _g, _b } + } +} + /// Canvas which is used for simple line drawing operations. /// /// The coordinate system is the following: @@ -716,6 +744,24 @@ impl Canvas { // 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; + } + } } /// Fills the `Canvas` with the given `Color`. @@ -744,7 +790,7 @@ mod test { #[test] fn builtin_line_drawing_glyphs_coverage() { - // Dummy metrics values to test builtin glyphs coverage. + // Dummy metrics values to test built-in glyphs coverage. let metrics = Metrics { average_advance: 6., line_height: 16., |