diff --git a/egui/src/context.rs b/egui/src/context.rs index 6c4087d6..5326aa7d 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -93,7 +93,7 @@ impl ContextImpl { new_font_definitions.unwrap_or_else(|| { self.fonts .as_ref() - .map(|font| font.lock().definitions().clone()) + .map(|font| font.lock().fonts.definitions().clone()) .unwrap_or_default() }), )); @@ -521,7 +521,7 @@ impl Context { pub fn set_fonts(&self, font_definitions: FontDefinitions) { if let Some(current_fonts) = &*self.fonts_mut() { // NOTE: this comparison is expensive since it checks TTF data for equality - if current_fonts.lock().definitions() == &font_definitions { + if current_fonts.lock().fonts.definitions() == &font_definitions { return; // no change - save us from reloading font textures } } @@ -708,7 +708,7 @@ impl Context { .memory .end_frame(&ctx_impl.input, &ctx_impl.frame_state.used_ids); - let font_image_delta = ctx_impl.fonts.as_ref().unwrap().lock().font_image_delta(); + let font_image_delta = ctx_impl.fonts.as_ref().unwrap().font_image_delta(); if let Some(font_image_delta) = font_image_delta { ctx_impl .tex_manager @@ -754,7 +754,7 @@ impl Context { let clipped_meshes = tessellator::tessellate_shapes( shapes, tessellation_options, - self.fonts().lock().font_image_size(), + self.fonts().font_image_size(), ); self.write().paint_stats = paint_stats.with_clipped_meshes(&clipped_meshes); clipped_meshes @@ -956,9 +956,9 @@ impl Context { CollapsingHeader::new("🔠 Fonts") .default_open(false) .show(ui, |ui| { - let mut font_definitions = self.fonts().lock().definitions().clone(); + let mut font_definitions = self.fonts().lock().fonts.definitions().clone(); font_definitions.ui(ui); - let font_image_size = self.fonts().lock().font_image_size(); + let font_image_size = self.fonts().font_image_size(); crate::introspection::font_texture_ui(ui, font_image_size); self.set_fonts(font_definitions); }); diff --git a/egui_demo_lib/benches/benchmark.rs b/egui_demo_lib/benches/benchmark.rs index 828e378e..52cda70f 100644 --- a/egui_demo_lib/benches/benchmark.rs +++ b/egui_demo_lib/benches/benchmark.rs @@ -92,7 +92,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { let fonts = egui::epaint::text::Fonts::new(pixels_per_point, egui::FontDefinitions::default()); { - let mut fonts_impl = fonts.lock(); + let mut locked_fonts = fonts.lock(); c.bench_function("text_layout_uncached", |b| { b.iter(|| { use egui::epaint::text::{layout, LayoutJob}; @@ -103,7 +103,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { color, wrap_width, ); - layout(&mut fonts_impl, job.into()) + layout(&mut locked_fonts.fonts, job.into()) }) }); } @@ -115,7 +115,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { let mut tessellator = egui::epaint::Tessellator::from_options(Default::default()); let mut mesh = egui::epaint::Mesh::default(); let text_shape = TextShape::new(egui::Pos2::ZERO, galley); - let font_image_size = fonts.lock().font_image_size(); + let font_image_size = fonts.font_image_size(); c.bench_function("tessellate_text", |b| { b.iter(|| { tessellator.tessellate_text(font_image_size, text_shape.clone(), &mut mesh); diff --git a/egui_demo_lib/src/apps/demo/font_book.rs b/egui_demo_lib/src/apps/demo/font_book.rs index d8d901b0..c3276466 100644 --- a/egui_demo_lib/src/apps/demo/font_book.rs +++ b/egui_demo_lib/src/apps/demo/font_book.rs @@ -73,6 +73,7 @@ impl super::View for FontBook { let named_chars = self.named_chars.entry(text_style).or_insert_with(|| { ui.fonts() .lock() + .fonts .font_mut(text_style) .characters() .iter() diff --git a/epaint/src/text/fonts.rs b/epaint/src/text/fonts.rs index e3332904..fdcd4501 100644 --- a/epaint/src/text/fonts.rs +++ b/epaint/src/text/fonts.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use crate::{ - mutex::{Arc, Mutex}, + mutex::{Arc, Mutex, MutexGuard}, text::{ font::{Font, FontImpl}, Galley, LayoutJob, @@ -232,45 +232,52 @@ impl Default for FontDefinitions { /// Required in order to paint text. /// Create one and reuse. Cheap to clone. /// -/// Wrapper for `Arc>`. -pub struct Fonts { - fonts: Arc>, - galley_cache: Arc>, -} +/// Wrapper for `Arc>`. +pub struct Fonts(Arc>); impl Fonts { /// Create a new [`Fonts`] for text layout. /// This call is expensive, so only create one [`Fonts`] and then reuse it. pub fn new(pixels_per_point: f32, definitions: FontDefinitions) -> Self { - let fonts = Arc::new(Mutex::new(FontsImpl::new(pixels_per_point, definitions))); - Self { - fonts, + let fonts_and_cache = FontsAndCache { + fonts: FontsImpl::new(pixels_per_point, definitions), galley_cache: Default::default(), - } + }; + Self(Arc::new(Mutex::new(fonts_and_cache))) } - /// Access the underlying [`FontsImpl`]. + /// Access the underlying [`FontsAndCache`]. #[doc(hidden)] #[inline] - pub fn lock(&self) -> crate::mutex::MutexGuard<'_, FontsImpl> { - self.fonts.lock() + pub fn lock(&self) -> MutexGuard<'_, FontsAndCache> { + self.0.lock() } #[inline] pub fn pixels_per_point(&self) -> f32 { - self.lock().pixels_per_point + self.lock().fonts.pixels_per_point + } + + /// Call each frame to get the change to the font texture since last call. + pub fn font_image_delta(&self) -> Option { + self.lock().fonts.atlas.lock().take_delta() + } + + /// Current size of the font image + pub fn font_image_size(&self) -> [usize; 2] { + self.lock().fonts.atlas.lock().size() } /// Width of this character in points. #[inline] pub fn glyph_width(&self, text_style: TextStyle, c: char) -> f32 { - self.lock().glyph_width(text_style, c) + self.lock().fonts.glyph_width(text_style, c) } /// Height of one row of text. In points #[inline] pub fn row_height(&self, text_style: TextStyle) -> f32 { - self.lock().row_height(text_style) + self.lock().fonts.row_height(text_style) } /// Layout some text. @@ -281,16 +288,16 @@ impl Fonts { /// The implementation uses memoization so repeated calls are cheap. /// #[inline] pub fn layout_job(&self, job: LayoutJob) -> Arc { - self.galley_cache.lock().layout(&mut self.fonts.lock(), job) + self.lock().layout_job(job) } pub fn num_galleys_in_cache(&self) -> usize { - self.galley_cache.lock().num_galleys_in_cache() + self.lock().galley_cache.num_galleys_in_cache() } /// Must be called once per frame to clear the [`Galley`] cache. pub fn end_frame(&self) { - self.galley_cache.lock().end_frame(); + self.lock().galley_cache.end_frame(); } /// Will wrap text at the given width and line break at `\n`. @@ -340,10 +347,16 @@ impl Fonts { // ---------------------------------------------------------------------------- -// pub struct CachedFonts { -// fonts: Arc>, -// galley_cache: Arc>, -// } +pub struct FontsAndCache { + pub fonts: FontsImpl, + galley_cache: GalleyCache, +} + +impl FontsAndCache { + fn layout_job(&mut self, job: LayoutJob) -> Arc { + self.galley_cache.layout(&mut self.fonts, job) + } +} // ---------------------------------------------------------------------------- @@ -421,23 +434,13 @@ impl FontsImpl { self.fonts.get_mut(&text_style).unwrap() } - /// Call each frame to get the change to the font texture since last call. - pub fn font_image_delta(&self) -> Option { - self.atlas.lock().take_delta() - } - - /// Current size of the font image - pub fn font_image_size(&self) -> [usize; 2] { - self.atlas.lock().size() - } - /// Width of this character in points. - pub fn glyph_width(&mut self, text_style: TextStyle, c: char) -> f32 { + fn glyph_width(&mut self, text_style: TextStyle, c: char) -> f32 { self.font_mut(text_style).glyph_width(c) } /// Height of one row of text. In points - pub fn row_height(&self, text_style: TextStyle) -> f32 { + fn row_height(&self, text_style: TextStyle) -> f32 { self.fonts[&text_style].row_height() } }