mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Add font variations API (#7859)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> * Closes N/A * [x] I have followed the instructions in the PR template This was mostly from last month, but I never got around to submitting it. This PR adds font variation coordinates to the `TextFormat` struct, and uses them when rendering text. The coordinates are stored in a `SmallVec`; I've chosen to store up to 2 inline, which makes it take up 24 bytes (the minimum possible for a `SmallVec`). The variation axis tags are stored as the `font_types::Tag` type, which I've chosen to re-export from `epaint::text`. The variation coordinates are resolved to a `skrifa::Location` during font rendering/scaling, and are cached in the same way as all the other scaled metrics. I've renamed the `ScaledMetrics` struct to `StyledMetrics`, since it now also contains the resolved variation coordinates. I haven't benchmarked the performance of text layout with variation coordinates, but the existing text layout performance is unchanged. I've replaced the API for manually overriding a font's weight (https://github.com/emilk/egui/pull/7790) with an API for manually overriding any variation coordinates via `FontTweak`. This should support the same use case as #7790 while being substantially more flexible. I have *not* yet added any higher-level API for mapping style attributes (weight, width, slant, etc) to variation coordinates or to different font faces within a single family. That's a pretty huge can of worms, and it'd involve rethinking the split between `FontId` and `TextFormat` (and whether `FontId` is so big that we should provide a way to reuse it). This API is intentionally pretty low-level for now. Likewise, I've intentionally not used variation coordinates when computing a font's row height. I can't think of any fonts that change their vertical metrics depending on variation axes, so this should be fine for now. --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::{
|
||||
Color32, Mesh, Stroke, Vertex,
|
||||
stroke::PathStroke,
|
||||
text::{
|
||||
font::{ScaledMetrics, is_cjk, is_cjk_break_allowed},
|
||||
font::{StyledMetrics, is_cjk, is_cjk_break_allowed},
|
||||
fonts::FontFaceKey,
|
||||
},
|
||||
};
|
||||
@@ -160,7 +160,7 @@ fn layout_section(
|
||||
} = section;
|
||||
let mut font = fonts.font(&format.font_id.family);
|
||||
let font_size = format.font_id.size;
|
||||
let font_metrics = font.scaled_metrics(pixels_per_point, font_size);
|
||||
let font_metrics = font.styled_metrics(pixels_per_point, font_size, &format.coords);
|
||||
let line_height = section
|
||||
.format
|
||||
.line_height
|
||||
@@ -178,7 +178,7 @@ fn layout_section(
|
||||
|
||||
// Optimization: only recompute `ScaledMetrics` when the concrete `FontImpl` changes.
|
||||
let mut current_font = FontFaceKey::INVALID;
|
||||
let mut current_font_face_metrics = ScaledMetrics::default();
|
||||
let mut current_font_face_metrics = StyledMetrics::default();
|
||||
|
||||
for chr in job.text[byte_range.clone()].chars() {
|
||||
if job.break_on_newline && chr == '\n' {
|
||||
@@ -192,7 +192,9 @@ fn layout_section(
|
||||
current_font = font_id;
|
||||
current_font_face_metrics = font_face
|
||||
.as_ref()
|
||||
.map(|font_face| font_face.scaled_metrics(pixels_per_point, font_size))
|
||||
.map(|font_face| {
|
||||
font_face.styled_metrics(pixels_per_point, font_size, &format.coords)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}
|
||||
|
||||
@@ -468,7 +470,7 @@ fn replace_last_glyph_with_overflow_character(
|
||||
let mut font_face = font.fonts_by_id.get_mut(&font_id);
|
||||
let font_face_metrics = font_face
|
||||
.as_mut()
|
||||
.map(|f| f.scaled_metrics(pixels_per_point, font_size))
|
||||
.map(|f| f.styled_metrics(pixels_per_point, font_size, §ion.format.coords))
|
||||
.unwrap_or_default();
|
||||
|
||||
let overflow_glyph_x = if let Some(prev_glyph) = row.glyphs.last() {
|
||||
@@ -519,7 +521,8 @@ fn replace_last_glyph_with_overflow_character(
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let font_metrics = font.scaled_metrics(pixels_per_point, font_size);
|
||||
let font_metrics =
|
||||
font.styled_metrics(pixels_per_point, font_size, §ion.format.coords);
|
||||
let line_height = section
|
||||
.format
|
||||
.line_height
|
||||
@@ -1212,7 +1215,7 @@ mod tests {
|
||||
let font_id = FontId::default();
|
||||
let font_height = fonts
|
||||
.font(&font_id.family)
|
||||
.scaled_metrics(pixels_per_point, font_id.size)
|
||||
.styled_metrics(pixels_per_point, font_id.size, &VariationCoords::default())
|
||||
.row_height;
|
||||
|
||||
let job = LayoutJob::simple(String::new(), font_id, Color32::WHITE, f32::INFINITY);
|
||||
@@ -1245,7 +1248,7 @@ mod tests {
|
||||
let font_id = FontId::default();
|
||||
let font_height = fonts
|
||||
.font(&font_id.family)
|
||||
.scaled_metrics(pixels_per_point, font_id.size)
|
||||
.styled_metrics(pixels_per_point, font_id.size, &VariationCoords::default())
|
||||
.row_height;
|
||||
|
||||
let job = LayoutJob::simple("Hi!\n".to_owned(), font_id, Color32::WHITE, f32::INFINITY);
|
||||
|
||||
Reference in New Issue
Block a user