Add Auto strategy to text::Shaping

This commit is contained in:
Héctor Ramón Jiménez 2025-08-30 18:15:12 +02:00
parent d31a7b6ae8
commit bc7d64987e
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 47 additions and 11 deletions

View file

@ -69,6 +69,10 @@ advanced = ["iced_core/advanced", "iced_widget/advanced"]
fira-sans = ["iced_renderer/fira-sans"] fira-sans = ["iced_renderer/fira-sans"]
# Auto-detects light/dark mode for the built-in theme # Auto-detects light/dark mode for the built-in theme
auto-detect-theme = ["iced_core/auto-detect-theme"] auto-detect-theme = ["iced_core/auto-detect-theme"]
# Enables basic text shaping by default
basic-shaping = ["iced_core/basic-shaping"]
# Enables advanced text shaping by default
advanced-shaping = ["iced_core/advanced-shaping"]
# Enables strict assertions for debugging purposes at the expense of performance # Enables strict assertions for debugging purposes at the expense of performance
strict-assertions = ["iced_renderer/strict-assertions"] strict-assertions = ["iced_renderer/strict-assertions"]
# Redraws on every runtime event, and not only when a widget requests it # Redraws on every runtime event, and not only when a widget requests it

View file

@ -17,6 +17,8 @@ workspace = true
auto-detect-theme = ["dep:dark-light"] auto-detect-theme = ["dep:dark-light"]
advanced = [] advanced = []
crisp = [] crisp = []
basic-shaping = []
advanced-shaping = []
[dependencies] [dependencies]
bitflags.workspace = true bitflags.workspace = true

View file

@ -130,8 +130,17 @@ impl From<Alignment> for alignment::Horizontal {
} }
/// The shaping strategy of some text. /// The shaping strategy of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Shaping { pub enum Shaping {
/// Auto-detect the best shaping strategy from the text.
///
/// This strategy will use [`Basic`](Self::Basic) shaping if the
/// text consists of only ASCII characters; otherwise, it will
/// use [`Advanced`](Self::Advanced) shaping.
///
/// This is the default, if neither the `basic-shaping` nor `advanced-shaping`
/// features are enabled.
Auto,
/// No shaping and no font fallback. /// No shaping and no font fallback.
/// ///
/// This shaping strategy is very cheap, but it will not display complex /// This shaping strategy is very cheap, but it will not display complex
@ -140,8 +149,8 @@ pub enum Shaping {
/// You should use this strategy when you have complete control of the text /// You should use this strategy when you have complete control of the text
/// and the font you are displaying in your application. /// and the font you are displaying in your application.
/// ///
/// This is the default. /// This will be the default if the `basic-shaping` feature is enabled and
#[default] /// the `advanced-shaping` feature is disabled.
Basic, Basic,
/// Advanced text shaping and font fallback. /// Advanced text shaping and font fallback.
/// ///
@ -150,9 +159,23 @@ pub enum Shaping {
/// may be needed to display all of the glyphs. /// may be needed to display all of the glyphs.
/// ///
/// Advanced shaping is expensive! You should only enable it when necessary. /// Advanced shaping is expensive! You should only enable it when necessary.
///
/// This will be the default if the `advanced-shaping` feature is enabled.
Advanced, Advanced,
} }
impl Default for Shaping {
fn default() -> Self {
if cfg!(feature = "advanced-shaping") {
Self::Advanced
} else if cfg!(feature = "basic-shaping") {
Self::Basic
} else {
Self::Auto
}
}
}
/// The wrapping strategy of some text. /// The wrapping strategy of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Wrapping { pub enum Wrapping {

View file

@ -94,14 +94,14 @@ impl Layout {
let controls = row([ let controls = row([
(!self.example.is_first()).then_some( (!self.example.is_first()).then_some(
button(text("← Previous").shaping(text::Shaping::Advanced)) button(text("← Previous"))
.padding([5, 10]) .padding([5, 10])
.on_press(Message::Previous) .on_press(Message::Previous)
.into(), .into(),
), ),
Some(horizontal_space().into()), Some(horizontal_space().into()),
(!self.example.is_last()).then_some( (!self.example.is_last()).then_some(
button(text("Next →").shaping(text::Shaping::Advanced)) button(text("Next →"))
.padding([5, 10]) .padding([5, 10])
.on_press(Message::Next) .on_press(Message::Next)
.into(), .into(),
@ -313,7 +313,7 @@ fn quotes<'a>() -> Element<'a, Message> {
"This is another reply", "This is another reply",
), ),
horizontal_rule(1), horizontal_rule(1),
text("A separator ↑").shaping(text::Shaping::Advanced), text("A separator ↑"),
] ]
.width(Shrink) .width(Shrink)
.spacing(10) .spacing(10)

View file

@ -1 +1 @@
0650eb2c27c21c5d48e1e00031a52d8471d8a3b4e827ad502c4628914f5c1c13 129523830df064908cfa911214ba61dadc31d8975425ba3efaae69da9514a3d0

View file

@ -323,8 +323,15 @@ fn to_align(alignment: Alignment) -> Option<cosmic_text::Align> {
} }
/// Converts some [`Shaping`] strategy to a [`cosmic_text::Shaping`] strategy. /// Converts some [`Shaping`] strategy to a [`cosmic_text::Shaping`] strategy.
pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { pub fn to_shaping(shaping: Shaping, text: &str) -> cosmic_text::Shaping {
match shaping { match shaping {
Shaping::Auto => {
if text.is_ascii() {
cosmic_text::Shaping::Basic
} else {
cosmic_text::Shaping::Advanced
}
}
Shaping::Basic => cosmic_text::Shaping::Basic, Shaping::Basic => cosmic_text::Shaping::Basic,
Shaping::Advanced => cosmic_text::Shaping::Advanced, Shaping::Advanced => cosmic_text::Shaping::Advanced,
} }

View file

@ -55,7 +55,7 @@ impl Cache {
font_system, font_system,
key.content, key.content,
&text::to_attributes(key.font), &text::to_attributes(key.font),
text::to_shaping(key.shaping), text::to_shaping(key.shaping, key.content),
); );
let bounds = text::align(&mut buffer, font_system, key.align_x); let bounds = text::align(&mut buffer, font_system, key.align_x);

View file

@ -88,7 +88,7 @@ impl core::text::Paragraph for Paragraph {
font_system.raw(), font_system.raw(),
text.content, text.content,
&text::to_attributes(text.font), &text::to_attributes(text.font),
text::to_shaping(text.shaping), text::to_shaping(text.shaping, text.content),
); );
let min_bounds = let min_bounds =
@ -158,7 +158,7 @@ impl core::text::Paragraph for Paragraph {
(span.text.as_ref(), attrs.metadata(i)) (span.text.as_ref(), attrs.metadata(i))
}), }),
&text::to_attributes(text.font), &text::to_attributes(text.font),
text::to_shaping(text.shaping), cosmic_text::Shaping::Advanced,
None, None,
); );