mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 13:20:05 -04:00
Wrap Fonts in a Mutex
This commit is contained in:
@@ -230,7 +230,106 @@ impl Default for FontDefinitions {
|
||||
/// The collection of fonts used by `epaint`.
|
||||
///
|
||||
/// Required in order to paint text.
|
||||
pub struct Fonts {
|
||||
/// Create one and reuse. Cheap to clone.
|
||||
///
|
||||
/// Wrapper for `Arc<Mutex<FontsImpl>>`.
|
||||
pub struct Fonts(Arc<Mutex<FontsImpl>>);
|
||||
|
||||
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 {
|
||||
Self(Arc::new(Mutex::new(FontsImpl::new(
|
||||
pixels_per_point,
|
||||
definitions,
|
||||
))))
|
||||
}
|
||||
|
||||
/// Access the underlying [`FontsImpl`].
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn lock(&self) -> crate::mutex::MutexGuard<'_, FontsImpl> {
|
||||
self.0.lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pixels_per_point(&self) -> f32 {
|
||||
self.lock().pixels_per_point
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// Height of one row of text. In points
|
||||
#[inline]
|
||||
pub fn row_height(&self, text_style: TextStyle) -> f32 {
|
||||
self.lock().row_height(text_style)
|
||||
}
|
||||
|
||||
/// Layout some text.
|
||||
/// This is the most advanced layout function.
|
||||
/// See also [`Self::layout`], [`Self::layout_no_wrap`] and
|
||||
/// [`Self::layout_delayed_color`].
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
/// #[inline]
|
||||
pub fn layout_job(&self, job: LayoutJob) -> Arc<Galley> {
|
||||
self.lock().layout_job(job)
|
||||
}
|
||||
|
||||
/// Will wrap text at the given width and line break at `\n`.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
let job = LayoutJob::simple(text, text_style, color, wrap_width);
|
||||
self.layout_job(job)
|
||||
}
|
||||
|
||||
/// Will line break at `\n`.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_no_wrap(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
) -> Arc<Galley> {
|
||||
let job = LayoutJob::simple(text, text_style, color, f32::INFINITY);
|
||||
self.layout_job(job)
|
||||
}
|
||||
|
||||
/// Like [`Self::layout`], made for when you want to pick a color for the text later.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_delayed_color(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
self.layout_job(LayoutJob::simple(
|
||||
text,
|
||||
text_style,
|
||||
crate::Color32::TEMPORARY_COLOR,
|
||||
wrap_width,
|
||||
))
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// The collection of fonts used by `epaint`.
|
||||
///
|
||||
/// Required in order to paint text.
|
||||
pub struct FontsImpl {
|
||||
pixels_per_point: f32,
|
||||
definitions: FontDefinitions,
|
||||
fonts: BTreeMap<TextStyle, Font>,
|
||||
@@ -238,9 +337,9 @@ pub struct Fonts {
|
||||
galley_cache: Mutex<GalleyCache>,
|
||||
}
|
||||
|
||||
impl Fonts {
|
||||
/// Create a new [`Fonts`] for text layout.
|
||||
/// This call is expensive, so only create one [`Fonts`] and then reuse it.
|
||||
impl FontsImpl {
|
||||
/// Create a new [`FontsImpl`] for text layout.
|
||||
/// This call is expensive, so only create one [`FontsImpl`] and then reuse it.
|
||||
pub fn new(pixels_per_point: f32, definitions: FontDefinitions) -> Self {
|
||||
assert!(
|
||||
0.0 < pixels_per_point && pixels_per_point < 100.0,
|
||||
@@ -332,51 +431,6 @@ impl Fonts {
|
||||
pub fn layout_job(&self, job: LayoutJob) -> Arc<Galley> {
|
||||
self.galley_cache.lock().layout(self, job)
|
||||
}
|
||||
|
||||
/// Will wrap text at the given width and line break at `\n`.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
let job = LayoutJob::simple(text, text_style, color, wrap_width);
|
||||
self.layout_job(job)
|
||||
}
|
||||
|
||||
/// Will line break at `\n`.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_no_wrap(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
) -> Arc<Galley> {
|
||||
let job = LayoutJob::simple(text, text_style, color, f32::INFINITY);
|
||||
self.layout_job(job)
|
||||
}
|
||||
|
||||
/// Like [`Self::layout`], made for when you want to pick a color for the text later.
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_delayed_color(
|
||||
&self,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
self.layout_job(LayoutJob::simple(
|
||||
text,
|
||||
text_style,
|
||||
crate::Color32::TEMPORARY_COLOR,
|
||||
wrap_width,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn num_galleys_in_cache(&self) -> usize {
|
||||
self.galley_cache.lock().num_galleys_in_cache()
|
||||
}
|
||||
@@ -403,7 +457,7 @@ struct GalleyCache {
|
||||
}
|
||||
|
||||
impl GalleyCache {
|
||||
fn layout(&mut self, fonts: &Fonts, job: LayoutJob) -> Arc<Galley> {
|
||||
fn layout(&mut self, fonts: &FontsImpl, job: LayoutJob) -> Arc<Galley> {
|
||||
let hash = crate::util::hash(&job); // TODO: even faster hasher?
|
||||
|
||||
match self.cache.entry(hash) {
|
||||
|
||||
@@ -10,7 +10,7 @@ mod text_layout_types;
|
||||
pub const TAB_SIZE: usize = 4;
|
||||
|
||||
pub use {
|
||||
fonts::{FontData, FontDefinitions, FontFamily, Fonts, TextStyle},
|
||||
fonts::{FontData, FontDefinitions, FontFamily, Fonts, FontsImpl, TextStyle},
|
||||
text_layout::layout,
|
||||
text_layout_types::*,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use super::{Fonts, Galley, Glyph, LayoutJob, LayoutSection, Row, RowVisuals};
|
||||
use super::{FontsImpl, Galley, Glyph, LayoutJob, LayoutSection, Row, RowVisuals};
|
||||
use crate::{mutex::Arc, Color32, Mesh, Stroke, Vertex};
|
||||
use emath::*;
|
||||
|
||||
@@ -50,7 +50,7 @@ struct Paragraph {
|
||||
///
|
||||
/// In most cases you should use [`Fonts::layout_job`] instead
|
||||
/// since that memoizes the input, making subsequent layouting of the same text much faster.
|
||||
pub fn layout(fonts: &Fonts, job: Arc<LayoutJob>) -> Galley {
|
||||
pub fn layout(fonts: &FontsImpl, job: Arc<LayoutJob>) -> Galley {
|
||||
let mut paragraphs = vec![Paragraph::default()];
|
||||
for (section_index, section) in job.sections.iter().enumerate() {
|
||||
layout_section(fonts, &job, section_index as u32, section, &mut paragraphs);
|
||||
@@ -75,7 +75,7 @@ pub fn layout(fonts: &Fonts, job: Arc<LayoutJob>) -> Galley {
|
||||
}
|
||||
|
||||
fn layout_section(
|
||||
fonts: &Fonts,
|
||||
fonts: &FontsImpl,
|
||||
job: &LayoutJob,
|
||||
section_index: u32,
|
||||
section: &LayoutSection,
|
||||
|
||||
Reference in New Issue
Block a user