mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Center-align all text vertically (#5117)
* Closes https://github.com/emilk/egui/issues/4929 * Builds on top of https://github.com/emilk/egui/pull/2724 by @lictex (ptal!) * Implement `Center` and `Max` vertical text alignment properly * Change default vertical alignment of text to centering The end result is that text centers better in buttons and other places, especially when mixing in emojis. Before, mixing text of different heights (e.g. emojis and latin text) in a label or button would cause the text to jump vertically. ## Before This is `master`, with custom `FontTweak` to move fonts up and down: <img width="1714" alt="image" src="https://github.com/user-attachments/assets/a10e2927-e824-4580-baea-124c0b38a527"> <img width="102" alt="image" src="https://github.com/user-attachments/assets/cd41f415-197b-42cd-9558-d46d63c21dcb"> ## After This PR, with the default (zero) `FontTweak` <img width="102" alt="image" src="https://github.com/user-attachments/assets/15e7d896-66b1-4996-ab58-dd1850b19a63"> <img width="1714" alt="image" src="https://github.com/user-attachments/assets/54ec708c-7698-4754-b1fc-fea0fd240ec9">
This commit is contained in:
@@ -171,8 +171,12 @@ fn layout_section(
|
||||
paragraph.glyphs.push(Glyph {
|
||||
chr,
|
||||
pos: pos2(paragraph.cursor_x, f32::NAN),
|
||||
size: vec2(glyph_info.advance_width, line_height),
|
||||
ascent: font_impl.map_or(0.0, |font| font.ascent()), // Failure to find the font here would be weird
|
||||
advance_width: glyph_info.advance_width,
|
||||
line_height,
|
||||
font_impl_height: font_impl.map_or(0.0, |f| f.row_height()),
|
||||
font_impl_ascent: font_impl.map_or(0.0, |f| f.ascent()),
|
||||
font_height: font.row_height(),
|
||||
font_ascent: font.ascent(),
|
||||
uv_rect: glyph_info.uv_rect,
|
||||
section_index,
|
||||
});
|
||||
@@ -376,7 +380,7 @@ fn replace_last_glyph_with_overflow_character(
|
||||
|
||||
let (_, last_glyph_info) = font.font_impl_and_glyph_info(last_glyph.chr);
|
||||
|
||||
let mut x = last_glyph.pos.x + last_glyph.size.x;
|
||||
let mut x = last_glyph.pos.x + last_glyph.advance_width;
|
||||
|
||||
let (font_impl, replacement_glyph_info) = font.font_impl_and_glyph_info(overflow_character);
|
||||
|
||||
@@ -391,8 +395,12 @@ fn replace_last_glyph_with_overflow_character(
|
||||
row.glyphs.push(Glyph {
|
||||
chr: overflow_character,
|
||||
pos: pos2(x, f32::NAN),
|
||||
size: vec2(replacement_glyph_info.advance_width, line_height),
|
||||
ascent: font_impl.map_or(0.0, |font| font.ascent()), // Failure to find the font here would be weird
|
||||
advance_width: replacement_glyph_info.advance_width,
|
||||
line_height,
|
||||
font_impl_height: font_impl.map_or(0.0, |f| f.row_height()),
|
||||
font_impl_ascent: font_impl.map_or(0.0, |f| f.ascent()),
|
||||
font_height: font.row_height(),
|
||||
font_ascent: font.ascent(),
|
||||
uv_rect: replacement_glyph_info.uv_rect,
|
||||
section_index,
|
||||
});
|
||||
@@ -409,8 +417,12 @@ fn replace_last_glyph_with_overflow_character(
|
||||
row.glyphs.push(Glyph {
|
||||
chr: overflow_character,
|
||||
pos: pos2(x, f32::NAN),
|
||||
size: vec2(replacement_glyph_info.advance_width, line_height),
|
||||
ascent: font_impl.map_or(0.0, |font| font.ascent()), // Failure to find the font here would be weird
|
||||
advance_width: replacement_glyph_info.advance_width,
|
||||
line_height,
|
||||
font_impl_height: font_impl.map_or(0.0, |f| f.row_height()),
|
||||
font_impl_ascent: font_impl.map_or(0.0, |f| f.ascent()),
|
||||
font_height: font.row_height(),
|
||||
font_ascent: font.ascent(),
|
||||
uv_rect: replacement_glyph_info.uv_rect,
|
||||
section_index,
|
||||
});
|
||||
@@ -438,7 +450,6 @@ fn replace_last_glyph_with_overflow_character(
|
||||
let section = &job.sections[last_glyph.section_index as usize];
|
||||
let extra_letter_spacing = section.format.extra_letter_spacing;
|
||||
let font = fonts.font(§ion.format.font_id);
|
||||
let line_height = row_height(section, font);
|
||||
|
||||
if let Some(prev_glyph) = prev_glyph {
|
||||
let prev_glyph_id = font.font_impl_and_glyph_info(prev_glyph.chr).1.id;
|
||||
@@ -453,7 +464,9 @@ fn replace_last_glyph_with_overflow_character(
|
||||
// Replace the glyph:
|
||||
last_glyph.chr = overflow_character;
|
||||
let (font_impl, glyph_info) = font.font_impl_and_glyph_info(last_glyph.chr);
|
||||
last_glyph.size = vec2(glyph_info.advance_width, line_height);
|
||||
last_glyph.advance_width = glyph_info.advance_width;
|
||||
last_glyph.font_impl_ascent = font_impl.map_or(0.0, |f| f.ascent());
|
||||
last_glyph.font_impl_height = font_impl.map_or(0.0, |f| f.row_height());
|
||||
last_glyph.uv_rect = glyph_info.uv_rect;
|
||||
|
||||
// Reapply kerning:
|
||||
@@ -472,8 +485,10 @@ fn replace_last_glyph_with_overflow_character(
|
||||
} else {
|
||||
// Just replace and be done with it.
|
||||
last_glyph.chr = overflow_character;
|
||||
let (_, glyph_info) = font.font_impl_and_glyph_info(last_glyph.chr);
|
||||
last_glyph.size = vec2(glyph_info.advance_width, line_height);
|
||||
let (font_impl, glyph_info) = font.font_impl_and_glyph_info(last_glyph.chr);
|
||||
last_glyph.advance_width = glyph_info.advance_width;
|
||||
last_glyph.font_impl_ascent = font_impl.map_or(0.0, |f| f.ascent());
|
||||
last_glyph.font_impl_height = font_impl.map_or(0.0, |f| f.row_height());
|
||||
last_glyph.uv_rect = glyph_info.uv_rect;
|
||||
return;
|
||||
}
|
||||
@@ -585,40 +600,36 @@ fn galley_from_rows(
|
||||
let mut min_x: f32 = 0.0;
|
||||
let mut max_x: f32 = 0.0;
|
||||
for row in &mut rows {
|
||||
let mut line_height = first_row_min_height.max(row.rect.height());
|
||||
let mut row_ascent = 0.0f32;
|
||||
let mut max_row_height = first_row_min_height.max(row.rect.height());
|
||||
first_row_min_height = 0.0;
|
||||
|
||||
// take metrics from the highest font in this row
|
||||
if let Some(glyph) = row
|
||||
.glyphs
|
||||
.iter()
|
||||
.max_by(|a, b| a.size.y.partial_cmp(&b.size.y).unwrap())
|
||||
{
|
||||
line_height = glyph.size.y;
|
||||
row_ascent = glyph.ascent;
|
||||
for glyph in &row.glyphs {
|
||||
max_row_height = max_row_height.max(glyph.line_height);
|
||||
}
|
||||
line_height = point_scale.round_to_pixel(line_height);
|
||||
max_row_height = point_scale.round_to_pixel(max_row_height);
|
||||
|
||||
// Now positions each glyph:
|
||||
// Now position each glyph vertically:
|
||||
for glyph in &mut row.glyphs {
|
||||
let format = &job.sections[glyph.section_index as usize].format;
|
||||
|
||||
let align_offset = match format.valign {
|
||||
Align::Center | Align::Max => row_ascent,
|
||||
glyph.pos.y = cursor_y
|
||||
+ glyph.font_impl_ascent
|
||||
|
||||
// raised text.
|
||||
Align::Min => glyph.ascent,
|
||||
};
|
||||
glyph.pos.y = cursor_y + align_offset;
|
||||
// Apply valign to the different in height of the entire row, and the height of this `Font`:
|
||||
+ format.valign.to_factor() * (max_row_height - glyph.line_height)
|
||||
|
||||
// When mixing different `FontImpl` (e.g. latin and emojis),
|
||||
// we always center the difference:
|
||||
+ 0.5 * (glyph.font_height - glyph.font_impl_height);
|
||||
|
||||
glyph.pos.y = point_scale.round_to_pixel(glyph.pos.y);
|
||||
}
|
||||
|
||||
row.rect.min.y = cursor_y;
|
||||
row.rect.max.y = cursor_y + line_height;
|
||||
row.rect.max.y = cursor_y + max_row_height;
|
||||
|
||||
min_x = min_x.min(row.rect.min.x);
|
||||
max_x = max_x.max(row.rect.max.x);
|
||||
cursor_y += line_height;
|
||||
cursor_y += max_row_height;
|
||||
cursor_y = point_scale.round_to_pixel(cursor_y);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user