Created
April 17, 2024 21:02
-
-
Save shaunduncan/f8f869e93bfb79fb69d1500e809e7152 to your computer and use it in GitHub Desktop.
alacritty patch to mimic the behavior of kitty's symbol_map for unicode codepoint substitution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
alacritty/src/config/font.rs | 20 ++++++++++++++ | |
alacritty/src/renderer/text/glyph_cache.rs | 42 ++++++++++++++++++++++++++---- | |
2 files changed, 57 insertions(+), 5 deletions(-) | |
diff --git a/alacritty/src/config/font.rs b/alacritty/src/config/font.rs | |
index 061c0f42..b9630f84 100644 | |
--- a/alacritty/src/config/font.rs | |
+++ b/alacritty/src/config/font.rs | |
@@ -42,6 +42,9 @@ pub struct Font { | |
/// Whether to use the built-in font for box drawing characters. | |
pub builtin_box_drawing: bool, | |
+ | |
+ /// Unicode codepoint substitutions | |
+ pub codepoint_substitutions: Vec<CodepointSubstitution>, | |
} | |
impl Font { | |
@@ -88,6 +91,7 @@ impl Default for Font { | |
normal: Default::default(), | |
bold: Default::default(), | |
size: Default::default(), | |
+ codepoint_substitutions: Default::default(), | |
} | |
} | |
} | |
@@ -163,3 +167,19 @@ impl<'de> Deserialize<'de> for Size { | |
deserializer.deserialize_any(NumVisitor) | |
} | |
} | |
+ | |
+/// Configuration for performing substitution for specific codepoints | |
+#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)] | |
+pub struct CodepointSubstitution { | |
+ pub font: String, | |
+ pub codepoints: Vec<String>, | |
+} | |
+ | |
+impl Default for CodepointSubstitution { | |
+ fn default() -> Self { | |
+ Self { | |
+ font: Default::default(), | |
+ codepoints: Default::default(), | |
+ } | |
+ } | |
+} | |
diff --git a/alacritty/src/renderer/text/glyph_cache.rs b/alacritty/src/renderer/text/glyph_cache.rs | |
index 957cde1a..31d3301f 100644 | |
--- a/alacritty/src/renderer/text/glyph_cache.rs | |
+++ b/alacritty/src/renderer/text/glyph_cache.rs | |
@@ -76,12 +76,35 @@ pub struct GlyphCache { | |
/// Whether to use the built-in font for box drawing characters. | |
builtin_box_drawing: bool, | |
+ | |
+ // glyph replacements | |
+ codepoint_substitutions: HashMap<char, FontKey>, | |
} | |
impl GlyphCache { | |
pub fn new(mut rasterizer: Rasterizer, font: &Font) -> Result<GlyphCache, crossfont::Error> { | |
let (regular, bold, italic, bold_italic) = Self::compute_font_keys(font, &mut rasterizer)?; | |
+ let mut codepoint_substitutions = HashMap::new(); | |
+ | |
+ // setup the symbol override map | |
+ for map in font.codepoint_substitutions.iter() { | |
+ let size = font.size(); | |
+ let description = &FontDescription{ | |
+ family: map.font.clone(), | |
+ style: font.normal().style.clone(), | |
+ }; | |
+ | |
+ let fontdesc = Self::make_desc(description, Slant::Normal, Weight::Normal); | |
+ let mapped_font = Self::load_regular_font(&mut rasterizer, &fontdesc, size)?; | |
+ | |
+ for codepoint in map.codepoints.iter() { | |
+ let codepoint_val = u32::from_str_radix(codepoint.replace("U+", "").as_str(), 16); | |
+ let codepoint_char = char::from_u32(codepoint_val.unwrap()); | |
+ codepoint_substitutions.insert(codepoint_char.unwrap(), mapped_font); | |
+ } | |
+ } | |
+ | |
// Need to load at least one glyph for the face before calling metrics. | |
// The glyph requested here ('m' at the time of writing) has no special | |
// meaning. | |
@@ -101,6 +124,7 @@ impl GlyphCache { | |
glyph_offset: font.glyph_offset, | |
metrics, | |
builtin_box_drawing: font.builtin_box_drawing, | |
+ codepoint_substitutions, | |
}) | |
} | |
@@ -196,8 +220,16 @@ impl GlyphCache { | |
where | |
L: LoadGlyph, | |
{ | |
+ let mut gk = glyph_key; | |
+ | |
+ // does this need a substitution? | |
+ if self.codepoint_substitutions.contains_key(&gk.character) { | |
+ let alt = self.codepoint_substitutions.get(&gk.character).unwrap(); | |
+ gk.font_key = *alt; | |
+ } | |
+ | |
// Try to load glyph from cache. | |
- if let Some(glyph) = self.cache.get(&glyph_key) { | |
+ if let Some(glyph) = self.cache.get(&gk) { | |
return *glyph; | |
}; | |
@@ -207,21 +239,21 @@ impl GlyphCache { | |
.builtin_box_drawing | |
.then(|| { | |
builtin_font::builtin_glyph( | |
- glyph_key.character, | |
+ gk.character, | |
&self.metrics, | |
&self.font_offset, | |
&self.glyph_offset, | |
) | |
}) | |
.flatten() | |
- .map_or_else(|| self.rasterizer.get_glyph(glyph_key), Ok); | |
+ .map_or_else(|| self.rasterizer.get_glyph(gk), Ok); | |
let glyph = match rasterized { | |
Ok(rasterized) => self.load_glyph(loader, rasterized), | |
// Load fallback glyph. | |
Err(RasterizerError::MissingGlyph(rasterized)) if show_missing => { | |
// Use `\0` as "missing" glyph to cache it only once. | |
- let missing_key = GlyphKey { character: '\0', ..glyph_key }; | |
+ let missing_key = GlyphKey { character: '\0', ..gk }; | |
if let Some(glyph) = self.cache.get(&missing_key) { | |
*glyph | |
} else { | |
@@ -236,7 +268,7 @@ impl GlyphCache { | |
}; | |
// Cache rasterized glyph. | |
- *self.cache.entry(glyph_key).or_insert(glyph) | |
+ *self.cache.entry(gk).or_insert(glyph) | |
} | |
/// Load glyph into the atlas. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment