mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Stop wrapping FontsImpl in an Arc<Mutex<_>>
We never need to clone it, and none of its methods took `self` as mutable, meaning it wasn't making use of the semantic difference between the two. This API is about to get reworked, and simplifying it is a first step.
This commit is contained in:
@@ -60,7 +60,7 @@ pub trait AtomExt<'a> {
|
||||
{
|
||||
let font_selection = FontSelection::default();
|
||||
let font_id = font_selection.resolve(ui.style());
|
||||
let height = ui.fonts(|f| f.row_height(&font_id));
|
||||
let height = ui.fonts_mut(|f| f.row_height(&font_id));
|
||||
self.atom_max_height(height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ impl Window<'_> {
|
||||
let (title_bar_height_with_margin, title_content_spacing) = if with_title_bar {
|
||||
let style = ctx.style();
|
||||
let title_bar_inner_height = ctx
|
||||
.fonts(|fonts| title.font_height(fonts, &style))
|
||||
.fonts_mut(|fonts| title.font_height(fonts, &style))
|
||||
.at_least(style.spacing.interact_size.y);
|
||||
let title_bar_inner_height = title_bar_inner_height + window_frame.inner_margin.sum().y;
|
||||
let half_height = (title_bar_inner_height / 2.0).round() as _;
|
||||
|
||||
@@ -641,7 +641,7 @@ impl ContextImpl {
|
||||
// Preload the most common characters for the most common fonts.
|
||||
// This is not very important to do, but may save a few GPU operations.
|
||||
for font_id in self.memory.options.style().text_styles.values() {
|
||||
fonts.lock().fonts.font(font_id).preload_common_characters();
|
||||
fonts.fonts.font(font_id).preload_common_characters();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1060,6 +1060,22 @@ impl Context {
|
||||
})
|
||||
}
|
||||
|
||||
/// Read-write access to [`Fonts`].
|
||||
///
|
||||
/// Not valid until first call to [`Context::run()`].
|
||||
/// That's because since we don't know the proper `pixels_per_point` until then.
|
||||
#[inline]
|
||||
pub fn fonts_mut<R>(&self, reader: impl FnOnce(&mut Fonts) -> R) -> R {
|
||||
self.write(move |ctx| {
|
||||
let pixels_per_point = ctx.pixels_per_point();
|
||||
reader(
|
||||
ctx.fonts
|
||||
.get_mut(&pixels_per_point.into())
|
||||
.expect("No fonts available until first call to Context::run()"),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Read-only access to [`Options`].
|
||||
#[inline]
|
||||
pub fn options<R>(&self, reader: impl FnOnce(&Options) -> R) -> R {
|
||||
@@ -1568,9 +1584,8 @@ impl Context {
|
||||
} = ModifierNames::SYMBOLS;
|
||||
|
||||
let font_id = TextStyle::Body.resolve(&self.style());
|
||||
self.fonts(|f| {
|
||||
let mut lock = f.lock();
|
||||
let font = lock.fonts.font(&font_id);
|
||||
self.fonts_mut(|f| {
|
||||
let font = f.fonts.font(&font_id);
|
||||
font.has_glyphs(alt)
|
||||
&& font.has_glyphs(ctrl)
|
||||
&& font.has_glyphs(shift)
|
||||
@@ -1927,7 +1942,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.fonts.definitions() == &font_definitions {
|
||||
update_fonts = false; // no need to update
|
||||
}
|
||||
}
|
||||
@@ -1955,7 +1970,6 @@ impl Context {
|
||||
self.read(|ctx| {
|
||||
if let Some(current_fonts) = ctx.fonts.get(&pixels_per_point.into()) {
|
||||
if current_fonts
|
||||
.lock()
|
||||
.fonts
|
||||
.definitions()
|
||||
.font_data
|
||||
|
||||
@@ -98,7 +98,7 @@ impl State {
|
||||
{
|
||||
// Paint location to left of `pos`:
|
||||
let location_galley =
|
||||
ctx.fonts(|f| f.layout(location, font_id.clone(), color, f32::INFINITY));
|
||||
ctx.fonts_mut(|f| f.layout(location, font_id.clone(), color, f32::INFINITY));
|
||||
let location_rect =
|
||||
Align2::RIGHT_TOP.anchor_size(pos - 4.0 * Vec2::X, location_galley.size());
|
||||
painter.galley(location_rect.min, location_galley, color);
|
||||
|
||||
@@ -149,6 +149,14 @@ impl Painter {
|
||||
self.ctx.fonts(reader)
|
||||
}
|
||||
|
||||
/// Read-write access to the shared [`Fonts`].
|
||||
///
|
||||
/// See [`Context`] documentation for how locks work.
|
||||
#[inline]
|
||||
pub fn fonts_mut<R>(&self, reader: impl FnOnce(&mut Fonts) -> R) -> R {
|
||||
self.ctx.fonts_mut(reader)
|
||||
}
|
||||
|
||||
/// Where we paint
|
||||
#[inline]
|
||||
pub fn layer_id(&self) -> LayerId {
|
||||
@@ -525,7 +533,7 @@ impl Painter {
|
||||
color: crate::Color32,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
self.fonts(|f| f.layout(text, font_id, color, wrap_width))
|
||||
self.fonts_mut(|f| f.layout(text, font_id, color, wrap_width))
|
||||
}
|
||||
|
||||
/// Will line break at `\n`.
|
||||
@@ -539,7 +547,7 @@ impl Painter {
|
||||
font_id: FontId,
|
||||
color: crate::Color32,
|
||||
) -> Arc<Galley> {
|
||||
self.fonts(|f| f.layout(text, font_id, color, f32::INFINITY))
|
||||
self.fonts_mut(|f| f.layout(text, font_id, color, f32::INFINITY))
|
||||
}
|
||||
|
||||
/// Lay out this text layut job in a galley.
|
||||
@@ -548,7 +556,7 @@ impl Painter {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn layout_job(&self, layout_job: LayoutJob) -> Arc<Galley> {
|
||||
self.fonts(|f| f.layout_job(layout_job))
|
||||
self.fonts_mut(|f| f.layout_job(layout_job))
|
||||
}
|
||||
|
||||
/// Paint text that has already been laid out in a [`Galley`].
|
||||
|
||||
@@ -735,7 +735,7 @@ impl Ui {
|
||||
///
|
||||
/// Returns a value rounded to [`emath::GUI_ROUNDING`].
|
||||
pub fn text_style_height(&self, style: &TextStyle) -> f32 {
|
||||
self.fonts(|f| f.row_height(&style.resolve(self.style())))
|
||||
self.fonts_mut(|f| f.row_height(&style.resolve(self.style())))
|
||||
}
|
||||
|
||||
/// Screen-space rectangle for clipping what we paint in this ui.
|
||||
@@ -852,6 +852,12 @@ impl Ui {
|
||||
pub fn fonts<R>(&self, reader: impl FnOnce(&Fonts) -> R) -> R {
|
||||
self.ctx().fonts(reader)
|
||||
}
|
||||
|
||||
/// Read-write access to [`Fonts`].
|
||||
#[inline]
|
||||
pub fn fonts_mut<R>(&self, reader: impl FnOnce(&mut Fonts) -> R) -> R {
|
||||
self.ctx().fonts_mut(reader)
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -307,7 +307,7 @@ impl RichText {
|
||||
/// Read the font height of the selected text style.
|
||||
///
|
||||
/// Returns a value rounded to [`emath::GUI_ROUNDING`].
|
||||
pub fn font_height(&self, fonts: &epaint::Fonts, style: &Style) -> f32 {
|
||||
pub fn font_height(&self, fonts: &mut epaint::Fonts, style: &Style) -> f32 {
|
||||
let mut font_id = self.text_style.as_ref().map_or_else(
|
||||
|| FontSelection::Default.resolve(style),
|
||||
|text_style| text_style.resolve(style),
|
||||
@@ -676,7 +676,7 @@ impl WidgetText {
|
||||
}
|
||||
|
||||
/// Returns a value rounded to [`emath::GUI_ROUNDING`].
|
||||
pub(crate) fn font_height(&self, fonts: &epaint::Fonts, style: &Style) -> f32 {
|
||||
pub(crate) fn font_height(&self, fonts: &mut epaint::Fonts, style: &Style) -> f32 {
|
||||
match self {
|
||||
Self::Text(_) => fonts.row_height(&FontSelection::Default.resolve(style)),
|
||||
Self::RichText(text) => text.font_height(fonts, style),
|
||||
@@ -762,7 +762,7 @@ impl WidgetText {
|
||||
},
|
||||
);
|
||||
layout_job.wrap = text_wrapping;
|
||||
ctx.fonts(|f| f.layout_job(layout_job))
|
||||
ctx.fonts_mut(|f| f.layout_job(layout_job))
|
||||
}
|
||||
Self::RichText(text) => {
|
||||
let mut layout_job = Arc::unwrap_or_clone(text).into_layout_job(
|
||||
@@ -771,12 +771,12 @@ impl WidgetText {
|
||||
default_valign,
|
||||
);
|
||||
layout_job.wrap = text_wrapping;
|
||||
ctx.fonts(|f| f.layout_job(layout_job))
|
||||
ctx.fonts_mut(|f| f.layout_job(layout_job))
|
||||
}
|
||||
Self::LayoutJob(job) => {
|
||||
let mut job = Arc::unwrap_or_clone(job);
|
||||
job.wrap = text_wrapping;
|
||||
ctx.fonts(|f| f.layout_job(job))
|
||||
ctx.fonts_mut(|f| f.layout_job(job))
|
||||
}
|
||||
Self::Galley(galley) => galley,
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ impl Label {
|
||||
if let Some(first_section) = layout_job.sections.first_mut() {
|
||||
first_section.leading_space = first_row_indentation;
|
||||
}
|
||||
let galley = ui.fonts(|fonts| fonts.layout_job(layout_job));
|
||||
let galley = ui.fonts_mut(|fonts| fonts.layout_job(layout_job));
|
||||
|
||||
let pos = pos2(ui.max_rect().left(), ui.cursor().top());
|
||||
assert!(!galley.rows.is_empty(), "Galleys are never empty");
|
||||
@@ -252,7 +252,7 @@ impl Label {
|
||||
layout_job.justify = ui.layout().horizontal_justify();
|
||||
}
|
||||
|
||||
let galley = ui.fonts(|fonts| fonts.layout_job(layout_job));
|
||||
let galley = ui.fonts_mut(|fonts| fonts.layout_job(layout_job));
|
||||
let (rect, mut response) = ui.allocate_exact_size(galley.size(), sense);
|
||||
response.intrinsic_size = Some(galley.intrinsic_size());
|
||||
let galley_pos = match galley.job.halign {
|
||||
|
||||
@@ -504,7 +504,7 @@ impl TextEdit<'_> {
|
||||
let hint_text_str = hint_text.text().to_owned();
|
||||
|
||||
let font_id = font_selection.resolve(ui.style());
|
||||
let row_height = ui.fonts(|f| f.row_height(&font_id));
|
||||
let row_height = ui.fonts_mut(|f| f.row_height(&font_id));
|
||||
const MIN_WIDTH: f32 = 24.0; // Never make a [`TextEdit`] more narrow than this.
|
||||
let available_width = (ui.available_width() - margin.sum().x).at_least(MIN_WIDTH);
|
||||
let desired_width = desired_width.unwrap_or_else(|| ui.spacing().text_edit_width);
|
||||
@@ -522,7 +522,7 @@ impl TextEdit<'_> {
|
||||
} else {
|
||||
LayoutJob::simple_singleline(text, font_id_clone.clone(), text_color)
|
||||
};
|
||||
ui.fonts(|f| f.layout_job(layout_job))
|
||||
ui.fonts_mut(|f| f.layout_job(layout_job))
|
||||
};
|
||||
|
||||
let layouter = layouter.unwrap_or(&mut default_layouter);
|
||||
|
||||
@@ -238,7 +238,7 @@ impl ColoredText {
|
||||
pub fn ui(&self, ui: &mut egui::Ui) {
|
||||
let mut job = self.0.clone();
|
||||
job.wrap.max_width = ui.available_width();
|
||||
let galley = ui.fonts(|f| f.layout_job(job));
|
||||
let galley = ui.fonts_mut(|f| f.layout_job(job));
|
||||
ui.add(egui::Label::new(galley).selectable(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ impl FrameHistory {
|
||||
));
|
||||
let cpu_usage = to_screen.inverse().transform_pos(pointer_pos).y;
|
||||
let text = format!("{:.1} ms", 1e3 * cpu_usage);
|
||||
shapes.push(ui.fonts(|f| {
|
||||
shapes.push(ui.fonts_mut(|f| {
|
||||
Shape::text(
|
||||
f,
|
||||
pos2(rect.left(), y),
|
||||
|
||||
@@ -165,14 +165,13 @@ 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(
|
||||
let mut fonts = egui::epaint::text::Fonts::new(
|
||||
pixels_per_point,
|
||||
max_texture_side,
|
||||
egui::epaint::AlphaFromCoverage::default(),
|
||||
egui::FontDefinitions::default(),
|
||||
);
|
||||
{
|
||||
let mut locked_fonts = fonts.lock();
|
||||
c.bench_function("text_layout_uncached", |b| {
|
||||
b.iter(|| {
|
||||
use egui::epaint::text::{LayoutJob, layout};
|
||||
@@ -183,7 +182,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
text_color,
|
||||
wrap_width,
|
||||
);
|
||||
layout(&mut locked_fonts.fonts, job.into())
|
||||
layout(&mut fonts.fonts, job.into())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ impl crate::View for CodeEditor {
|
||||
language,
|
||||
);
|
||||
layout_job.wrap.max_width = wrap_width;
|
||||
ui.fonts(|f| f.layout_job(layout_job))
|
||||
ui.fonts_mut(|f| f.layout_job(layout_job))
|
||||
};
|
||||
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
|
||||
@@ -85,7 +85,7 @@ impl CodeExample {
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let font_id = egui::TextStyle::Monospace.resolve(ui.style());
|
||||
let indentation = 2.0 * 4.0 * ui.fonts(|f| f.glyph_width(&font_id, ' '));
|
||||
let indentation = 2.0 * 4.0 * ui.fonts_mut(|f| f.glyph_width(&font_id, ' '));
|
||||
ui.add_space(indentation);
|
||||
|
||||
egui::Grid::new("code_samples")
|
||||
|
||||
@@ -141,9 +141,8 @@ fn char_info_ui(ui: &mut egui::Ui, chr: char, glyph_info: &GlyphInfo, font_id: e
|
||||
}
|
||||
|
||||
fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap<char, GlyphInfo> {
|
||||
ui.fonts(|f| {
|
||||
f.lock()
|
||||
.fonts
|
||||
ui.fonts_mut(|f| {
|
||||
f.fonts
|
||||
.font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters
|
||||
.characters()
|
||||
.iter()
|
||||
|
||||
@@ -213,7 +213,7 @@ fn label_ui(ui: &mut egui::Ui) {
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
// Trick so we don't have to add spaces in the text below:
|
||||
let width = ui.fonts(|f|f.glyph_width(&TextStyle::Body.resolve(ui.style()), ' '));
|
||||
let width = ui.fonts_mut(|f|f.glyph_width(&TextStyle::Body.resolve(ui.style()), ' '));
|
||||
ui.spacing_mut().item_spacing.x = width;
|
||||
|
||||
ui.label(RichText::new("Text can have").color(Color32::from_rgb(110, 255, 110)));
|
||||
@@ -792,7 +792,7 @@ impl TextRotation {
|
||||
|
||||
let start_pos = self.size / 2.0;
|
||||
|
||||
let s = ui.ctx().fonts(|f| {
|
||||
let s = ui.ctx().fonts_mut(|f| {
|
||||
let mut t = egui::Shape::text(
|
||||
f,
|
||||
rect.min + start_pos,
|
||||
|
||||
@@ -191,7 +191,7 @@ fn huge_content_painter(ui: &mut egui::Ui) {
|
||||
ui.add_space(4.0);
|
||||
|
||||
let font_id = TextStyle::Body.resolve(ui.style());
|
||||
let row_height = ui.fonts(|f| f.row_height(&font_id)) + ui.spacing().item_spacing.y;
|
||||
let row_height = ui.fonts_mut(|f| f.row_height(&font_id)) + ui.spacing().item_spacing.y;
|
||||
let num_rows = 10_000;
|
||||
|
||||
ScrollArea::vertical()
|
||||
|
||||
@@ -83,7 +83,7 @@ impl EasyMarkEditor {
|
||||
let mut layouter = |ui: &egui::Ui, easymark: &dyn TextBuffer, wrap_width: f32| {
|
||||
let mut layout_job = highlighter.highlight(ui.style(), easymark.as_str());
|
||||
layout_job.wrap.max_width = wrap_width;
|
||||
ui.fonts(|f| f.layout_job(layout_job))
|
||||
ui.fonts_mut(|f| f.layout_job(layout_job))
|
||||
};
|
||||
|
||||
ui.add(
|
||||
|
||||
@@ -162,7 +162,7 @@ fn bullet_point(ui: &mut Ui, width: f32) -> Response {
|
||||
|
||||
fn numbered_point(ui: &mut Ui, width: f32, number: &str) -> Response {
|
||||
let font_id = TextStyle::Body.resolve(ui.style());
|
||||
let row_height = ui.fonts(|f| f.row_height(&font_id));
|
||||
let row_height = ui.fonts_mut(|f| f.row_height(&font_id));
|
||||
let (rect, response) = ui.allocate_exact_size(vec2(width, row_height), Sense::hover());
|
||||
let text = format!("{number}.");
|
||||
let text_color = ui.visuals().strong_text_color();
|
||||
|
||||
@@ -299,7 +299,7 @@ impl Shape {
|
||||
|
||||
#[expect(clippy::needless_pass_by_value)]
|
||||
pub fn text(
|
||||
fonts: &Fonts,
|
||||
fonts: &mut Fonts,
|
||||
pos: Pos2,
|
||||
anchor: Align2,
|
||||
text: impl ToString,
|
||||
|
||||
@@ -181,7 +181,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn text_bounding_box_under_rotation() {
|
||||
let fonts = Fonts::new(
|
||||
let mut fonts = Fonts::new(
|
||||
1.0,
|
||||
1024,
|
||||
AlphaFromCoverage::default(),
|
||||
@@ -190,7 +190,7 @@ mod tests {
|
||||
let font = FontId::monospace(12.0);
|
||||
|
||||
let mut t = crate::Shape::text(
|
||||
&fonts,
|
||||
&mut fonts,
|
||||
Pos2::ZERO,
|
||||
emath::Align2::CENTER_CENTER,
|
||||
"testing123",
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
AlphaFromCoverage, TextureAtlas,
|
||||
mutex::{Mutex, MutexGuard},
|
||||
mutex::Mutex,
|
||||
text::{
|
||||
Galley, LayoutJob, LayoutSection,
|
||||
font::{Font, FontImpl},
|
||||
@@ -418,8 +418,10 @@ impl FontDefinitions {
|
||||
/// If you are using `egui`, use `egui::Context::set_fonts` and `egui::Context::fonts`.
|
||||
///
|
||||
/// You need to call [`Self::begin_pass`] and [`Self::font_image_delta`] once every frame.
|
||||
#[derive(Clone)]
|
||||
pub struct Fonts(Arc<Mutex<FontsAndCache>>);
|
||||
pub struct Fonts {
|
||||
pub fonts: FontsImpl,
|
||||
galley_cache: GalleyCache,
|
||||
}
|
||||
|
||||
impl Fonts {
|
||||
/// Create a new [`Fonts`] for text layout.
|
||||
@@ -433,7 +435,7 @@ impl Fonts {
|
||||
text_alpha_from_coverage: AlphaFromCoverage,
|
||||
definitions: FontDefinitions,
|
||||
) -> Self {
|
||||
let fonts_and_cache = FontsAndCache {
|
||||
Self {
|
||||
fonts: FontsImpl::new(
|
||||
pixels_per_point,
|
||||
max_texture_side,
|
||||
@@ -441,8 +443,7 @@ impl Fonts {
|
||||
definitions,
|
||||
),
|
||||
galley_cache: Default::default(),
|
||||
};
|
||||
Self(Arc::new(Mutex::new(fonts_and_cache)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Call at the start of each frame with the latest known
|
||||
@@ -453,27 +454,25 @@ impl Fonts {
|
||||
/// This function will react to changes in `pixels_per_point`, `max_texture_side`, and `text_alpha_from_coverage`,
|
||||
/// as well as notice when the font atlas is getting full, and handle that.
|
||||
pub fn begin_pass(
|
||||
&self,
|
||||
&mut self,
|
||||
pixels_per_point: f32,
|
||||
max_texture_side: usize,
|
||||
text_alpha_from_coverage: AlphaFromCoverage,
|
||||
) {
|
||||
let mut fonts_and_cache = self.0.lock();
|
||||
|
||||
let pixels_per_point_changed = fonts_and_cache.fonts.pixels_per_point != pixels_per_point;
|
||||
let max_texture_side_changed = fonts_and_cache.fonts.max_texture_side != max_texture_side;
|
||||
let pixels_per_point_changed = self.fonts.pixels_per_point != pixels_per_point;
|
||||
let max_texture_side_changed = self.fonts.max_texture_side != max_texture_side;
|
||||
let text_alpha_from_coverage_changed =
|
||||
fonts_and_cache.fonts.atlas.lock().text_alpha_from_coverage != text_alpha_from_coverage;
|
||||
let font_atlas_almost_full = fonts_and_cache.fonts.atlas.lock().fill_ratio() > 0.8;
|
||||
self.fonts.atlas.lock().text_alpha_from_coverage != text_alpha_from_coverage;
|
||||
let font_atlas_almost_full = self.fonts.atlas.lock().fill_ratio() > 0.8;
|
||||
let needs_recreate = pixels_per_point_changed
|
||||
|| max_texture_side_changed
|
||||
|| text_alpha_from_coverage_changed
|
||||
|| font_atlas_almost_full;
|
||||
|
||||
if needs_recreate {
|
||||
let definitions = fonts_and_cache.fonts.definitions.clone();
|
||||
let definitions = self.fonts.definitions.clone();
|
||||
|
||||
*fonts_and_cache = FontsAndCache {
|
||||
*self = Self {
|
||||
fonts: FontsImpl::new(
|
||||
pixels_per_point,
|
||||
max_texture_side,
|
||||
@@ -484,83 +483,70 @@ impl Fonts {
|
||||
};
|
||||
}
|
||||
|
||||
fonts_and_cache.galley_cache.flush_cache();
|
||||
self.galley_cache.flush_cache();
|
||||
}
|
||||
|
||||
/// Call at the end of each frame (before painting) to get the change to the font texture since last call.
|
||||
pub fn font_image_delta(&self) -> Option<crate::ImageDelta> {
|
||||
self.lock().fonts.atlas.lock().take_delta()
|
||||
}
|
||||
|
||||
/// Access the underlying [`FontsAndCache`].
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn lock(&self) -> MutexGuard<'_, FontsAndCache> {
|
||||
self.0.lock()
|
||||
self.fonts.atlas.lock().take_delta()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pixels_per_point(&self) -> f32 {
|
||||
self.lock().fonts.pixels_per_point
|
||||
self.fonts.pixels_per_point
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max_texture_side(&self) -> usize {
|
||||
self.lock().fonts.max_texture_side
|
||||
self.fonts.max_texture_side
|
||||
}
|
||||
|
||||
/// The font atlas.
|
||||
/// Pass this to [`crate::Tessellator`].
|
||||
pub fn texture_atlas(&self) -> Arc<Mutex<TextureAtlas>> {
|
||||
self.lock().fonts.atlas.clone()
|
||||
self.fonts.atlas.clone()
|
||||
}
|
||||
|
||||
/// The full font atlas image.
|
||||
#[inline]
|
||||
pub fn image(&self) -> crate::ColorImage {
|
||||
self.lock().fonts.atlas.lock().image().clone()
|
||||
self.fonts.atlas.lock().image().clone()
|
||||
}
|
||||
|
||||
/// Current size of the font image.
|
||||
/// Pass this to [`crate::Tessellator`].
|
||||
pub fn font_image_size(&self) -> [usize; 2] {
|
||||
self.lock().fonts.atlas.lock().size()
|
||||
self.fonts.atlas.lock().size()
|
||||
}
|
||||
|
||||
/// Width of this character in points.
|
||||
#[inline]
|
||||
pub fn glyph_width(&self, font_id: &FontId, c: char) -> f32 {
|
||||
self.lock().fonts.glyph_width(font_id, c)
|
||||
pub fn glyph_width(&mut self, font_id: &FontId, c: char) -> f32 {
|
||||
self.fonts.glyph_width(font_id, c)
|
||||
}
|
||||
|
||||
/// Can we display this glyph?
|
||||
#[inline]
|
||||
pub fn has_glyph(&self, font_id: &FontId, c: char) -> bool {
|
||||
self.lock().fonts.has_glyph(font_id, c)
|
||||
pub fn has_glyph(&mut self, font_id: &FontId, c: char) -> bool {
|
||||
self.fonts.has_glyph(font_id, c)
|
||||
}
|
||||
|
||||
/// Can we display all the glyphs in this text?
|
||||
pub fn has_glyphs(&self, font_id: &FontId, s: &str) -> bool {
|
||||
self.lock().fonts.has_glyphs(font_id, s)
|
||||
pub fn has_glyphs(&mut self, font_id: &FontId, s: &str) -> bool {
|
||||
self.fonts.has_glyphs(font_id, s)
|
||||
}
|
||||
|
||||
/// Height of one row of text in points.
|
||||
///
|
||||
/// Returns a value rounded to [`emath::GUI_ROUNDING`].
|
||||
#[inline]
|
||||
pub fn row_height(&self, font_id: &FontId) -> f32 {
|
||||
self.lock().fonts.row_height(font_id)
|
||||
pub fn row_height(&mut self, font_id: &FontId) -> f32 {
|
||||
self.fonts.row_height(font_id)
|
||||
}
|
||||
|
||||
/// List of all known font families.
|
||||
pub fn families(&self) -> Vec<FontFamily> {
|
||||
self.lock()
|
||||
.fonts
|
||||
.definitions
|
||||
.families
|
||||
.keys()
|
||||
.cloned()
|
||||
.collect()
|
||||
self.fonts.definitions.families.keys().cloned().collect()
|
||||
}
|
||||
|
||||
/// Layout some text.
|
||||
@@ -571,12 +557,14 @@ impl Fonts {
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
#[inline]
|
||||
pub fn layout_job(&self, job: LayoutJob) -> Arc<Galley> {
|
||||
self.lock().layout_job(job)
|
||||
pub fn layout_job(&mut self, job: LayoutJob) -> Arc<Galley> {
|
||||
let allow_split_paragraphs = true; // Optimization for editing text with many paragraphs.
|
||||
self.galley_cache
|
||||
.layout(&mut self.fonts, job, allow_split_paragraphs)
|
||||
}
|
||||
|
||||
pub fn num_galleys_in_cache(&self) -> usize {
|
||||
self.lock().galley_cache.num_galleys_in_cache()
|
||||
self.galley_cache.num_galleys_in_cache()
|
||||
}
|
||||
|
||||
/// How full is the font atlas?
|
||||
@@ -584,14 +572,14 @@ impl Fonts {
|
||||
/// This increases as new fonts and/or glyphs are used,
|
||||
/// but can also decrease in a call to [`Self::begin_pass`].
|
||||
pub fn font_atlas_fill_ratio(&self) -> f32 {
|
||||
self.lock().fonts.atlas.lock().fill_ratio()
|
||||
self.fonts.atlas.lock().fill_ratio()
|
||||
}
|
||||
|
||||
/// 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,
|
||||
&mut self,
|
||||
text: String,
|
||||
font_id: FontId,
|
||||
color: crate::Color32,
|
||||
@@ -605,7 +593,7 @@ impl Fonts {
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_no_wrap(
|
||||
&self,
|
||||
&mut self,
|
||||
text: String,
|
||||
font_id: FontId,
|
||||
color: crate::Color32,
|
||||
@@ -618,7 +606,7 @@ impl Fonts {
|
||||
///
|
||||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_delayed_color(
|
||||
&self,
|
||||
&mut self,
|
||||
text: String,
|
||||
font_id: FontId,
|
||||
wrap_width: f32,
|
||||
@@ -629,19 +617,6 @@ impl Fonts {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
pub struct FontsAndCache {
|
||||
pub fonts: FontsImpl,
|
||||
galley_cache: GalleyCache,
|
||||
}
|
||||
|
||||
impl FontsAndCache {
|
||||
fn layout_job(&mut self, job: LayoutJob) -> Arc<Galley> {
|
||||
let allow_split_paragraphs = true; // Optimization for editing text with many paragraphs.
|
||||
self.galley_cache
|
||||
.layout(&mut self.fonts, job, allow_split_paragraphs)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// The collection of fonts used by `epaint`.
|
||||
|
||||
@@ -184,7 +184,7 @@ impl LayoutJob {
|
||||
/// The height of the tallest font used in the job.
|
||||
///
|
||||
/// Returns a value rounded to [`emath::GUI_ROUNDING`].
|
||||
pub fn font_height(&self, fonts: &crate::Fonts) -> f32 {
|
||||
pub fn font_height(&self, fonts: &mut crate::Fonts) -> f32 {
|
||||
let mut max_height = 0.0_f32;
|
||||
for section in &self.sections {
|
||||
max_height = max_height.max(fonts.row_height(§ion.format.font_id));
|
||||
|
||||
Reference in New Issue
Block a user