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 {
|
||||
id: Id,
|
||||
title_label: Label,
|
||||
title_galley: Galley,
|
||||
title_galley: std::sync::Arc<Galley>,
|
||||
min_rect: Rect,
|
||||
rect: Rect,
|
||||
}
|
||||
|
|
|
@ -302,14 +302,14 @@ impl Painter {
|
|||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
pub fn galley_with_italics(
|
||||
&self,
|
||||
pos: Pos2,
|
||||
galley: Galley,
|
||||
galley: std::sync::Arc<Galley>,
|
||||
color: Color32,
|
||||
fake_italics: bool,
|
||||
) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::*;
|
||||
use epaint::Galley;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Static text.
|
||||
///
|
||||
|
@ -143,12 +144,12 @@ 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();
|
||||
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 wrap_width = if self.should_wrap(ui) {
|
||||
max_width
|
||||
|
@ -174,11 +175,11 @@ impl Label {
|
|||
// TODO: a paint method for painting anywhere in a ui.
|
||||
// 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)
|
||||
}
|
||||
|
||||
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 {
|
||||
mut background_color,
|
||||
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 {
|
||||
// Hacky McHackface strikes again:
|
||||
let dy = if self.raised {
|
||||
|
@ -269,8 +275,10 @@ impl Label {
|
|||
// normal_text_heigth - font_height // align bottom
|
||||
};
|
||||
|
||||
for row in &mut galley.rows {
|
||||
row.translate_y(dy);
|
||||
if dy != 0.0 {
|
||||
for row in &mut Arc::make_mut(&mut galley).rows {
|
||||
row.translate_y(dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
galley
|
||||
|
@ -293,12 +301,13 @@ impl Widget for Label {
|
|||
let first_row_indentation = max_width - ui.available_size_before_wrap().x;
|
||||
|
||||
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,
|
||||
self.text.clone(),
|
||||
first_row_indentation,
|
||||
max_width,
|
||||
);
|
||||
let mut galley: Galley = (*galley).clone();
|
||||
|
||||
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 mut response = ui.allocate_rect(rect, sense);
|
||||
|
|
|
@ -75,9 +75,12 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
egui::FontDefinitions::default(),
|
||||
);
|
||||
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))
|
||||
});
|
||||
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 mut tessellator = egui::epaint::Tessellator::from_options(Default::default());
|
||||
|
|
|
@ -43,7 +43,7 @@ pub enum Shape {
|
|||
/// Top left corner of the first character..
|
||||
pos: Pos2,
|
||||
/// The layed out text.
|
||||
galley: Galley,
|
||||
galley: std::sync::Arc<Galley>,
|
||||
/// Text color (foreground).
|
||||
color: Color32,
|
||||
/// If true, tilt the letters for a hacky italics effect.
|
||||
|
|
|
@ -278,7 +278,7 @@ impl Fonts {
|
|||
|
||||
/// Always returns at least one row.
|
||||
/// 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)
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ impl Fonts {
|
|||
///
|
||||
/// Most often you probably want `\n` to produce a new row,
|
||||
/// 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.fonts,
|
||||
LayoutJob {
|
||||
|
@ -306,7 +306,7 @@ impl Fonts {
|
|||
text_style: TextStyle,
|
||||
text: String,
|
||||
max_width_in_points: f32,
|
||||
) -> Galley {
|
||||
) -> Arc<Galley> {
|
||||
self.layout_multiline_with_indentation_and_max_width(
|
||||
text_style,
|
||||
text,
|
||||
|
@ -324,7 +324,7 @@ impl Fonts {
|
|||
text: String,
|
||||
first_row_indentation: f32,
|
||||
max_width_in_points: f32,
|
||||
) -> Galley {
|
||||
) -> Arc<Galley> {
|
||||
self.galley_cache.lock().layout(
|
||||
&self.fonts,
|
||||
LayoutJob {
|
||||
|
@ -377,7 +377,7 @@ struct LayoutJob {
|
|||
struct CachedGalley {
|
||||
/// When it was last used
|
||||
last_used: u32,
|
||||
galley: Galley, // TODO: use an Arc instead!
|
||||
galley: Arc<Galley>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -388,7 +388,7 @@ struct 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) {
|
||||
cached.last_used = self.generation;
|
||||
cached.galley.clone()
|
||||
|
@ -410,6 +410,7 @@ impl GalleyCache {
|
|||
max_width_in_points.into_inner(),
|
||||
),
|
||||
};
|
||||
let galley = Arc::new(galley);
|
||||
self.cache.insert(
|
||||
job,
|
||||
CachedGalley {
|
||||
|
|
Loading…
Reference in a new issue