From e6240759a5305db88845ddd8edc08b22ef034778 Mon Sep 17 00:00:00 2001 From: StarStarJ Date: Sat, 26 Oct 2024 15:59:31 +0200 Subject: [PATCH] Reduce the amount of `FontDefinitions` cloning --- crates/egui/src/context.rs | 23 +++++++++++------------ crates/egui/src/lib.rs | 4 ++-- crates/egui/src/memory/mod.rs | 2 +- crates/egui_demo_lib/benches/benchmark.rs | 7 ++----- crates/epaint/src/text/fonts.rs | 6 +++--- crates/epaint/src/text/text_layout.rs | 10 +++++----- examples/custom_font/src/main.rs | 3 ++- 7 files changed, 26 insertions(+), 29 deletions(-) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 7e7eff2eb74..f43c5ab263d 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -401,7 +401,7 @@ struct ContextImpl { /// This is because the `Fonts` depend on `pixels_per_point` for the font atlas /// as well as kerning, font sizes, etc. fonts: std::collections::BTreeMap, Fonts>, - font_definitions: FontDefinitions, + font_definitions: Arc, memory: Memory, animation_manager: AnimationManager, @@ -583,22 +583,21 @@ impl ContextImpl { } if !self.memory.add_fonts.is_empty() { + // Recreate all the fonts + self.fonts.clear(); + let mut font_definitions = self.font_definitions.as_ref().clone(); let fonts = self.memory.add_fonts.drain(..); for font in fonts { - self.fonts.clear(); // recreate all the fonts for family in font.families { - let fam = self - .font_definitions - .families - .entry(family.family) - .or_default(); + let fam = font_definitions.families.entry(family.family).or_default(); match family.priority { FontPriority::Highest => fam.insert(0, font.name.clone()), FontPriority::Lowest => fam.push(font.name.clone()), } } - self.font_definitions.font_data.insert(font.name, font.data); + font_definitions.font_data.insert(font.name, font.data); } + self.font_definitions = Arc::new(font_definitions); #[cfg(feature = "log")] log::trace!("Adding new fonts"); @@ -1750,7 +1749,7 @@ impl Context { /// /// The new fonts will become active at the start of the next pass. /// This will overwrite the existing fonts. - pub fn set_fonts(&self, font_definitions: FontDefinitions) { + pub fn set_fonts(&self, font_definitions: Arc) { crate::profile_function!(); let pixels_per_point = self.pixels_per_point(); @@ -1760,7 +1759,7 @@ impl Context { self.read(|ctx| { if let Some(current_fonts) = ctx.fonts.get(&pixels_per_point.into()) { // NOTE: this comparison is expensive since it checks TTF data for equality - if current_fonts.lock().fonts.definitions() == &font_definitions { + if current_fonts.lock().fonts.definitions() == font_definitions.as_ref() { update_fonts = false; // no need to update } } @@ -2935,7 +2934,7 @@ impl Context { } fn fonts_tweak_ui(&self, ui: &mut Ui) { - let mut font_definitions = self.write(|ctx| ctx.font_definitions.clone()); + let mut font_definitions = self.write(|ctx| ctx.font_definitions.as_ref().clone()); let mut changed = false; for (name, data) in &mut font_definitions.font_data { @@ -2947,7 +2946,7 @@ impl Context { } if changed { - self.set_fonts(font_definitions); + self.set_fonts(Arc::new(font_definitions)); } } diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index 29cd9ddcac8..dae8dfb74dd 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -667,7 +667,7 @@ pub enum WidgetType { /// For use in tests; especially doctests. pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) { let ctx = Context::default(); - ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) + ctx.set_fonts(std::sync::Arc::new(FontDefinitions::empty())); // prevent fonts from being loaded (save CPU time) let _ = ctx.run(Default::default(), |ctx| { run_ui(ctx); }); @@ -676,7 +676,7 @@ pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) { /// For use in tests; especially doctests. pub fn __run_test_ui(add_contents: impl Fn(&mut Ui)) { let ctx = Context::default(); - ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) + ctx.set_fonts(std::sync::Arc::new(FontDefinitions::empty())); // prevent fonts from being loaded (save CPU time) let _ = ctx.run(Default::default(), |ctx| { crate::CentralPanel::default().show(ctx, |ui| { add_contents(ui); diff --git a/crates/egui/src/memory/mod.rs b/crates/egui/src/memory/mod.rs index 75183bdd15b..cc04826408d 100644 --- a/crates/egui/src/memory/mod.rs +++ b/crates/egui/src/memory/mod.rs @@ -77,7 +77,7 @@ pub struct Memory { // ------------------------------------------ /// new fonts that will be applied at the start of the next frame #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) new_font_definitions: Option, + pub(crate) new_font_definitions: Option>, /// add new font that will be applied at the start of the next frame #[cfg_attr(feature = "persistence", serde(skip))] diff --git a/crates/egui_demo_lib/benches/benchmark.rs b/crates/egui_demo_lib/benches/benchmark.rs index d3820603d5c..b7573aa4f0d 100644 --- a/crates/egui_demo_lib/benches/benchmark.rs +++ b/crates/egui_demo_lib/benches/benchmark.rs @@ -90,11 +90,8 @@ pub fn criterion_benchmark(c: &mut Criterion) { let wrap_width = 512.0; let font_id = egui::FontId::default(); let text_color = egui::Color32::WHITE; - let fonts = egui::epaint::text::Fonts::new( - pixels_per_point, - max_texture_side, - egui::FontDefinitions::default(), - ); + let fonts = + egui::epaint::text::Fonts::new(pixels_per_point, max_texture_side, Default::default()); { let mut locked_fonts = fonts.lock(); c.bench_function("text_layout_uncached", |b| { diff --git a/crates/epaint/src/text/fonts.rs b/crates/epaint/src/text/fonts.rs index 685bdf9b8a8..772c7a92c56 100644 --- a/crates/epaint/src/text/fonts.rs +++ b/crates/epaint/src/text/fonts.rs @@ -418,7 +418,7 @@ impl Fonts { pub fn new( pixels_per_point: f32, max_texture_side: usize, - definitions: FontDefinitions, + definitions: Arc, ) -> Self { let fonts_and_cache = FontsAndCache { fonts: FontsImpl::new(pixels_per_point, max_texture_side, definitions), @@ -614,7 +614,7 @@ impl FontsAndCache { pub struct FontsImpl { pixels_per_point: f32, max_texture_side: usize, - definitions: FontDefinitions, + definitions: Arc, atlas: Arc>, font_impl_cache: FontImplCache, sized_family: ahash::HashMap<(OrderedFloat, FontFamily), Font>, @@ -626,7 +626,7 @@ impl FontsImpl { pub fn new( pixels_per_point: f32, max_texture_side: usize, - definitions: FontDefinitions, + definitions: Arc, ) -> Self { assert!( 0.0 < pixels_per_point && pixels_per_point < 100.0, diff --git a/crates/epaint/src/text/text_layout.rs b/crates/epaint/src/text/text_layout.rs index 9db77f888af..a2017f6b4d1 100644 --- a/crates/epaint/src/text/text_layout.rs +++ b/crates/epaint/src/text/text_layout.rs @@ -1042,7 +1042,7 @@ mod tests { #[test] fn test_zero_max_width() { - let mut fonts = FontsImpl::new(1.0, 1024, FontDefinitions::default()); + let mut fonts = FontsImpl::new(1.0, 1024, Default::default()); let mut layout_job = LayoutJob::single_section("W".into(), TextFormat::default()); layout_job.wrap.max_width = 0.0; let galley = layout(&mut fonts, layout_job.into()); @@ -1053,7 +1053,7 @@ mod tests { fn test_truncate_with_newline() { // No matter where we wrap, we should be appending the newline character. - let mut fonts = FontsImpl::new(1.0, 1024, FontDefinitions::default()); + let mut fonts = FontsImpl::new(1.0, 1024, Default::default()); let text_format = TextFormat { font_id: FontId::monospace(12.0), ..Default::default() @@ -1098,7 +1098,7 @@ mod tests { #[test] fn test_cjk() { - let mut fonts = FontsImpl::new(1.0, 1024, FontDefinitions::default()); + let mut fonts = FontsImpl::new(1.0, 1024, Default::default()); let mut layout_job = LayoutJob::single_section( "日本語とEnglishの混在した文章".into(), TextFormat::default(), @@ -1113,7 +1113,7 @@ mod tests { #[test] fn test_pre_cjk() { - let mut fonts = FontsImpl::new(1.0, 1024, FontDefinitions::default()); + let mut fonts = FontsImpl::new(1.0, 1024, Default::default()); let mut layout_job = LayoutJob::single_section( "日本語とEnglishの混在した文章".into(), TextFormat::default(), @@ -1128,7 +1128,7 @@ mod tests { #[test] fn test_truncate_width() { - let mut fonts = FontsImpl::new(1.0, 1024, FontDefinitions::default()); + let mut fonts = FontsImpl::new(1.0, 1024, Default::default()); let mut layout_job = LayoutJob::single_section("# DNA\nMore text".into(), TextFormat::default()); layout_job.wrap.max_width = f32::INFINITY; diff --git a/examples/custom_font/src/main.rs b/examples/custom_font/src/main.rs index 99c98a6e158..7155537a903 100644 --- a/examples/custom_font/src/main.rs +++ b/examples/custom_font/src/main.rs @@ -5,6 +5,7 @@ use eframe::{ egui, epaint::text::{FontInsert, InsertFontFamily}, }; +use std::sync::Arc; fn main() -> eframe::Result { env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`). @@ -68,7 +69,7 @@ fn replace_fonts(ctx: &egui::Context) { .push("my_font".to_owned()); // Tell egui to use these fonts: - ctx.set_fonts(fonts); + ctx.set_fonts(Arc::new(fonts)); } struct MyApp {