From 3ae3c9c8dbc89753e2772096d58b64cdb489af95 Mon Sep 17 00:00:00 2001 From: lucasmerlin Date: Tue, 29 Apr 2025 16:28:38 +0200 Subject: [PATCH 01/10] Make WidgetText much smaller --- crates/egui/src/widget_text.rs | 173 +++++++++++++++------------ crates/egui/src/widgets/label.rs | 14 +-- crates/egui_demo_app/src/wrap_app.rs | 3 +- 3 files changed, 108 insertions(+), 82 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index e66cb1bc803f..9192720b6eeb 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -488,7 +488,9 @@ impl RichText { /// which will be replaced with a color chosen by the widget that paints the text. #[derive(Clone)] pub enum WidgetText { - RichText(RichText), + Text(String), + + RichText(Arc), /// Use this [`LayoutJob`] when laying out the text. /// @@ -502,7 +504,7 @@ pub enum WidgetText { /// /// You can color the text however you want, or use [`Color32::PLACEHOLDER`] /// which will be replaced with a color chosen by the widget that paints the text. - LayoutJob(LayoutJob), + LayoutJob(Arc), /// Use exactly this galley when painting the text. /// @@ -513,7 +515,7 @@ pub enum WidgetText { impl Default for WidgetText { fn default() -> Self { - Self::RichText(RichText::default()) + Self::Text(String::new()) } } @@ -521,6 +523,7 @@ impl WidgetText { #[inline] pub fn is_empty(&self) -> bool { match self { + Self::Text(text) => text.is_empty(), Self::RichText(text) => text.is_empty(), Self::LayoutJob(job) => job.is_empty(), Self::Galley(galley) => galley.is_empty(), @@ -530,21 +533,39 @@ impl WidgetText { #[inline] pub fn text(&self) -> &str { match self { + Self::Text(text) => text, Self::RichText(text) => text.text(), Self::LayoutJob(job) => &job.text, Self::Galley(galley) => galley.text(), } } + /// Map the contents based on the provided closure. + /// + /// - [`Self::Text`] => convert to [`RichText`] and call f + /// - [`Self::RichText`] => call f + /// - else do nothing + fn map_rich_text(self, f: F) -> Self + where + F: FnOnce(RichText) -> RichText, + { + match self { + WidgetText::Text(text) => f(RichText::new(text)).into(), + WidgetText::RichText(mut text) => { + let a = Arc::make_mut(&mut text); + *a = f(std::mem::take(&mut *a)); + Self::RichText(text) + } + other => other, + } + } + /// Override the [`TextStyle`] if, and only if, this is a [`RichText`]. /// /// Prefer using [`RichText`] directly! #[inline] pub fn text_style(self, text_style: TextStyle) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.text_style(text_style)), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.text_style(text_style)) } /// Set the [`TextStyle`] unless it has already been set @@ -552,10 +573,7 @@ impl WidgetText { /// Prefer using [`RichText`] directly! #[inline] pub fn fallback_text_style(self, text_style: TextStyle) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.fallback_text_style(text_style)), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.fallback_text_style(text_style)) } /// Override text color if, and only if, this is a [`RichText`]. @@ -563,111 +581,85 @@ impl WidgetText { /// Prefer using [`RichText`] directly! #[inline] pub fn color(self, color: impl Into) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.color(color)), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.color(color)) } /// Prefer using [`RichText`] directly! + #[inline] pub fn heading(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.heading()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.heading()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn monospace(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.monospace()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.monospace()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn code(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.code()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.code()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn strong(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.strong()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.strong()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn weak(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.weak()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.weak()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn underline(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.underline()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.underline()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn strikethrough(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.strikethrough()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.strikethrough()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn italics(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.italics()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.italics()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn small(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.small()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.small()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn small_raised(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.small_raised()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.small_raised()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn raised(self) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.raised()), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.raised()) } /// Prefer using [`RichText`] directly! + #[inline] pub fn background_color(self, background_color: impl Into) -> Self { - match self { - Self::RichText(text) => Self::RichText(text.background_color(background_color)), - Self::LayoutJob(_) | Self::Galley(_) => self, - } + self.map_rich_text(|text| text.background_color(background_color)) } /// Returns a value rounded to [`emath::GUI_ROUNDING`]. pub(crate) fn font_height(&self, fonts: &epaint::Fonts, style: &Style) -> f32 { match self { + Self::Text(_) => fonts.row_height(&FontSelection::Default.resolve(style)), Self::RichText(text) => text.font_height(fonts, style), Self::LayoutJob(job) => job.font_height(fonts), Self::Galley(galley) => { @@ -685,11 +677,19 @@ impl WidgetText { style: &Style, fallback_font: FontSelection, default_valign: Align, - ) -> LayoutJob { + ) -> Arc { match self { - Self::RichText(text) => text.into_layout_job(style, fallback_font, default_valign), + Self::Text(text) => Arc::new(LayoutJob::single_section( + text, + crate::text::TextFormat::default(), + )), + Self::RichText(text) => Arc::new(Arc::unwrap_or_clone(text).into_layout_job( + style, + fallback_font, + default_valign, + )), Self::LayoutJob(job) => job, - Self::Galley(galley) => (*galley.job).clone(), + Self::Galley(galley) => galley.job.clone(), } } @@ -721,12 +721,23 @@ impl WidgetText { default_valign: Align, ) -> Arc { match self { + Self::Text(text) => { + let mut layout_job = + LayoutJob::single_section(text, crate::text::TextFormat::default()); + layout_job.wrap = text_wrapping; + ctx.fonts(|f| f.layout_job(layout_job)) + } Self::RichText(text) => { - let mut layout_job = text.into_layout_job(style, fallback_font, default_valign); + let mut layout_job = Arc::unwrap_or_clone(text).into_layout_job( + style, + fallback_font, + default_valign, + ); layout_job.wrap = text_wrapping; ctx.fonts(|f| f.layout_job(layout_job)) } - Self::LayoutJob(mut job) => { + Self::LayoutJob(job) => { + let mut job = Arc::unwrap_or_clone(job); job.wrap = text_wrapping; ctx.fonts(|f| f.layout_job(job)) } @@ -738,48 +749,55 @@ impl WidgetText { impl From<&str> for WidgetText { #[inline] fn from(text: &str) -> Self { - Self::RichText(RichText::new(text)) + Self::Text(text.to_owned()) } } impl From<&String> for WidgetText { #[inline] fn from(text: &String) -> Self { - Self::RichText(RichText::new(text)) + Self::Text(text.clone()) } } impl From for WidgetText { #[inline] fn from(text: String) -> Self { - Self::RichText(RichText::new(text)) + Self::Text(text) } } impl From<&Box> for WidgetText { #[inline] fn from(text: &Box) -> Self { - Self::RichText(RichText::new(text.clone())) + Self::Text(text.to_string()) } } impl From> for WidgetText { #[inline] fn from(text: Box) -> Self { - Self::RichText(RichText::new(text)) + Self::Text(text.into()) } } impl From> for WidgetText { #[inline] fn from(text: Cow<'_, str>) -> Self { - Self::RichText(RichText::new(text)) + Self::Text(text.into_owned()) } } impl From for WidgetText { #[inline] fn from(rich_text: RichText) -> Self { + Self::RichText(Arc::new(rich_text)) + } +} + +impl From> for WidgetText { + #[inline] + fn from(rich_text: Arc) -> Self { Self::RichText(rich_text) } } @@ -787,6 +805,13 @@ impl From for WidgetText { impl From for WidgetText { #[inline] fn from(layout_job: LayoutJob) -> Self { + Self::LayoutJob(Arc::new(layout_job)) + } +} + +impl From> for WidgetText { + #[inline] + fn from(layout_job: Arc) -> Self { Self::LayoutJob(layout_job) } } diff --git a/crates/egui/src/widgets/label.rs b/crates/egui/src/widgets/label.rs index 3656af92bfd5..d90bdf963cc7 100644 --- a/crates/egui/src/widgets/label.rs +++ b/crates/egui/src/widgets/label.rs @@ -1,12 +1,10 @@ use std::sync::Arc; use crate::{ - epaint, pos2, text_selection, Align, Direction, FontSelection, Galley, Pos2, Response, Sense, - Stroke, TextWrapMode, Ui, Widget, WidgetInfo, WidgetText, WidgetType, + epaint, pos2, text_selection::LabelSelectionState, Align, Direction, FontSelection, Galley, + Pos2, Response, Sense, Stroke, TextWrapMode, Ui, Widget, WidgetInfo, WidgetText, WidgetType, }; -use self::text_selection::LabelSelectionState; - /// Static text. /// /// Usually it is more convenient to use [`Ui::label`]. @@ -182,9 +180,11 @@ impl Label { } let valign = ui.text_valign(); - let mut layout_job = self - .text - .into_layout_job(ui.style(), FontSelection::Default, valign); + let mut layout_job = Arc::unwrap_or_clone(self.text.into_layout_job( + ui.style(), + FontSelection::Default, + valign, + )); let available_width = ui.available_width(); diff --git a/crates/egui_demo_app/src/wrap_app.rs b/crates/egui_demo_app/src/wrap_app.rs index ea5fbfaba881..a8c39188897d 100644 --- a/crates/egui_demo_app/src/wrap_app.rs +++ b/crates/egui_demo_app/src/wrap_app.rs @@ -5,6 +5,7 @@ use eframe::glow; #[cfg(target_arch = "wasm32")] use core::any::Any; +use egui::WidgetText; #[derive(Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] @@ -134,7 +135,7 @@ impl std::fmt::Display for Anchor { impl From for egui::WidgetText { fn from(value: Anchor) -> Self { - Self::RichText(egui::RichText::new(value.to_string())) + WidgetText::from(value.to_string()) } } From a1941b5029214d575e7e5e59ef3c25861e815603 Mon Sep 17 00:00:00 2001 From: lucasmerlin Date: Wed, 30 Apr 2025 12:10:16 +0200 Subject: [PATCH 02/10] Add test --- crates/egui/src/widget_text.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 9192720b6eeb..af039be25283 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -822,3 +822,13 @@ impl From> for WidgetText { Self::Galley(galley) } } + +#[cfg(test)] +mod tests { + use crate::WidgetText; + + #[test] + fn ensure_small_widget_text() { + assert_eq!(size_of::(), size_of::()); + } +} From d95a21a5063358a6f40da58c9a29d2568eaa9e1d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 11:22:03 +0200 Subject: [PATCH 03/10] clippy fix --- crates/egui_demo_app/src/wrap_app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/egui_demo_app/src/wrap_app.rs b/crates/egui_demo_app/src/wrap_app.rs index a8c39188897d..2b160cd72505 100644 --- a/crates/egui_demo_app/src/wrap_app.rs +++ b/crates/egui_demo_app/src/wrap_app.rs @@ -135,7 +135,7 @@ impl std::fmt::Display for Anchor { impl From for egui::WidgetText { fn from(value: Anchor) -> Self { - WidgetText::from(value.to_string()) + Self::from(value.to_string()) } } From 0dd8b5e4c20c40ef35ac0769a4d03fc1ca2d8d84 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 11:25:57 +0200 Subject: [PATCH 04/10] More clippy fixes --- crates/egui/src/widget_text.rs | 4 ++-- crates/egui_demo_app/src/wrap_app.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index af039be25283..13050fd79d85 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -550,8 +550,8 @@ impl WidgetText { F: FnOnce(RichText) -> RichText, { match self { - WidgetText::Text(text) => f(RichText::new(text)).into(), - WidgetText::RichText(mut text) => { + Self::Text(text) => f(RichText::new(text)).into(), + Self::RichText(mut text) => { let a = Arc::make_mut(&mut text); *a = f(std::mem::take(&mut *a)); Self::RichText(text) diff --git a/crates/egui_demo_app/src/wrap_app.rs b/crates/egui_demo_app/src/wrap_app.rs index 2b160cd72505..3775d93d211f 100644 --- a/crates/egui_demo_app/src/wrap_app.rs +++ b/crates/egui_demo_app/src/wrap_app.rs @@ -5,7 +5,6 @@ use eframe::glow; #[cfg(target_arch = "wasm32")] use core::any::Any; -use egui::WidgetText; #[derive(Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] From b375687cbbba4c18077672b9497814ecccdfaebb Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 11:28:29 +0200 Subject: [PATCH 05/10] Add motivational docstring --- crates/egui/src/widget_text.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 13050fd79d85..b2688c30f6c3 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -488,8 +488,15 @@ impl RichText { /// which will be replaced with a color chosen by the widget that paints the text. #[derive(Clone)] pub enum WidgetText { + /// Plain unstyled text. + /// + /// We have this as a special case, as it is the common-case, + /// and it uses less memory than [`Self::RichText`]. Text(String), + /// Text and optional style choices for it. + /// + /// Prefer [`Self::Text`] if there is no styling, as it will be faster. RichText(Arc), /// Use this [`LayoutJob`] when laying out the text. From 0ec14d38214bd88d96704ad3f095098b7f6a98a0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 12:04:36 +0200 Subject: [PATCH 06/10] Use the correct text style --- crates/egui/src/widget_text.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index b2688c30f6c3..8a08a7042798 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -666,7 +666,7 @@ impl WidgetText { /// Returns a value rounded to [`emath::GUI_ROUNDING`]. pub(crate) fn font_height(&self, fonts: &epaint::Fonts, style: &Style) -> f32 { match self { - Self::Text(_) => fonts.row_height(&FontSelection::Default.resolve(style)), + Self::Text(_) => fonts.row_height(&TextStyle::Body.resolve(style)), Self::RichText(text) => text.font_height(fonts, style), Self::LayoutJob(job) => job.font_height(fonts), Self::Galley(galley) => { @@ -686,9 +686,10 @@ impl WidgetText { default_valign: Align, ) -> Arc { match self { - Self::Text(text) => Arc::new(LayoutJob::single_section( + Self::Text(text) => Arc::new(LayoutJob::simple_singleline( text, - crate::text::TextFormat::default(), + TextStyle::Body.resolve(style), + crate::Color32::PLACEHOLDER, )), Self::RichText(text) => Arc::new(Arc::unwrap_or_clone(text).into_layout_job( style, @@ -729,8 +730,11 @@ impl WidgetText { ) -> Arc { match self { Self::Text(text) => { - let mut layout_job = - LayoutJob::single_section(text, crate::text::TextFormat::default()); + let mut layout_job = LayoutJob::simple_singleline( + text, + TextStyle::Body.resolve(style), + crate::Color32::PLACEHOLDER, + ); layout_job.wrap = text_wrapping; ctx.fonts(|f| f.layout_job(layout_job)) } From 13761abcf6c8897817f8126257c65c0dc22d0150 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 15:07:34 +0200 Subject: [PATCH 07/10] Heed `override_font_id` and `override_text_style` --- crates/egui/src/widget_text.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 8a08a7042798..01209d341700 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -666,7 +666,7 @@ impl WidgetText { /// Returns a value rounded to [`emath::GUI_ROUNDING`]. pub(crate) fn font_height(&self, fonts: &epaint::Fonts, style: &Style) -> f32 { match self { - Self::Text(_) => fonts.row_height(&TextStyle::Body.resolve(style)), + Self::Text(_) => fonts.row_height(&FontSelection::Default.resolve(style)), Self::RichText(text) => text.font_height(fonts, style), Self::LayoutJob(job) => job.font_height(fonts), Self::Galley(galley) => { @@ -688,7 +688,7 @@ impl WidgetText { match self { Self::Text(text) => Arc::new(LayoutJob::simple_singleline( text, - TextStyle::Body.resolve(style), + FontSelection::Default.resolve(style), crate::Color32::PLACEHOLDER, )), Self::RichText(text) => Arc::new(Arc::unwrap_or_clone(text).into_layout_job( @@ -732,7 +732,7 @@ impl WidgetText { Self::Text(text) => { let mut layout_job = LayoutJob::simple_singleline( text, - TextStyle::Body.resolve(style), + FontSelection::Default.resolve(style), crate::Color32::PLACEHOLDER, ); layout_job.wrap = text_wrapping; From e00c0ec392ef8ed966ec4c3ee8560c877d1be2f4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 15:09:42 +0200 Subject: [PATCH 08/10] Fix `map_rich_text` --- crates/egui/src/widget_text.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 01209d341700..4fd4d03c2f1e 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -558,10 +558,10 @@ impl WidgetText { { match self { Self::Text(text) => f(RichText::new(text)).into(), - Self::RichText(mut text) => { - let a = Arc::make_mut(&mut text); - *a = f(std::mem::take(&mut *a)); - Self::RichText(text) + Self::RichText(text) => { + let mut text = Arc::unwrap_or_clone(text); + text = f(text); + Self::RichText(text.into()) } other => other, } From a3009a0ffc316bafb31a60ab3d32984cfa1c4e33 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 15:19:28 +0200 Subject: [PATCH 09/10] Cleanup --- crates/egui/src/widget_text.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 4fd4d03c2f1e..45f83d2db3de 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -552,17 +552,14 @@ impl WidgetText { /// - [`Self::Text`] => convert to [`RichText`] and call f /// - [`Self::RichText`] => call f /// - else do nothing + #[must_use] fn map_rich_text(self, f: F) -> Self where F: FnOnce(RichText) -> RichText, { match self { - Self::Text(text) => f(RichText::new(text)).into(), - Self::RichText(text) => { - let mut text = Arc::unwrap_or_clone(text); - text = f(text); - Self::RichText(text.into()) - } + Self::Text(text) => Self::RichText(Arc::new(f(RichText::new(text)))), + Self::RichText(text) => Self::RichText(Arc::new(f(Arc::unwrap_or_clone(text)))), other => other, } } From 18eae419a9dc9f45ae577271e9f72e37e43900f0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 6 May 2025 15:31:04 +0200 Subject: [PATCH 10/10] Fix valign --- crates/egui/src/widget_text.rs | 21 +++++++++++++++------ crates/epaint/src/text/text_layout_types.rs | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index 45f83d2db3de..d9f98859b5c8 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -1,6 +1,7 @@ use std::{borrow::Cow, sync::Arc}; use emath::GuiRounding as _; +use epaint::text::TextFormat; use crate::{ text::{LayoutJob, TextWrapping}, @@ -683,10 +684,14 @@ impl WidgetText { default_valign: Align, ) -> Arc { match self { - Self::Text(text) => Arc::new(LayoutJob::simple_singleline( + Self::Text(text) => Arc::new(LayoutJob::simple_format( text, - FontSelection::Default.resolve(style), - crate::Color32::PLACEHOLDER, + TextFormat { + font_id: FontSelection::Default.resolve(style), + color: crate::Color32::PLACEHOLDER, + valign: default_valign, + ..Default::default() + }, )), Self::RichText(text) => Arc::new(Arc::unwrap_or_clone(text).into_layout_job( style, @@ -727,10 +732,14 @@ impl WidgetText { ) -> Arc { match self { Self::Text(text) => { - let mut layout_job = LayoutJob::simple_singleline( + let mut layout_job = LayoutJob::simple_format( text, - FontSelection::Default.resolve(style), - crate::Color32::PLACEHOLDER, + TextFormat { + font_id: FontSelection::Default.resolve(style), + color: crate::Color32::PLACEHOLDER, + valign: default_valign, + ..Default::default() + }, ); layout_job.wrap = text_wrapping; ctx.fonts(|f| f.layout_job(layout_job)) diff --git a/crates/epaint/src/text/text_layout_types.rs b/crates/epaint/src/text/text_layout_types.rs index 49ec2908745d..795b9c9f453e 100644 --- a/crates/epaint/src/text/text_layout_types.rs +++ b/crates/epaint/src/text/text_layout_types.rs @@ -118,6 +118,21 @@ impl LayoutJob { } } + /// Break on `\n` + #[inline] + pub fn simple_format(text: String, format: TextFormat) -> Self { + Self { + sections: vec![LayoutSection { + leading_space: 0.0, + byte_range: 0..text.len(), + format, + }], + text, + break_on_newline: true, + ..Default::default() + } + } + /// Does not break on `\n`, but shows the replacement character instead. #[inline] pub fn simple_singleline(text: String, font_id: FontId, color: Color32) -> Self {