Pass around Arc<Galley> to avoid copying a lot of data
This commit is contained in:
parent
94baf98eab
commit
1c60dc8d66
6 changed files with 33 additions and 20 deletions
|
@ -673,7 +673,7 @@ fn paint_frame_interaction(
|
||||||
struct TitleBar {
|
struct TitleBar {
|
||||||
id: Id,
|
id: Id,
|
||||||
title_label: Label,
|
title_label: Label,
|
||||||
title_galley: Galley,
|
title_galley: std::sync::Arc<Galley>,
|
||||||
min_rect: Rect,
|
min_rect: Rect,
|
||||||
rect: Rect,
|
rect: Rect,
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,14 +302,14 @@ impl Painter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paint text that has already been layed out in a `Galley`.
|
/// Paint text that has already been layed out in a `Galley`.
|
||||||
pub fn galley(&self, pos: Pos2, galley: Galley, color: Color32) {
|
pub fn galley(&self, pos: Pos2, galley: std::sync::Arc<Galley>, color: Color32) {
|
||||||
self.galley_with_italics(pos, galley, color, false)
|
self.galley_with_italics(pos, galley, color, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn galley_with_italics(
|
pub fn galley_with_italics(
|
||||||
&self,
|
&self,
|
||||||
pos: Pos2,
|
pos: Pos2,
|
||||||
galley: Galley,
|
galley: std::sync::Arc<Galley>,
|
||||||
color: Color32,
|
color: Color32,
|
||||||
fake_italics: bool,
|
fake_italics: bool,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use epaint::Galley;
|
use epaint::Galley;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Static text.
|
/// Static text.
|
||||||
///
|
///
|
||||||
|
@ -143,12 +144,12 @@ impl Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Label {
|
impl Label {
|
||||||
pub fn layout(&self, ui: &Ui) -> Galley {
|
pub fn layout(&self, ui: &Ui) -> Arc<Galley> {
|
||||||
let max_width = ui.available_width();
|
let max_width = ui.available_width();
|
||||||
self.layout_width(ui, max_width)
|
self.layout_width(ui, max_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_width(&self, ui: &Ui, max_width: f32) -> Galley {
|
pub fn layout_width(&self, ui: &Ui, max_width: f32) -> Arc<Galley> {
|
||||||
let text_style = self.text_style_or_default(ui.style());
|
let text_style = self.text_style_or_default(ui.style());
|
||||||
let wrap_width = if self.should_wrap(ui) {
|
let wrap_width = if self.should_wrap(ui) {
|
||||||
max_width
|
max_width
|
||||||
|
@ -174,11 +175,11 @@ impl Label {
|
||||||
// TODO: a paint method for painting anywhere in a ui.
|
// TODO: a paint method for painting anywhere in a ui.
|
||||||
// This should be the easiest method of putting text anywhere.
|
// This should be the easiest method of putting text anywhere.
|
||||||
|
|
||||||
pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: Galley) {
|
pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: Arc<Galley>) {
|
||||||
self.paint_galley_focus(ui, pos, galley, false)
|
self.paint_galley_focus(ui, pos, galley, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_galley_focus(&self, ui: &mut Ui, pos: Pos2, galley: Galley, focus: bool) {
|
fn paint_galley_focus(&self, ui: &mut Ui, pos: Pos2, galley: Arc<Galley>, focus: bool) {
|
||||||
let Self {
|
let Self {
|
||||||
mut background_color,
|
mut background_color,
|
||||||
code,
|
code,
|
||||||
|
@ -256,7 +257,12 @@ impl Label {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valign_galley(&self, ui: &Ui, text_style: TextStyle, mut galley: Galley) -> Galley {
|
fn valign_galley(
|
||||||
|
&self,
|
||||||
|
ui: &Ui,
|
||||||
|
text_style: TextStyle,
|
||||||
|
mut galley: Arc<Galley>,
|
||||||
|
) -> Arc<Galley> {
|
||||||
if text_style == TextStyle::Small {
|
if text_style == TextStyle::Small {
|
||||||
// Hacky McHackface strikes again:
|
// Hacky McHackface strikes again:
|
||||||
let dy = if self.raised {
|
let dy = if self.raised {
|
||||||
|
@ -269,8 +275,10 @@ impl Label {
|
||||||
// normal_text_heigth - font_height // align bottom
|
// normal_text_heigth - font_height // align bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
for row in &mut galley.rows {
|
if dy != 0.0 {
|
||||||
row.translate_y(dy);
|
for row in &mut Arc::make_mut(&mut galley).rows {
|
||||||
|
row.translate_y(dy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
galley
|
galley
|
||||||
|
@ -293,12 +301,13 @@ impl Widget for Label {
|
||||||
let first_row_indentation = max_width - ui.available_size_before_wrap().x;
|
let first_row_indentation = max_width - ui.available_size_before_wrap().x;
|
||||||
|
|
||||||
let text_style = self.text_style_or_default(ui.style());
|
let text_style = self.text_style_or_default(ui.style());
|
||||||
let mut galley = ui.fonts().layout_multiline_with_indentation_and_max_width(
|
let galley = ui.fonts().layout_multiline_with_indentation_and_max_width(
|
||||||
text_style,
|
text_style,
|
||||||
self.text.clone(),
|
self.text.clone(),
|
||||||
first_row_indentation,
|
first_row_indentation,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
let mut galley: Galley = (*galley).clone();
|
||||||
|
|
||||||
let pos = pos2(ui.max_rect().left(), ui.cursor().top());
|
let pos = pos2(ui.max_rect().left(), ui.cursor().top());
|
||||||
|
|
||||||
|
@ -321,7 +330,7 @@ impl Widget for Label {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let galley = self.valign_galley(ui, text_style, galley);
|
let galley = self.valign_galley(ui, text_style, Arc::new(galley));
|
||||||
|
|
||||||
let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y));
|
let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y));
|
||||||
let mut response = ui.allocate_rect(rect, sense);
|
let mut response = ui.allocate_rect(rect, sense);
|
||||||
|
|
|
@ -75,9 +75,12 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
egui::FontDefinitions::default(),
|
egui::FontDefinitions::default(),
|
||||||
);
|
);
|
||||||
let font = &fonts[text_style];
|
let font = &fonts[text_style];
|
||||||
c.bench_function("text layout", |b| {
|
c.bench_function("text layout (uncached)", |b| {
|
||||||
b.iter(|| font.layout_multiline(LOREM_IPSUM_LONG.to_owned(), wrap_width))
|
b.iter(|| font.layout_multiline(LOREM_IPSUM_LONG.to_owned(), wrap_width))
|
||||||
});
|
});
|
||||||
|
c.bench_function("text layout (cached)", |b| {
|
||||||
|
b.iter(|| fonts.layout_multiline(text_style, LOREM_IPSUM_LONG.to_owned(), wrap_width))
|
||||||
|
});
|
||||||
|
|
||||||
let galley = font.layout_multiline(LOREM_IPSUM_LONG.to_owned(), wrap_width);
|
let galley = font.layout_multiline(LOREM_IPSUM_LONG.to_owned(), wrap_width);
|
||||||
let mut tessellator = egui::epaint::Tessellator::from_options(Default::default());
|
let mut tessellator = egui::epaint::Tessellator::from_options(Default::default());
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub enum Shape {
|
||||||
/// Top left corner of the first character..
|
/// Top left corner of the first character..
|
||||||
pos: Pos2,
|
pos: Pos2,
|
||||||
/// The layed out text.
|
/// The layed out text.
|
||||||
galley: Galley,
|
galley: std::sync::Arc<Galley>,
|
||||||
/// Text color (foreground).
|
/// Text color (foreground).
|
||||||
color: Color32,
|
color: Color32,
|
||||||
/// If true, tilt the letters for a hacky italics effect.
|
/// If true, tilt the letters for a hacky italics effect.
|
||||||
|
|
|
@ -278,7 +278,7 @@ impl Fonts {
|
||||||
|
|
||||||
/// Always returns at least one row.
|
/// Always returns at least one row.
|
||||||
/// Will line break at `\n`.
|
/// Will line break at `\n`.
|
||||||
pub fn layout_no_wrap(&self, text_style: TextStyle, text: String) -> Galley {
|
pub fn layout_no_wrap(&self, text_style: TextStyle, text: String) -> Arc<Galley> {
|
||||||
self.layout_multiline(text_style, text, f32::INFINITY)
|
self.layout_multiline(text_style, text, f32::INFINITY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ impl Fonts {
|
||||||
///
|
///
|
||||||
/// Most often you probably want `\n` to produce a new row,
|
/// Most often you probably want `\n` to produce a new row,
|
||||||
/// and so [`Self::layout_no_wrap`] may be a better choice.
|
/// and so [`Self::layout_no_wrap`] may be a better choice.
|
||||||
pub fn layout_single_line(&self, text_style: TextStyle, text: String) -> Galley {
|
pub fn layout_single_line(&self, text_style: TextStyle, text: String) -> Arc<Galley> {
|
||||||
self.galley_cache.lock().layout(
|
self.galley_cache.lock().layout(
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
LayoutJob {
|
LayoutJob {
|
||||||
|
@ -306,7 +306,7 @@ impl Fonts {
|
||||||
text_style: TextStyle,
|
text_style: TextStyle,
|
||||||
text: String,
|
text: String,
|
||||||
max_width_in_points: f32,
|
max_width_in_points: f32,
|
||||||
) -> Galley {
|
) -> Arc<Galley> {
|
||||||
self.layout_multiline_with_indentation_and_max_width(
|
self.layout_multiline_with_indentation_and_max_width(
|
||||||
text_style,
|
text_style,
|
||||||
text,
|
text,
|
||||||
|
@ -324,7 +324,7 @@ impl Fonts {
|
||||||
text: String,
|
text: String,
|
||||||
first_row_indentation: f32,
|
first_row_indentation: f32,
|
||||||
max_width_in_points: f32,
|
max_width_in_points: f32,
|
||||||
) -> Galley {
|
) -> Arc<Galley> {
|
||||||
self.galley_cache.lock().layout(
|
self.galley_cache.lock().layout(
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
LayoutJob {
|
LayoutJob {
|
||||||
|
@ -377,7 +377,7 @@ struct LayoutJob {
|
||||||
struct CachedGalley {
|
struct CachedGalley {
|
||||||
/// When it was last used
|
/// When it was last used
|
||||||
last_used: u32,
|
last_used: u32,
|
||||||
galley: Galley, // TODO: use an Arc instead!
|
galley: Arc<Galley>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -388,7 +388,7 @@ struct GalleyCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GalleyCache {
|
impl GalleyCache {
|
||||||
fn layout(&mut self, fonts: &BTreeMap<TextStyle, Font>, job: LayoutJob) -> Galley {
|
fn layout(&mut self, fonts: &BTreeMap<TextStyle, Font>, job: LayoutJob) -> Arc<Galley> {
|
||||||
if let Some(cached) = self.cache.get_mut(&job) {
|
if let Some(cached) = self.cache.get_mut(&job) {
|
||||||
cached.last_used = self.generation;
|
cached.last_used = self.generation;
|
||||||
cached.galley.clone()
|
cached.galley.clone()
|
||||||
|
@ -410,6 +410,7 @@ impl GalleyCache {
|
||||||
max_width_in_points.into_inner(),
|
max_width_in_points.into_inner(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
let galley = Arc::new(galley);
|
||||||
self.cache.insert(
|
self.cache.insert(
|
||||||
job,
|
job,
|
||||||
CachedGalley {
|
CachedGalley {
|
||||||
|
|
Loading…
Reference in a new issue