1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Make the width of the thin space configurable (#8070)

Adds `FontTweak::thin_space_width` and `FontTweak::tab_size`
This commit is contained in:
Emil Ernerfeldt
2026-04-06 18:09:54 +02:00
committed by GitHub
parent 16cad760a5
commit ab4bca65ea
11 changed files with 73 additions and 37 deletions

View File

@@ -432,8 +432,7 @@ impl FontFace {
&& let Some(space) = self.glyph_info(' ')
{
let glyph_info = GlyphInfo {
advance_width_unscaled: (crate::text::TAB_SIZE as f32
* space.advance_width_unscaled.0)
advance_width_unscaled: (self.tweak.tab_size * space.advance_width_unscaled.0)
.into(),
..space
};
@@ -441,21 +440,18 @@ impl FontFace {
return Some(glyph_info);
}
if c == '\u{2009}' {
// Thin space, often used as thousands deliminator: 1234567890
// https://www.compart.com/en/unicode/U+2009
// https://en.wikipedia.org/wiki/Thin_space
if let Some(space) = self.glyph_info(' ') {
let em = self.font.borrow_dependent().metrics.units_per_em as f32;
let advance_width = f32::min(em / 6.0, space.advance_width_unscaled.0 * 0.5); // TODO(emilk): make configurable
let glyph_info = GlyphInfo {
advance_width_unscaled: advance_width.into(),
..space
};
self.glyph_info_cache.insert(c, glyph_info);
return Some(glyph_info);
}
if (c == '\u{2009}' || c == '\u{202F}')
&& let Some(space) = self.glyph_info(' ')
{
// Thin space (U+2009) and narrow no-break space (U+202F),
// often used as thousands separator: 1234567890
let advance_width = self.tweak.thin_space_width * space.advance_width_unscaled.0;
let glyph_info = GlyphInfo {
advance_width_unscaled: advance_width.into(),
..space
};
self.glyph_info_cache.insert(c, glyph_info);
return Some(glyph_info);
}
if invisible_char(c) {

View File

@@ -193,6 +193,19 @@ pub struct FontTweak {
/// Override the font's default variation coordinates.
pub coords: VariationCoords,
/// Width of a thin space (`\u{2009}`) and narrow no-break space (`\u{202F}`),
/// as a fraction of the normal space width.
///
/// Thin space is often used as a thousands separator: `1 234 567`.
///
/// Default: `0.5` (half a normal space).
pub thin_space_width: f32,
/// Width of a tab character (`\t`), measured in number of space widths.
///
/// Default: `4.0`.
pub tab_size: f32,
}
impl Default for FontTweak {
@@ -203,6 +216,8 @@ impl Default for FontTweak {
y_offset: 0.0,
hinting_override: None,
coords: VariationCoords::default(),
thin_space_width: 0.5,
tab_size: 4.0,
}
}
}

View File

@@ -6,9 +6,6 @@ mod fonts;
mod text_layout;
mod text_layout_types;
/// One `\t` character is this many spaces wide.
pub const TAB_SIZE: usize = 4;
pub use {
fonts::{
FontData, FontDefinitions, FontFamily, FontId, FontInsert, FontPriority, FontTweak, Fonts,

View File

@@ -8,7 +8,6 @@ use crate::{
Color32, Mesh, Stroke, Vertex,
stroke::PathStroke,
text::{
TAB_SIZE,
font::{StyledMetrics, UvRect, is_cjk, is_cjk_break_allowed},
fonts::FontFaceKey,
},
@@ -250,11 +249,23 @@ fn layout_shaped_run(
.unwrap_or('\u{FFFD}'); // Unicode Replacement Character
// Tab is a layout concept, not a glyph — the shaper doesn't know about tab stops.
// Override the advance width to TAB_SIZE × space width.
// Override the advance width using the font's configured tab size.
if chr == '\t' {
let tweak = font.fonts_by_id.get(&run.font_key).map(|ff| ff.tweak());
let tab_size = tweak.map_or(4.0, |t| t.tab_size);
let (_, space_info) = font.glyph_info(' ');
let space_width_px = space_info.advance_width_unscaled.0 * px_scale;
advance_width_px = TAB_SIZE as f32 * space_width_px;
advance_width_px = tab_size * space_width_px;
}
// Thin space (U+2009) and narrow no-break space (U+202F):
// override the shaper's advance width with the configured fraction of a space.
if chr == '\u{2009}' || chr == '\u{202F}' {
let tweak = font.fonts_by_id.get(&run.font_key).map(|ff| ff.tweak());
let thin_space_width = tweak.map_or(0.5, |t| t.thin_space_width);
let (_, space_info) = font.glyph_info(' ');
let space_width_px = space_info.advance_width_unscaled.0 * px_scale;
advance_width_px = thin_space_width * space_width_px;
}
// Apply extra_letter_spacing only at cluster boundaries,