summaryrefslogtreecommitdiffstats
path: root/font
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2017-12-07 21:52:50 +0100
committerJoe Wilm <jwilm@users.noreply.github.com>2017-12-24 09:46:54 -0800
commitd82c4f02b69a8e16057a42de470c5bea114ffda6 (patch)
tree64f7f4bbd14634410cfcabae826a4f63b25199ba /font
parent9f708146d989f601bd4cc5b253cd58db02ce41d3 (diff)
Add custom beam cursor
In issue jwilm/asacritty#31 a few people complained about Beam cursor being weird with their fonts, so to make all cursors uniform in alacritty, a custom cursor has been added for the Beam too. The beam cursor's height is always the full height of the monospace font glyph bounding box. The width depends on the font size. It is calculated using the width of the cell and dividing it by two. The block is always aligned at the far-left of the cell. The implementation is identical to the one of the underline cursor, but it has been refactored so the glyphs are created in `lib.rs`, which can be used by darwin/macos to implement these features too. A small bug in the underline cursor has also been fixed, until now the width was just using the width of the unicode character. Now it should be using the full width of the monospace glyph bounding box with every font. Here are some screenshots for the Beam cursor: ![Small](https://u.teknik.io/v1QH3.png) ![Normal](https://u.teknik.io/RTlp2.png) ![Big](https://u.teknik.io/DLu2M.png) ![Huge](https://u.teknik.io/pSAFX.png)
Diffstat (limited to 'font')
-rw-r--r--font/src/ft/mod.rs75
-rw-r--r--font/src/lib.rs42
2 files changed, 86 insertions, 31 deletions
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index b8559237..7b22fb03 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -24,7 +24,7 @@ use libc::c_uint;
pub mod fc;
-use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey, Weight, Slant, Style, UNDERLINE_CURSOR_CHAR};
+use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey, Weight, Slant, Style};
struct FixedSize {
pixelsize: f64,
@@ -294,37 +294,50 @@ impl FreeTypeRasterizer {
let (pixel_width, buf) = Self::normalize_buffer(&glyph.bitmap())?;
- // Render a custom symbol for the underline cursor
- if glyph_key.c == UNDERLINE_CURSOR_CHAR {
- // Get the bottom of the bounding box
- let size_metrics = face.ft_face.size_metrics()
- .ok_or(Error::MissingSizeMetrics)?;
- let descent = (size_metrics.descender / 64) as f32;
-
- // Create a new rectangle, the height is half the distance between
- // bounding box bottom and the baseline
- let height = f32::abs(descent / 2.) as i32;
- let buf = vec![255u8; (pixel_width * height * 3) as usize];
-
- // Create a custom glyph with the rectangle data attached to it
- return Ok(RasterizedGlyph {
- c: glyph_key.c,
- top: descent as i32 + height,
- left: glyph.bitmap_left(),
- height,
- width: pixel_width,
- buf: buf,
- });
- }
+ // Render a custom symbol for the underline and beam cursor
+ match glyph_key.c {
+ super::UNDERLINE_CURSOR_CHAR => {
+ // Get the bottom of the bounding box
+ let size_metrics = face.ft_face.size_metrics()
+ .ok_or(Error::MissingSizeMetrics)?;
+ let descent = (size_metrics.descender / 64) as i32;
- Ok(RasterizedGlyph {
- c: glyph_key.c,
- top: glyph.bitmap_top(),
- left: glyph.bitmap_left(),
- width: pixel_width,
- height: glyph.bitmap().rows(),
- buf: buf,
- })
+ // Get the width of the cell
+ let metrics = glyph.metrics();
+ let width = (metrics.vertAdvance as f32 / 128.).round() as i32;
+
+ // Return the new custom glyph
+ super::get_underline_cursor_glyph(descent, width)
+ },
+ super::BEAM_CURSOR_CHAR => {
+ // Get the top of the bounding box
+ let size_metrics = face.ft_face.size_metrics()
+ .ok_or(Error::MissingSizeMetrics)?;
+ let ascent = (size_metrics.ascender / 64) as i32 - 1;
+
+ // Get the height of the cell
+ let descent = (size_metrics.descender / 64) as i32;
+ let height = ascent - descent;
+
+ // Get the width of the cell
+ let metrics = glyph.metrics();
+ let width = (metrics.vertAdvance as f32 / 128.).round() as i32;
+
+ // Return the new custom glyph
+ super::get_beam_cursor_glyph(ascent, height, width)
+ },
+ _ => {
+ // If it's not a special char, return the normal glyph
+ Ok(RasterizedGlyph {
+ c: glyph_key.c,
+ top: glyph.bitmap_top(),
+ left: glyph.bitmap_left(),
+ width: pixel_width,
+ height: glyph.bitmap().rows(),
+ buf: buf,
+ })
+ }
+ }
}
fn ft_load_flags(pat: &fc::Pattern) -> freetype::face::LoadFlag {
diff --git a/font/src/lib.rs b/font/src/lib.rs
index 5d35e47a..776127ea 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -65,6 +65,13 @@ pub const UNDERLINE_CURSOR_CHAR: char = '\u{10a3e2}';
#[cfg(target_os = "macos")]
pub const UNDERLINE_CURSOR_CHAR: char = '▁';
+/// Character used for the beam cursor
+#[cfg(not(target_os = "macos"))]
+// This is part of the private use area and should not conflict with any font
+pub const BEAM_CURSOR_CHAR: char = '\u{10a3e3}';
+#[cfg(target_os = "macos")]
+pub const BEAM_CURSOR_CHAR: char = '▎';
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
name: String,
@@ -209,6 +216,41 @@ impl Default for RasterizedGlyph {
}
}
+// Returns a custom underline cursor character
+pub fn get_underline_cursor_glyph(descent: i32, width: i32) -> Result<RasterizedGlyph, Error> {
+ // Create a new rectangle, the height is half the distance between
+ // bounding box bottom and the baseline
+ let height = i32::abs(descent / 2);
+ let buf = vec![255u8; (width * height * 3) as usize];
+
+ // Create a custom glyph with the rectangle data attached to it
+ return Ok(RasterizedGlyph {
+ c: UNDERLINE_CURSOR_CHAR,
+ top: descent + height,
+ left: 0,
+ height,
+ width,
+ buf: buf,
+ });
+}
+
+// Returns a custom beam cursor character
+pub fn get_beam_cursor_glyph(ascent: i32, height: i32, width: i32) -> Result<RasterizedGlyph, Error> {
+ // Create a new rectangle
+ let beam_width = (f64::from(width) / 5.) as i32;
+ let buf = vec![255u8; (beam_width * height * 3) as usize];
+
+ // Create a custom glyph with the rectangle data attached to it
+ return Ok(RasterizedGlyph {
+ c: BEAM_CURSOR_CHAR,
+ top: ascent,
+ left: 0,
+ height,
+ width: beam_width,
+ buf: buf,
+ });
+}
+
struct BufDebugger<'a>(&'a [u8]);
impl<'a> fmt::Debug for BufDebugger<'a> {